From dfa8dc0cebb0a2b995612c85ff6f8127ba9758f8 Mon Sep 17 00:00:00 2001 From: "us341@nyu.edu" Date: Sun, 5 Oct 2014 21:09:18 -0400 Subject: [PATCH 01/23] updated http_Server --- httpserver.r2py | 103 ++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 61 deletions(-) diff --git a/httpserver.r2py b/httpserver.r2py index 79abfe4..661832a 100644 --- a/httpserver.r2py +++ b/httpserver.r2py @@ -131,22 +131,12 @@ def httpserver_registercallback(addresstuple, cbfunc): try: newhttpdid = uniqueid_getid() - # Keep track of this server's id in a closure: def _httpserver_cbclosure(remoteip, remoteport, sock, ch, listench): # Do the actual processing on the request. _httpserver_socketcb(remoteip, remoteport, sock, ch, listench, \ newhttpdid) - - # Close the socket afterwards. - try: - sock.close() - except Exception, e: - if "socket" not in str(e).lower(): - raise - pass # Best effort. - - + sock.close() _httpserver_context['handles'][newhttpdid] = \ waitforconn(addresstuple[0], addresstuple[1], _httpserver_cbclosure) _httpserver_context['cbfuncs'][newhttpdid] = cbfunc @@ -223,15 +213,7 @@ def _httpserver_socketcb(remoteip, remoteport, sock, ch, listench, httpdid): # Not much else we can do. break - except Exception, e: - if "Socket closed" in str(e): - break - - # We shouldn't encounter these, other than 'Socket closed' ones. They - # represent a bug in our code somewhere. However, not raising the - # exception makes HTTP server software incredibly unintuitive to - # debug. - raise + @@ -313,40 +295,42 @@ def _httpserver_parseHTTPheader(headerdatalist): def _httpserver_sendAll(sock, datastr, besteffort=False): - # Sends all the data in datastr to sock. If besteffort is True, - # we don't care if it fails or not. - try: - while len(datastr) > 0: - datastr = datastr[sock.send(datastr):] - except Exception, e: - if "socket" not in str(e).lower(): - raise - - # If the caller didn't want this function to raise an exception for - # any reason, we don't, and instead return silently. If they are ok - # with exceptions, we re-raise. - if not besteffort: - raise + + sent = 0 + while sent < len(datastr): + try: + sent += sock.send(data[sent:]) + except SocketWouldBlockError: + # retry if response hasn't been sent yet + sleep(.05) + continue + except SocketClosedRemote: + log('client from',srcip,'aborted before response could be sent...\n') + return + def _httpserver_getline(sock, datastr): # Reads a line out of datastr (if possible), or failing that, gets more from - # the socket. Returns (line, extra). - - try: - newdatastr = "" - while True: - endloc = datastr.find("\n", -len(newdatastr)) - if endloc != -1: - return (datastr[:endloc], datastr[endloc+1:]) + # the socket. Returns (line, extra) + newdatastr = "" + while True: + endloc = datastr.find("\n", -len(newdatastr)) + if endloc != -1: + return (datastr[:endloc], datastr[endloc+1:]) + try: newdatastr = sock.recv(4096) - datastr += newdatastr - except Exception, e: - if "Socket closed" in str(e) and len(datastr) != 0: + except SocketWouldBlockError: + # retry if they haven't completed sending the header + sleep(.05) + continue + except SocketClosedRemote: + log('socket is closed before operation completion...\n') return (datastr, "") - raise + datastr += newdatastr + @@ -354,16 +338,20 @@ def _httpserver_getline(sock, datastr): def _httpserver_getblock(blocksize, sock, datastr): # Reads a block of size blocksize out of datastr (if possible), or failing # that, gets more from the socket. Returns (block, extra). - - try: - while len(datastr) < blocksize: + + while len(datastr) < blocksize: + try: datastr += sock.recv(4096) - - return (datastr[:blocksize], datastr[blocksize:]) - except Exception, e: - if "Socket closed" in str(e) and len(datastr) != 0: + except SocketWouldBlockError: + # retry if they haven't completed sending the header + sleep(.05) + continue + except SocketClosedRemote: + log('socket is closed before operation completion...\n') return (datastr, "") - raise + return (datastr[:blocksize], datastr[blocksize:]) + + @@ -897,13 +885,6 @@ def _httpserver_process_single_request(sock, cbfunc, extradata, httpdid, \ # the client using HTTP/1.1 chunked encoding. _httpserver_sendfile_chunked(sock, messagestream) - except Exception, e: - if "socket" not in str(e).lower(): - raise - - # The exception we're trying to catch here is anything sock.send() - # raises. However, it just raises plain exceptions. - # The reason we care about the data actually going through for HTTP/1.1 # is that we keep connections open. If there is an error, we shouldn't # keep going, so we indicate that the socket should be closed. From 3c41e49dc0404f33d4c98f8d55f842e8c8d2e911 Mon Sep 17 00:00:00 2001 From: us341 Date: Mon, 6 Oct 2014 10:51:31 -0400 Subject: [PATCH 02/23] Update httpserver.r2py --- httpserver.r2py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/httpserver.r2py b/httpserver.r2py index 661832a..7a82fac 100644 --- a/httpserver.r2py +++ b/httpserver.r2py @@ -297,16 +297,16 @@ def _httpserver_parseHTTPheader(headerdatalist): def _httpserver_sendAll(sock, datastr, besteffort=False): sent = 0 - while sent < len(datastr): - try: - sent += sock.send(data[sent:]) - except SocketWouldBlockError: - # retry if response hasn't been sent yet - sleep(.05) - continue - except SocketClosedRemote: - log('client from',srcip,'aborted before response could be sent...\n') - return + while sent < len(datastr): + try: + sent += sock.send(data[sent:]) + except SocketWouldBlockError: + # retry if response hasn't been sent yet + sleep(.05) + continue + except SocketClosedRemote: + log('client from',srcip,'aborted before response could be sent...\n') + return From 61529337f1dc6c67438610e282bfe15356e908e2 Mon Sep 17 00:00:00 2001 From: us341 Date: Thu, 9 Oct 2014 16:58:44 -0400 Subject: [PATCH 03/23] Update httpserver.r2py --- httpserver.r2py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/httpserver.r2py b/httpserver.r2py index 7a82fac..f1fbca6 100644 --- a/httpserver.r2py +++ b/httpserver.r2py @@ -28,7 +28,7 @@ dy_import_module_symbols("httpretrieve.r2py") -class _httpserver_ClientClosedSockEarly(Exception): +class _httpserver_ClientClosedSockEarly(RepyException): # Raised internally when the client unexpectedly closes the socket. The # correct behavior in this instance is to clean up that handler and # continue. @@ -37,14 +37,14 @@ class _httpserver_ClientClosedSockEarly(Exception): -class _httpserver_BadRequest(Exception): +class _httpserver_BadRequest(RepyException): # Raised internally when the client's request is malformed. pass -class _httpserver_ServerError(Exception): +class _httpserver_ServerError(RepyException): # Raised internally when the callback function unexpectedly raises an # exception. pass @@ -52,7 +52,7 @@ class _httpserver_ServerError(Exception): -class _httpserver_BadTransferCoding(Exception): +class _httpserver_BadTransferCoding(RepyException): # Raised internally when the request's encoding is something we can't # handle (most everything at the time of writing). pass @@ -299,7 +299,7 @@ def _httpserver_sendAll(sock, datastr, besteffort=False): sent = 0 while sent < len(datastr): try: - sent += sock.send(data[sent:]) + sent += sock.send(datastr[sent:]) except SocketWouldBlockError: # retry if response hasn't been sent yet sleep(.05) @@ -877,18 +877,18 @@ def _httpserver_process_single_request(sock, cbfunc, extradata, httpdid, \ reqinfo['headers']["Connection"]): closeconn = True - try: - # Send response headers. - _httpserver_sendAll(sock, response) + + # Send response headers. + _httpserver_sendAll(sock, response) - # Read chunks from the callback and efficiently send them to - # the client using HTTP/1.1 chunked encoding. - _httpserver_sendfile_chunked(sock, messagestream) + # Read chunks from the callback and efficiently send them to + # the client using HTTP/1.1 chunked encoding. + _httpserver_sendfile_chunked(sock, messagestream) - # The reason we care about the data actually going through for HTTP/1.1 - # is that we keep connections open. If there is an error, we shouldn't - # keep going, so we indicate that the socket should be closed. - closeconn = True + # The reason we care about the data actually going through for HTTP/1.1 + # is that we keep connections open. If there is an error, we shouldn't + # keep going, so we indicate that the socket should be closed. + closeconn = True else: # If the cbfunc's response dictionary didn't specify 0.9, 1.0, or 1.1, From 021b28f15d705103c6b27f6ffb2e3baaf0fd6c7f Mon Sep 17 00:00:00 2001 From: us341 Date: Thu, 16 Oct 2014 11:59:44 -0400 Subject: [PATCH 04/23] Create test_httpserver.r2py test file for httpserver.r2py --- test/test_httpserver.r2py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 test/test_httpserver.r2py diff --git a/test/test_httpserver.r2py b/test/test_httpserver.r2py new file mode 100644 index 0000000..c60c673 --- /dev/null +++ b/test/test_httpserver.r2py @@ -0,0 +1,38 @@ +dy_import_module_symbols("httpserver.r2py") + + +# prints failed message if the test failes and raises an exception the registorhttpcallback +# or httpretrieve raises an exception and just excutes if the test passes + + +def test_normal_server(httprequest_dictionary): + # normal server just sends a message + + # store the http dictionary to check the content + mycontext['httprequest_dictionary'] = httprequest_dictionary + dict_toreturn = { + 'version': '1.1', + 'statuscode': 101, + 'statusmsg': "valid", + 'headers': { 'X-Header-Foo': 'Bar' }, + 'message': "this is original message" + } + return dict_toreturn + + +if callfunc == 'initialize': + # used to store the httprequest_dictionary from server + mycontext['httprequest_dictionary'] = {} + + # used to send post data using the httpretrieve client + http_query = {"first": "1st", "second": "2nd"} + http_post = {"third": "3rd", "fourth": "4th"} + + + # register the callback server + try: + handle = httpserver_registercallback(('192.168.1.6',12345), test_normal_server) + except Exception, e: + raise Exception('failed test: server raised an exception: ' + str(e)) + + From 0e3ef07f7d2e129a51c5cfa63efeea2ae494c0a5 Mon Sep 17 00:00:00 2001 From: us341 Date: Thu, 16 Oct 2014 12:00:28 -0400 Subject: [PATCH 05/23] Update test_httpserver.r2py --- test/test_httpserver.r2py | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/test_httpserver.r2py b/test/test_httpserver.r2py index c60c673..fb6bccc 100644 --- a/test/test_httpserver.r2py +++ b/test/test_httpserver.r2py @@ -1,9 +1,6 @@ dy_import_module_symbols("httpserver.r2py") -# prints failed message if the test failes and raises an exception the registorhttpcallback -# or httpretrieve raises an exception and just excutes if the test passes - def test_normal_server(httprequest_dictionary): # normal server just sends a message From aa0139078b226901c116cb3726962b4642ee4263 Mon Sep 17 00:00:00 2001 From: us341 Date: Sat, 18 Oct 2014 22:58:51 -0400 Subject: [PATCH 06/23] Delete test_httpserver.r2py --- test/test_httpserver.r2py | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 test/test_httpserver.r2py diff --git a/test/test_httpserver.r2py b/test/test_httpserver.r2py deleted file mode 100644 index fb6bccc..0000000 --- a/test/test_httpserver.r2py +++ /dev/null @@ -1,35 +0,0 @@ -dy_import_module_symbols("httpserver.r2py") - - - -def test_normal_server(httprequest_dictionary): - # normal server just sends a message - - # store the http dictionary to check the content - mycontext['httprequest_dictionary'] = httprequest_dictionary - dict_toreturn = { - 'version': '1.1', - 'statuscode': 101, - 'statusmsg': "valid", - 'headers': { 'X-Header-Foo': 'Bar' }, - 'message': "this is original message" - } - return dict_toreturn - - -if callfunc == 'initialize': - # used to store the httprequest_dictionary from server - mycontext['httprequest_dictionary'] = {} - - # used to send post data using the httpretrieve client - http_query = {"first": "1st", "second": "2nd"} - http_post = {"third": "3rd", "fourth": "4th"} - - - # register the callback server - try: - handle = httpserver_registercallback(('192.168.1.6',12345), test_normal_server) - except Exception, e: - raise Exception('failed test: server raised an exception: ' + str(e)) - - From 2b0b6d297dd1aa8fd6a4bb4103cf6162fcff5e75 Mon Sep 17 00:00:00 2001 From: us341 Date: Sat, 18 Oct 2014 23:03:07 -0400 Subject: [PATCH 07/23] Create ut_seattlelib_httpserver.r2py unit test for httpserver.r2py --- tests/ut_seattlelib_httpserver.r2py | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/ut_seattlelib_httpserver.r2py diff --git a/tests/ut_seattlelib_httpserver.r2py b/tests/ut_seattlelib_httpserver.r2py new file mode 100644 index 0000000..c60c673 --- /dev/null +++ b/tests/ut_seattlelib_httpserver.r2py @@ -0,0 +1,38 @@ +dy_import_module_symbols("httpserver.r2py") + + +# prints failed message if the test failes and raises an exception the registorhttpcallback +# or httpretrieve raises an exception and just excutes if the test passes + + +def test_normal_server(httprequest_dictionary): + # normal server just sends a message + + # store the http dictionary to check the content + mycontext['httprequest_dictionary'] = httprequest_dictionary + dict_toreturn = { + 'version': '1.1', + 'statuscode': 101, + 'statusmsg': "valid", + 'headers': { 'X-Header-Foo': 'Bar' }, + 'message': "this is original message" + } + return dict_toreturn + + +if callfunc == 'initialize': + # used to store the httprequest_dictionary from server + mycontext['httprequest_dictionary'] = {} + + # used to send post data using the httpretrieve client + http_query = {"first": "1st", "second": "2nd"} + http_post = {"third": "3rd", "fourth": "4th"} + + + # register the callback server + try: + handle = httpserver_registercallback(('192.168.1.6',12345), test_normal_server) + except Exception, e: + raise Exception('failed test: server raised an exception: ' + str(e)) + + From 31dc69e543edb354b2a6500f5ebd5cfc25ba6877 Mon Sep 17 00:00:00 2001 From: us341 Date: Sat, 18 Oct 2014 23:18:29 -0400 Subject: [PATCH 08/23] Update ut_seattlelib_httpserver.r2py --- tests/ut_seattlelib_httpserver.r2py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ut_seattlelib_httpserver.r2py b/tests/ut_seattlelib_httpserver.r2py index c60c673..233fd02 100644 --- a/tests/ut_seattlelib_httpserver.r2py +++ b/tests/ut_seattlelib_httpserver.r2py @@ -1,5 +1,5 @@ -dy_import_module_symbols("httpserver.r2py") +httpserver = dy_import_module("httpserver.r2py") # prints failed message if the test failes and raises an exception the registorhttpcallback # or httpretrieve raises an exception and just excutes if the test passes @@ -31,7 +31,7 @@ if callfunc == 'initialize': # register the callback server try: - handle = httpserver_registercallback(('192.168.1.6',12345), test_normal_server) + handle = httpserver.httpserver_registercallback(('192.168.1.6',12345), test_normal_server) except Exception, e: raise Exception('failed test: server raised an exception: ' + str(e)) From b7418fe7f3574012cec443eadd43f6d73d85f5f2 Mon Sep 17 00:00:00 2001 From: us341 Date: Sat, 18 Oct 2014 23:35:05 -0400 Subject: [PATCH 09/23] Update ut_seattlelib_httpserver.r2py --- tests/ut_seattlelib_httpserver.r2py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ut_seattlelib_httpserver.r2py b/tests/ut_seattlelib_httpserver.r2py index 233fd02..3ef1f52 100644 --- a/tests/ut_seattlelib_httpserver.r2py +++ b/tests/ut_seattlelib_httpserver.r2py @@ -1,3 +1,5 @@ +#pragma repy restrictions.default dylink.r2py +#pragma out httpserver = dy_import_module("httpserver.r2py") From 7322817c76f784139dc65068e2303dbd85ba9292 Mon Sep 17 00:00:00 2001 From: us341 Date: Sat, 18 Oct 2014 23:52:18 -0400 Subject: [PATCH 10/23] Update ut_seattlelib_httpserver.r2py --- tests/ut_seattlelib_httpserver.r2py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ut_seattlelib_httpserver.r2py b/tests/ut_seattlelib_httpserver.r2py index 3ef1f52..da99acc 100644 --- a/tests/ut_seattlelib_httpserver.r2py +++ b/tests/ut_seattlelib_httpserver.r2py @@ -33,7 +33,7 @@ if callfunc == 'initialize': # register the callback server try: - handle = httpserver.httpserver_registercallback(('192.168.1.6',12345), test_normal_server) + handle = httpserver.httpserver_registercallback((getmyip(),12345), test_normal_server) except Exception, e: raise Exception('failed test: server raised an exception: ' + str(e)) From 3b8e34bf7d8d1dd13e5675c99968b6c9ac557edf Mon Sep 17 00:00:00 2001 From: us341 Date: Sun, 19 Oct 2014 00:20:10 -0400 Subject: [PATCH 11/23] Update ut_seattlelib_httpserver.r2py --- tests/ut_seattlelib_httpserver.r2py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ut_seattlelib_httpserver.r2py b/tests/ut_seattlelib_httpserver.r2py index da99acc..e224279 100644 --- a/tests/ut_seattlelib_httpserver.r2py +++ b/tests/ut_seattlelib_httpserver.r2py @@ -36,5 +36,7 @@ if callfunc == 'initialize': handle = httpserver.httpserver_registercallback((getmyip(),12345), test_normal_server) except Exception, e: raise Exception('failed test: server raised an exception: ' + str(e)) + + exitall() From 71aa32d28df32ecacb717ab5579bac7230b5d5bc Mon Sep 17 00:00:00 2001 From: us341 Date: Sun, 19 Oct 2014 00:27:17 -0400 Subject: [PATCH 12/23] Update ut_seattlelib_httpserver.r2py --- tests/ut_seattlelib_httpserver.r2py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/ut_seattlelib_httpserver.r2py b/tests/ut_seattlelib_httpserver.r2py index e224279..a3f2528 100644 --- a/tests/ut_seattlelib_httpserver.r2py +++ b/tests/ut_seattlelib_httpserver.r2py @@ -3,9 +3,6 @@ httpserver = dy_import_module("httpserver.r2py") -# prints failed message if the test failes and raises an exception the registorhttpcallback -# or httpretrieve raises an exception and just excutes if the test passes - def test_normal_server(httprequest_dictionary): # normal server just sends a message From b21fca2bf45b045b9b670e0ed38d36f455d2d35e Mon Sep 17 00:00:00 2001 From: us341 Date: Wed, 22 Oct 2014 12:40:46 -0400 Subject: [PATCH 13/23] removing #pragma out from file --- tests/ut_seattlelib_httpserver.r2py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/tests/ut_seattlelib_httpserver.r2py b/tests/ut_seattlelib_httpserver.r2py index a3f2528..5b75185 100644 --- a/tests/ut_seattlelib_httpserver.r2py +++ b/tests/ut_seattlelib_httpserver.r2py @@ -1,12 +1,10 @@ #pragma repy restrictions.default dylink.r2py -#pragma out - -httpserver = dy_import_module("httpserver.r2py") +dy_import_module_symbols("httpserver.r2py") +# this method will work as callback function for httpserver_registercallback in httpserver.r2py def test_normal_server(httprequest_dictionary): # normal server just sends a message - # store the http dictionary to check the content mycontext['httprequest_dictionary'] = httprequest_dictionary dict_toreturn = { @@ -23,17 +21,10 @@ if callfunc == 'initialize': # used to store the httprequest_dictionary from server mycontext['httprequest_dictionary'] = {} - # used to send post data using the httpretrieve client - http_query = {"first": "1st", "second": "2nd"} - http_post = {"third": "3rd", "fourth": "4th"} - - # register the callback server try: - handle = httpserver.httpserver_registercallback((getmyip(),12345), test_normal_server) + handle = httpserver_registercallback((getmyip(),12345), test_normal_server) except Exception, e: raise Exception('failed test: server raised an exception: ' + str(e)) - - exitall() From 6a091968919c86bbbbb144f76854717e70f60fa2 Mon Sep 17 00:00:00 2001 From: us341 Date: Wed, 22 Oct 2014 12:42:52 -0400 Subject: [PATCH 14/23] Updated doc string Updated doc string to have some more info --- httpserver.r2py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/httpserver.r2py b/httpserver.r2py index f1fbca6..ca24ce7 100644 --- a/httpserver.r2py +++ b/httpserver.r2py @@ -8,6 +8,12 @@ Conrad Meyer + + Oct 22, 2014 + + + Urvashi Soni + This is a library that abstracts away the details of the HTTP protocol, instead calling a user-supplied function on each request. The return From 2b2a18e24d7f10d1787353839f0eac8097a00bf6 Mon Sep 17 00:00:00 2001 From: us341 Date: Wed, 22 Oct 2014 12:48:25 -0400 Subject: [PATCH 15/23] Modified doc String to include purpose of updation --- httpserver.r2py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/httpserver.r2py b/httpserver.r2py index ca24ce7..c705ee4 100644 --- a/httpserver.r2py +++ b/httpserver.r2py @@ -19,6 +19,9 @@ instead calling a user-supplied function on each request. The return value of the user-supplied function determines the response that is sent to the HTTP client. + + This file is updated to make it appropriate to be used for Repy V2. The code + changes include Exception handling correction and other functio changes. """ From ca848b78634ad37d8ea396fde4b7b22671225d2f Mon Sep 17 00:00:00 2001 From: us341 Date: Wed, 22 Oct 2014 13:30:02 -0400 Subject: [PATCH 16/23] added exitall() to unit test --- tests/ut_seattlelib_httpserver.r2py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ut_seattlelib_httpserver.r2py b/tests/ut_seattlelib_httpserver.r2py index 5b75185..fe15a07 100644 --- a/tests/ut_seattlelib_httpserver.r2py +++ b/tests/ut_seattlelib_httpserver.r2py @@ -28,3 +28,4 @@ if callfunc == 'initialize': raise Exception('failed test: server raised an exception: ' + str(e)) + exitall() From 8e040c205d06d59fe4f12adbfc488ddafc317f46 Mon Sep 17 00:00:00 2001 From: us341 Date: Mon, 10 Nov 2014 11:26:04 -0500 Subject: [PATCH 17/23] Changed dy_import_module_symbols to dy_link_module httpretrieve.r2py is left intentionaly as dylink.r2py needs some ammendment --- httpserver.r2py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/httpserver.r2py b/httpserver.r2py index c705ee4..641af62 100644 --- a/httpserver.r2py +++ b/httpserver.r2py @@ -9,7 +9,7 @@ Conrad Meyer - Oct 22, 2014 + Nov 10, 2014 Urvashi Soni @@ -19,19 +19,16 @@ instead calling a user-supplied function on each request. The return value of the user-supplied function determines the response that is sent to the HTTP client. - - This file is updated to make it appropriate to be used for Repy V2. The code - changes include Exception handling correction and other functio changes. """ -dy_import_module_symbols("librepy.r2py") -dy_import_module_symbols("urllib.r2py") -dy_import_module_symbols("urlparse.r2py") -dy_import_module_symbols("uniqueid.r2py") -dy_import_module_symbols("sockettimeout.r2py") +librepy = dy_import_module("librepy.r2py") +urllib = dy_import_module("urllib.r2py") +urlparse = dy_import_module("urlparse.r2py") +uniqueid = dy_import_module("uniqueid.r2py") +sockettimeout = dy_import_module("sockettimeout.r2py") dy_import_module_symbols("httpretrieve.r2py") @@ -139,15 +136,17 @@ def httpserver_registercallback(addresstuple, cbfunc): _httpserver_context['lock'].acquire(True) try: - newhttpdid = uniqueid_getid() + newhttpdid = uniqueid.uniqueid_getid() + # Keep track of this server's id in a closure: def _httpserver_cbclosure(remoteip, remoteport, sock, ch, listench): # Do the actual processing on the request. _httpserver_socketcb(remoteip, remoteport, sock, ch, listench, \ newhttpdid) - sock.close() + sock.close() + _httpserver_context['handles'][newhttpdid] = \ - waitforconn(addresstuple[0], addresstuple[1], _httpserver_cbclosure) + librepy.waitforconn(addresstuple[0], addresstuple[1], _httpserver_cbclosure) _httpserver_context['cbfuncs'][newhttpdid] = cbfunc return newhttpdid @@ -288,12 +287,12 @@ def _httpserver_parseHTTPheader(headerdatalist): infodict['querystr'] = None try: - infodict['headers'] = _httpretrieve_parse_responseheaders(otherheaderslist) + infodict['headers'] = _httpretrieve_parse_responseheaders(otherheaderslist) except HttpBrokenServerError: raise _httpserver_BadRequest("Request headers are misformed.") try: - infodict['querydict'] = urllib_unquote_parameters(infodict['querystr']) + infodict['querydict'] = urllib.urllib_unquote_parameters(infodict['querystr']) except (ValueError, AttributeError, TypeError): infodict['querydict'] = None From 4078ce0d054613205efd3850548cf05f48d583f4 Mon Sep 17 00:00:00 2001 From: us341 Date: Mon, 10 Nov 2014 11:28:38 -0500 Subject: [PATCH 18/23] added client for unit test, changed pragma to restrictions.threeports restrictions.threeports is added in place of restrictions.default as two different ports were needed for callback method hosted on server and client --- tests/ut_seattlelib_httpserver.r2py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/ut_seattlelib_httpserver.r2py b/tests/ut_seattlelib_httpserver.r2py index fe15a07..73dbf1e 100644 --- a/tests/ut_seattlelib_httpserver.r2py +++ b/tests/ut_seattlelib_httpserver.r2py @@ -1,4 +1,4 @@ -#pragma repy restrictions.default dylink.r2py +#pragma repy restrictions.threeports dylink.r2py dy_import_module_symbols("httpserver.r2py") @@ -16,6 +16,11 @@ def test_normal_server(httprequest_dictionary): } return dict_toreturn + + +def client(): + sockobj = openconnection(getmyip(), 12345,getmyip(),12346,25) + assert sockobj.send('') == len('') if callfunc == 'initialize': # used to store the httprequest_dictionary from server @@ -25,7 +30,11 @@ if callfunc == 'initialize': try: handle = httpserver_registercallback((getmyip(),12345), test_normal_server) except Exception, e: - raise Exception('failed test: server raised an exception: ' + str(e)) + raise Exception('failed test: server raised an exception: ' + str(e)) + + #client call + client() + sleep(0.1) exitall() From bb617cf5305b7019946abb2de7c2b9fcde08939e Mon Sep 17 00:00:00 2001 From: us341 Date: Mon, 17 Nov 2014 12:08:20 -0500 Subject: [PATCH 19/23] renamed _httpserver_sendAll method to _httpserver_send_all Also mentioned the reason in comments to leave httpretrieve.r2py module with dy_import_module_symbols --- httpserver.r2py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/httpserver.r2py b/httpserver.r2py index 641af62..f5227e8 100644 --- a/httpserver.r2py +++ b/httpserver.r2py @@ -9,7 +9,7 @@ Conrad Meyer - Nov 10, 2014 + Oct 22, 2014 Urvashi Soni @@ -29,7 +29,9 @@ urllib = dy_import_module("urllib.r2py") urlparse = dy_import_module("urlparse.r2py") uniqueid = dy_import_module("uniqueid.r2py") sockettimeout = dy_import_module("sockettimeout.r2py") -dy_import_module_symbols("httpretrieve.r2py") +dy_import_module_symbols("httpretrieve.r2py") +# httprettrieve is left out intentionally because dylink.r2py needs some changes. +# please refer to https://github.com/SeattleTestbed/seattlelib_v2/issues/153 @@ -196,7 +198,7 @@ def _httpserver_socketcb(remoteip, remoteport, sock, ch, listench, httpdid): # There was some sort of flaw in the client's request. response = "HTTP/1.0 400 Bad Request\r\n" + \ "Content-Type: text/plain\r\n\r\n" + str(br) + "\r\n" - _httpserver_sendAll(sock, response, besteffort=True) + _httpserver_send_all(sock, response, besteffort=True) break except _httpserver_ServerError, se: @@ -204,7 +206,7 @@ def _httpserver_socketcb(remoteip, remoteport, sock, ch, listench, httpdid): # we didn't expect. response = "HTTP/1.0 500 Internal Server Error\r\n" + \ "Content-Type: text/plain\r\n\r\n" + str(se) + "\r\n" - _httpserver_sendAll(sock, response, besteffort=True) + _httpserver_send_all(sock, response, besteffort=True) break except _httpserver_BadTransferCoding, bte: @@ -214,7 +216,7 @@ def _httpserver_socketcb(remoteip, remoteport, sock, ch, listench, httpdid): ("Content-Length: %d\r\n" % (len(str(bte)) + 2)) + \ "Connection: close\r\n" + \ "Content-Type: text/plain\r\n\r\n" + str(bte) + "\r\n" - _httpserver_sendAll(sock, response, besteffort=True) + _httpserver_send_all(sock, response, besteffort=True) break except _httpserver_ClientClosedSockEarly: @@ -302,7 +304,7 @@ def _httpserver_parseHTTPheader(headerdatalist): -def _httpserver_sendAll(sock, datastr, besteffort=False): +def _httpserver_send_all(sock, datastr, besteffort=False): sent = 0 while sent < len(datastr): @@ -761,7 +763,7 @@ def _httpserver_sendfile(sock, filelikeobj): chunk = filelikeobj.read(4096) if len(chunk) == 0: break - _httpserver_sendAll(sock, chunk, besteffort=True) + _httpserver_send_all(sock, chunk, besteffort=True) @@ -777,12 +779,12 @@ def _httpserver_sendfile_chunked(sock, filelikeobj): # encode as HTTP/1.1 chunks: totallen += len(chunk) chunk = "%X\r\n%s\r\n" % (len(chunk), chunk) - _httpserver_sendAll(sock, chunk) + _httpserver_send_all(sock, chunk) lastchunk = "0\r\n" lastchunk += ("Content-Length: %d\r\n" % totallen) lastchunk += "\r\n" - _httpserver_sendAll(sock, lastchunk) + _httpserver_send_all(sock, lastchunk) @@ -865,7 +867,7 @@ def _httpserver_process_single_request(sock, cbfunc, extradata, httpdid, \ for key, val in headers.items(): response += key + ": " + val + "\r\n" response += "\r\n" - _httpserver_sendAll(sock, response, besteffort=True) + _httpserver_send_all(sock, response, besteffort=True) # Send the response body: _httpserver_sendfile(sock, messagestream) @@ -887,7 +889,7 @@ def _httpserver_process_single_request(sock, cbfunc, extradata, httpdid, \ # Send response headers. - _httpserver_sendAll(sock, response) + _httpserver_send_all(sock, response) # Read chunks from the callback and efficiently send them to # the client using HTTP/1.1 chunked encoding. From d9d314090365abc48f812a4352401813e4d5a306 Mon Sep 17 00:00:00 2001 From: us341 Date: Mon, 17 Nov 2014 13:30:41 -0500 Subject: [PATCH 20/23] changed waitforconn docstring for callback function Changed waitforconn docstring for callback function to take five arguments instead of one. --- librepysocket.r2py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/librepysocket.r2py b/librepysocket.r2py index d9cbba9..4414a61 100644 --- a/librepysocket.r2py +++ b/librepysocket.r2py @@ -626,8 +626,8 @@ def waitforconn(localip, localport, func, thread_pool=None, check_intv=0.1, err_ localport: The local port to listen on - func: The function to trigger when a connection comes in. This function should - take a single argument which is a RepySocket object connected to the remote peer + func: The function to trigger when a connection comes in. It should take five arguments: + (remoteip, remoteport, socketlikeobj, thiscommhandle, listencommhandle) localip: A local ip to listen on. If None, then getmyip() will be used. From f326ef784b77040906dc541fb1cd567580fd9f85 Mon Sep 17 00:00:00 2001 From: us341 Date: Tue, 16 Dec 2014 00:18:00 -0500 Subject: [PATCH 21/23] test case to check if httpserver raises error for wrong type of status code --- ..._seattlelib_httpserver_statuscodetype.r2py | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/ut_seattlelib_httpserver_statuscodetype.r2py diff --git a/tests/ut_seattlelib_httpserver_statuscodetype.r2py b/tests/ut_seattlelib_httpserver_statuscodetype.r2py new file mode 100644 index 0000000..f9a5780 --- /dev/null +++ b/tests/ut_seattlelib_httpserver_statuscodetype.r2py @@ -0,0 +1,36 @@ +#checks if httpserver raise error for wrong type of status code + +dy_import_module_symbols("httpserver.r2py") + +# this method will work as callback function for httpserver_registercallback in httpserver.r2py +def test_normal_server(httprequest_dictionary): + # normal server just sends a message + # store the http dictionary to check the content + mycontext['httprequest_dictionary'] = httprequest_dictionary + dict_toreturn = { + 'version': '1.1', + 'statuscode': '101', #status code is not an int so httpserver should raise raise + 'statusmsg': "valid", + 'headers': { 'X-Header-Foo': 'Bar' }, + 'message': "this is original message" + } + return dict_toreturn + + + +def client(): + sockobj = openconnection(getmyip(), 12345,getmyip(),12346,25) + assert sockobj.send('') == len('') + +if callfunc == 'initialize': + # used to store the httprequest_dictionary from server + mycontext['httprequest_dictionary'] = {} + + # register the callback server + try: + handle = httpserver_registercallback((getmyip(),12345), test_normal_server) + except Exception, e: + raise Exception('failed test: server raised an exception: ' + str(e)) + + + From fe2e49419344910fcd3c103eced357d013b6aeec Mon Sep 17 00:00:00 2001 From: us341 Date: Tue, 16 Dec 2014 00:19:09 -0500 Subject: [PATCH 22/23] test for wrong value of status code --- ...seattlelib_httpserver_statuscodevalue.r2py | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/ut_seattlelib_httpserver_statuscodevalue.r2py diff --git a/tests/ut_seattlelib_httpserver_statuscodevalue.r2py b/tests/ut_seattlelib_httpserver_statuscodevalue.r2py new file mode 100644 index 0000000..af9cb79 --- /dev/null +++ b/tests/ut_seattlelib_httpserver_statuscodevalue.r2py @@ -0,0 +1,34 @@ +dy_import_module_symbols("httpserver.r2py") + +# this method will work as callback function for httpserver_registercallback in httpserver.r2py +def test_normal_server(httprequest_dictionary): + # normal server just sends a message + # store the http dictionary to check the content + mycontext['httprequest_dictionary'] = httprequest_dictionary + dict_toreturn = { + 'version': '0.9', + 'statuscode': 0, #ideally the status code should be within 100-599 range. + 'statusmsg': "valid", + 'headers': { 'X-Header-Foo': 'Bar' }, + 'message': "this is original message" + } + return dict_toreturn + + + +def client(): + sockobj = openconnection(getmyip(), 12345,getmyip(),12346,25) + assert sockobj.send('') == len('') + +if callfunc == 'initialize': + # used to store the httprequest_dictionary from server + mycontext['httprequest_dictionary'] = {} + + # register the callback server + try: + handle = httpserver_registercallback((getmyip(),12345), test_normal_server) + except Exception, e: + raise Exception('failed test: server raised an exception: ' + str(e)) + + + From 546b911c181b7cb0ba4dffedb4963a9d89429c88 Mon Sep 17 00:00:00 2001 From: us341 Date: Tue, 16 Dec 2014 00:21:44 -0500 Subject: [PATCH 23/23] checks httpserver response for empty dictionary --- .../ut_seattlelib_httpserver_emptydictionary | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 tests/ut_seattlelib_httpserver_emptydictionary diff --git a/tests/ut_seattlelib_httpserver_emptydictionary b/tests/ut_seattlelib_httpserver_emptydictionary new file mode 100644 index 0000000..a1ded8d --- /dev/null +++ b/tests/ut_seattlelib_httpserver_emptydictionary @@ -0,0 +1,32 @@ +#checks httpserver response for empty dictionary + +dy_import_module_symbols("httpserver.r2py") + +# this method will work as callback function for httpserver_registercallback in httpserver.r2py +def test_normal_server(httprequest_dictionary): + # normal server just sends a message + # store the http dictionary to check the content + mycontext['httprequest_dictionary'] = httprequest_dictionary + dict_toreturn = { + + } + return dict_toreturn + + + +def client(): + sockobj = openconnection(getmyip(), 12345,getmyip(),12346,25) + assert sockobj.send('') == len('') + +if callfunc == 'initialize': + # used to store the httprequest_dictionary from server + mycontext['httprequest_dictionary'] = {} + + # register the callback server + try: + handle = httpserver_registercallback((getmyip(),12345), test_normal_server) + except Exception, e: + raise Exception('failed test: server raised an exception: ' + str(e)) + + +