Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import socket
- import threading
- from datetime import datetime
- import sys
- import os
- import mimetypes
- import urllib.parse
- import subprocess
- respTemplate = """HTTP/1.1 {statusNum} {statusCode}
- Date: {dateSent}
- Server: {server}
- Last-Modified: {modified}
- Content-Length: {length}
- Content-Type: {contentType}
- Connection: {connectionType}
- {body}
- """
- DOC_ROOT = "DocRoot"
- CODES = {"200": "OK",
- "304": "NOT MODIFIED",
- "400": "BAD REQUEST", "401": "UNAUTHORIZED", "403": "FORBIDDEN", "404": "NOT FOUND",
- "500": "INTERNAL SERVER ERROR"}
- MIMES = {"txt": "text/plain", "css":"text/css", "html":"text/html", "png": "image/png", "jpg":"image/jpg",
- "ttf":"application/octet-stream","otf":"application/octet-stream", "woff":"font/woff", "woff2": "font/woff2",
- "js":"application/javascript","gz":"application/zip", "py":"text/plain", "map": "application/octet-stream"}
- class Response:
- def __init__(self, **kwargs):
- self.__dict__.update(kwargs)
- now = datetime.now()
- self.dateSent = self.modified = now.strftime("%a, %d %b %Y %H:%M:%S")
- def stringResponse(self):
- return respTemplate.format(**self.__dict__)
- class Request:
- def __init__(self, request):
- self.good = True
- try:
- request = self.parseRequest(request)
- self.method = request["method"]
- self.doc = request["doc"]
- self.vers = request["vers"]
- self.header = request["header"]
- self.body = request["body"]
- except:
- self.good = False
- def parseRequest(self, request):
- req = request.strip("\r").split("\n")
- method,doc,vers = req[0].split(" ")
- header = req[1:-3]
- body = req[-1]
- headerDict = {}
- for param in header:
- pos = param.find(": ")
- key, val = param[:pos], param[pos+2:]
- headerDict.update({key: val})
- return {"method": method, "doc": doc, "vers": vers, "header": headerDict, "body": body}
- class Server:
- def __init__(self, host, port):
- self.host = host
- self.port = port
- self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- self.sock.bind((self.host, self.port))
- def listen(self):
- self.sock.listen(5)
- while True:
- client, address = self.sock.accept()
- client.settimeout(60)
- threading.Thread(target = self.listenToClient,args = (client,address)).start()
- def listenToClient(self, client, address):
- size = 1024
- while True:
- try:
- data = client.recv(size)
- if data:
- # Set the response to echo back the recieved data
- req = Request(data.decode())
- self.handleRequest(req, client, address)
- client.shutdown()
- client.close()
- else:
- raise error('Client disconnected')
- except:
- client.close()
- return False
- def handleRequest(self, request, conn, address):
- if request.good:
- # try:
- # print(str(request.method) + " " + str(request.doc), end=' ')
- # print("from {0}".format(address[0]))
- # except Exception as e:
- # print(e)
- document = self.serveDoc(request.doc, DOC_ROOT)
- statusNum=document["status"]
- else:
- document = self.serveDoc("/errors/400.html", DOC_ROOT)
- statusNum="400"
- body = document["body"]
- statusCode=CODES[statusNum]
- dateSent = ""
- server = "BadHTTPServer"
- modified = ""
- length = len(body)
- contentType = document["mime"] # Try and identify MIME type from string
- connectionType = "Closed"
- resp = Response(
- statusNum=statusNum, statusCode=statusCode,
- dateSent = dateSent, server = server,
- modified = modified, length = length,
- contentType = contentType, connectionType = connectionType,
- body = body
- )
- data = resp.stringResponse()
- if not data:
- return -1
- conn.send(data.encode())
- return 0
- def serveDoc(self, path, docRoot):
- path = urllib.parse.unquote(path)
- try:
- info = "output = 'Document: {}'" # Keep the output for later debug
- exec(info.format(path)) # This is how you do string formatting, right?
- cwd = os.path.dirname(os.path.realpath(__file__))
- docRoot = os.path.join(cwd, docRoot)
- if path == "/":
- path = "/index.html"
- requested = os.path.join(docRoot, path[1:])
- if os.path.isfile(requested):
- mime = mimetypes.guess_type(requested)
- mime = (mime if mime[0] != None else "text/html")
- mime = MIMES[requested.split(".")[-1]]
- try:
- with open(requested, "r") as f:
- data = f.read()
- except:
- with open(requested, "rb") as f:
- data = f.read()
- status = "200"
- else:
- errorPage = os.path.join(docRoot, "errors", "404.html")
- mime = "text/html"
- with open(errorPage, "r") as f:
- data = f.read().format(path)
- status = "404"
- except Exception as e:
- print(e)
- errorPage = os.path.join(docRoot, "errors", "500.html")
- mime = "text/html"
- with open(errorPage, "r") as f:
- data = f.read()
- status = "500"
- return {"body": data, "mime": mime, "status": status}
- myServer = Server('127.0.0.1', 4001)
- Server.listen(myServer)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement