# -*- Mode: Python; tab-width: 4 -*- import coro import coroutine import socket import string import time class http_client: def __init__ (self, conn, addr, doc_root): self.s = conn self.addr = addr self.buffer = '' self.lines = [] self.doc_root = doc_root def read_line (self): # could be yet another use for coroutines if self.lines: l = self.lines[0] self.lines = self.lines[1:] return l else: while not self.lines: buffer = self.s.recv (8192) lines = string.split (buffer, '\r\n') for l in lines[:-1]: self.lines.append (l) self.buffer = lines[-1] return self.read_line() def read_header (self): header = [] while 1: l = self.read_line() if not l: break else: header.append (l) self.header = header return header def send (self, data): olb = lb = len(data) while lb: ns = self.s.send (data) lb = lb - ns return olb def close (self): self.s.close() def send_response (self): request = self.header[0] method, uri, version = string.split (request) import os filename = os.path.join (self.doc_root, uri[1:]) if os.path.isdir (filename): filename = os.path.join (filename, 'index.html') if not os.path.isfile (filename): self.send ( 'HTTP/1.0 404 Not Found\r\n' 'Connection close\r\n' '\r\n' ) self.close() sys.stdout.write ('%s %s 404\n' % (time.ctime(time.time()), request)) else: f = open (filename, 'rb') header = ( 'HTTP/1.0 200 OK\r\n' 'Content-Type: text/html\r\n' 'Connection: close\r\n' '\r\n' ) self.send (header) bc = 0 while 1: block = f.read (8192) if not block: break else: bc = bc + self.send (block) sys.stdout.write ('%s %s 200 %d\n' % (time.ctime(time.time()), request, bc)) self.close() def client (conn, addr, doc_root): h = http_client (conn, addr, doc_root) h.read_header() h.send_response() return coro.yield_() def serve (doc_root): s = coro.coroutine_socket() s.create_socket (socket.AF_INET, socket.SOCK_STREAM) s.set_reuse_addr() s.bind (('', 8081)) s.listen (128) while 1: conn, addr = s.accept() coro.spawn (client, conn, addr, doc_root) if __name__ == '__main__': import backdoor import sys if len (sys.argv) > 1: doc_root = sys.argv[1] else: doc_root = '/usr/share/doc/handbook' coro.spawn (serve, doc_root) coro.spawn (backdoor.serve) coro.event_loop (30.0)