it serves files

master
Yorick van Pelt 2015-02-28 00:45:59 +01:00
parent dd14dee99a
commit 8af1cd2b28
1 changed files with 74 additions and 8 deletions

View File

@ -1,4 +1,5 @@
import socket, select
import os.path
class Server(object):
def __init__(self, port=8080):
@ -24,7 +25,7 @@ class Server(object):
self.handlers[otherable].do_other()
def do_read(self):
(sock, addrinfo) = self.listening_socket.accept()
c = EchoClient(self, sock, addrinfo)
c = HTTPDirClient(self, sock, addrinfo)
self.clients.append(c)
self.handlers[sock] = c
def client_closed(self, c):
@ -53,14 +54,19 @@ class Client(object):
self.read_buf += data
self.on_data()
def do_write(self):
if self.write_buf:
no_written = self.sock.send(self.write_buf)
self.write_buf = self.write_buf[no_written:]
if len(self.write_buf) == 0 and self.to_close:
self.sock.close()
self.parent.client_closed(self)
try:
if self.write_buf:
no_written = self.sock.send(self.write_buf)
self.write_buf = self.write_buf[no_written:]
if len(self.write_buf) == 0 and self.to_close:
self.sock.close()
self.parent.client_closed(self)
except socket.error:
self.on_error()
def on_data(self): raise NotImplementedError()
def do_other(self): pass
def on_error(self):
self.parent.client_closed(self)
def write(self, msg):
self.write_buf += msg
def close(self):
@ -74,7 +80,67 @@ class EchoClient(Client):
self.write(self.read_buf)
self.read_buf = ""
codes = {
200: "OK",
404: "Not Found"
}
class HTTPClient(Client):
"""docstring for HTTPClient"""
def __init__(self, parent, sock, addrinfo):
super(HTTPClient, self).__init__(parent, sock, addrinfo)
def on_data(self):
try:
idx = self.read_buf.index("\r\n\r\n")
except ValueError:
return
else:
headers = self.read_buf[:idx]
self.read_buf = self.read_buf[idx+4:]
self.on_request(headers)
def on_request(self, req):
headers = req.split('\r\n')
if not (headers[0].startswith("GET ") and headers[0].endswith("HTTP/1.1")):
print(headers[0])
print("malformed request:", headers)
return
url = headers[0][4:-9]
hdr = {}
for h in headers[1:]:
x = h.split(': ')
hdr[x[0]] = x[1]
self.on_GET(url, hdr)
def on_GET(self, url, headers):
print("got GET", url, headers)
def send_response(self, code, headers, data):
headers["Content-Length"] = len(data)
name = codes[code]
resp = "HTTP/1.1 %d %s\r\n" % (code, name)
for n, val in headers.iteritems():
resp += "%s: %s\r\n" % (n, val)
resp += "\r\n" + data
self.write(resp)
class HTTPDirClient(HTTPClient):
"""docstring for HTTPDirClient"""
def __init__(self, parent, sock, addrinfo):
super(HTTPDirClient, self).__init__(parent, sock, addrinfo)
self.directory = "content"
def on_GET(self, url, headers):
reqpath = os.path.abspath("./content" + url)
if not reqpath.startswith(os.path.abspath("./content/")):
self.send_response(404, {}, "Not Found, sorry\n")
return
if url.endswith('/'): # TODO FIX
print url, reqpath
reqpath += "/index.html"
if not os.path.isfile(reqpath):
self.send_response(404, {}, "Not Found, sorry\n")
else:
with open(reqpath) as f:
self.send_response(200, {}, f.read())
if __name__ == '__main__':
s = Server()