#!/usr/bin/env python3 import os import socket import subprocess class Connection(): def __init__(self, sock): self.sock = sock self.buffer = "" def read_until(self, sep): while sep not in self.buffer: self.buffer += self.sock.recv(4096) res, self.buffer = self.buffer.split(sep, 1) return res def read_line(self): return self.read_until("\r\n") def read_request(self): request_line = self.read_line() method, path, version = request_line.split(" ", 3) headers = {} line = self.read_line() while len(line): k, v = line.split(":", 1) headers[k] = v.strip() line = self.read_line() # we do not read the body return Request(method, path, headers) class Request(): def __init__(self, method, path, headers): self.method = method self.path = path self.headers = headers def __str__(self): return "Request(method='{}' path='{}' headers='{}')".format(self.method, self.path, self.headers) MSGS = { 200: "OK", 400: "Bad Request", 401: "Unauthorized", 403: "Forbidden", 404: "Not Found", 500: "Internal Server Error", } def respond(conn, status_code, content): conn.send("HTTP/1.1 {} {}\r\n".format(status_code, MSGS[status_code]), 0) conn.send("Content-Length: {}\r\n".format(len(content))) conn.send("\r\n", 0) conn.send(content, 0) def respond_to(conn, req): content = "" try: path = os.getcwd() + req.path if os.path.exists(path): if os.access(path, os.X_OK): content = subprocess.check_output([path]) else: with open(path, 'r') as f: content = f.read() status_code = 200 else: status_code = 404 except Exception as e: content = str(e) status_code = 500 respond(conn, status_code, content) def accept(s): conn, addr_info = s.accept() connection = Connection(conn) req = connection.read_request() respond_to(conn, req) def accept_loop(s): while True: accept(s) def listen(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) s.bind(('', 8080)) s.listen(5) accept_loop(s) if __name__ == '__main__': listen()