aboutsummaryrefslogtreecommitdiff
path: root/scripts/async-http.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/async-http.py')
-rw-r--r--scripts/async-http.py88
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):