it serves files
parent
dd14dee99a
commit
8af1cd2b28
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue