diff options
Diffstat (limited to 'scripts/async-http.py')
-rw-r--r-- | scripts/async-http.py | 88 |
1 files changed, 57 insertions, 31 deletions
diff --git a/scripts/async-http.py b/scripts/async-http.py index a22a53a3..3c6251c6 100644 --- a/scripts/async-http.py +++ b/scripts/async-http.py @@ -18,14 +18,63 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """ +# Command that may be useful for testing server side of this: +# +# lynx -post_data -mime_header -source http://127.0.0.1:8000/ + + import sys, os, time, socket, fcntl, asyncore, asynchat, getopt, email, traceback +class http_message(object): + + def __init__(self, headers): + headers = headers.split("\r\n") + self.parse_first_line(*headers.pop(0).split(None, 2)) + for i in xrange(len(headers) - 2, -1, -1): + if headers[i + 1][0].isspace(): + headers[i] += headers[i + 1] + del headers[i + 1] + headers = [h.split(":", 1) for h in headers] + self.headers = dict((k.lower(), v) for (k,v) in headers) + + def __str__(self): + s = "Version: %d.%d\n" % self.version + s += "Type: %s\n" % self.__class__.__name__ + s += "Command: %s\n" % getattr(self, "cmd", "") + s += "Path: %s\n" % getattr(self, "path", "") + s += "Code: %s\n" % getattr(self, "code", "") + s += "Msg: %s\n" % getattr(self, "msg", "") + for k,v in self.headers.iteritems(): + s += " %s: %s\n" % (k, v) + return s + +class http_request(http_message): + + def parse_first_line(self, cmd, path, version = None): + self.cmd = cmd.upper() + self.path = path + if version is None: + self.version = (0, 9) + elif version[:5] == "HTTP/": + self.version = tuple(int(i) for i in version[5:].split(".")) + else: + raise RuntimeError + +class http_response(http_message): + + def parse_first_line(self, version, code, msg): + if version[:5] == "HTTP/": + self.version = tuple(int(i) for i in version[5:].split(".")) + else: + raise RuntimeError + self.code = int(code) + self.msg = msg + class http_server(asynchat.async_chat): """This started out as the asynchat example from the Python manual.""" def __init__(self, conn): asynchat.async_chat.__init__(self, conn = conn) - self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) self.ibuffer = [] self.set_terminator("\r\n\r\n") @@ -52,36 +101,14 @@ class http_server(asynchat.async_chat): raise RuntimeError def handle_headers(self): - headers = self.get_ibuffer().split("\r\n") - request = headers.pop(0).split() - if len(request) == 3: - cmd, path, version = request - assert version[:5] == "HTTP/" - version = tuple(int(i) for i in version[5:].split(".")) - elif len(request) == 2: - cmd, path = request - version = (0, 9) - else: - raise RuntimeError - cmd = cmd.upper() - for i in xrange(len(headers) - 2, -1, -1): - if headers[i + 1][0].isspace(): - headers[i] += headers[i + 1] - del headers[i + 1] - headers = [h.split(":", 1) for h in headers] - headers = dict((k.lower(), v) for (k,v) in headers) - print - print "Command: ", cmd - print "Path: ", path - print "Version:", version - print - print "Headers:", repr(headers) - self.push_line("HTTP/1.0 200 Yo!") - self.push_line("Content-Type: text/plain") - self.push_line() - self.push_line("Hi, Mom!") + msg = http_request(self.get_ibuffer()) + print msg + self.reply(msg) + + def reply(self, msg): + self.push("HTTP/1.0 200 Yo!\r\nContent-Type: text/plain\r\n\r\n") + self.push(str(msg).replace("\n", "\r\n")) self.close_when_done() - #asyncore.close_all() def push_line(self, line = ""): self.push(line + "\r\n") @@ -96,7 +123,6 @@ class http_listener(asyncore.dispatcher): asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.bind(("", 8000)) - self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) self.listen(5) def handle_accept(self): |