-------------------------------- Homework 4: Writing a Web server -------------------------------- Due Tuesday, October 6th, at 4:30pm (class start). Write two simple Web servers ---------------------------- Using only the socket networking library in Python, write both blocking and non-blocking HTTP servers that return 'hello, $URL" to a GET or a POST request, where $URL is replaced by the URL path being requested. For example, :: python webserve.py starts a blocking Web server bound to interface '' on port . (The non-blocking Web server should be called ``webserve_nb.py``.) This Web server, when accessed at :: http://host:port/some/random/url returns the string :: hello, /some/random/url The server should respond to both GET and POST requests, and should *read* and *ignore* any GET query strings and POST data. All data processing must take place in a function ``handle_connection`` that takes at least one parameter and up to two:: def handle_connection(client_sock, stuff=None): and returns a tuple ``(close_flag, stuff)``, where ``close_flag`` indicates whether or not this connection should now be closed, and ``stuff`` is a black box that will be passed into the function on calls subsequent to the first call, e.g. :: # first time (flag, stuff) = handle_connection(client_sock) # second time (flag was true, so connection was kept & processed) (flag, stuff) = handle_connection(client_sock, stuff) For example, here's the main loop for your blocking server: :: while 1: client_sock, _ = sock.accept() close_flag, stuff = handle_connection(client_sock) while not close_flag: close_flag, stuff = handle_connection(client_sock, stuff) The same exact ``handle_connection`` function should be used in the blocking and the non-blocking server; in fact, you can even import it from one module into another. The purpose of the ``stuff`` object is to store intermediate data between calls to handle_connection. Please remember to make both of these importable scripts, i.e. the code that actually starts the Web server should be in a ``if __name__ == '__main__'`` block. Also, remember that the Web server should **under no reasonable circumstances** fail to return a proper HTTP response; that is, even if your code generates an internal exception, a proper HTTP response should be returned. (**Unreasonable** circumstances are things like power outages or backhoe-based network connection interruptions.) Your Web server should be implemented to the point that Firefox can talk to it. (5.0 points) A suggestion for how to proceed ------------------------------- First, write a blocking server that ignores all received data and returns a hard-coded "hello, world" HTTP response. Next, modify that server to parse the HTTP response out of the received data, but still return a hard-coded HTTP response. Third, modify this server to properly handle the HTTP request. Finally, fix the handle_connection code so that it works with non-blocking sockets, too. We will write some test code for this HW on Thursday. More Jinja2 madness ------------------- Separate your ``templates/process_form.html`` from hw2 into two files, ``templates/base.html`` and ``templates/process_form.html``. ``base.html`` should define a properly structured HTML file, including , , and tags, as well as two blocks: {% title %} and {% content %}, one in the area and the other in the <body> area. ``process_form.html`` must inherit from ``base.html`` and should override the title and content blocks to provide its own content (as before, this content should be the form processing code; no change in content of actual rendered page is needed apart from the <html>, <head>, and <body> tags). (Your Python code from HW 2 for rendering the Jinja2 templates should still work as-is with your revised templates; **no changes are needed to the Python code**.) (2.5 points)