Advertisement
Guest User

Untitled

a guest
Jan 20th, 2020
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.98 KB | None | 0 0
  1. import socket
  2. import threading
  3. from datetime import datetime
  4. import sys
  5. import os
  6. import mimetypes
  7. import urllib.parse
  8. import subprocess
  9.  
  10. respTemplate = """HTTP/1.1 {statusNum} {statusCode}
  11. Date: {dateSent}
  12. Server: {server}
  13. Last-Modified: {modified}
  14. Content-Length: {length}
  15. Content-Type: {contentType}
  16. Connection: {connectionType}
  17.  
  18. {body}
  19. """
  20. DOC_ROOT = "DocRoot"
  21.  
  22. CODES = {"200": "OK",
  23. "304": "NOT MODIFIED",
  24. "400": "BAD REQUEST", "401": "UNAUTHORIZED", "403": "FORBIDDEN", "404": "NOT FOUND",
  25. "500": "INTERNAL SERVER ERROR"}
  26.  
  27. MIMES = {"txt": "text/plain", "css":"text/css", "html":"text/html", "png": "image/png", "jpg":"image/jpg",
  28. "ttf":"application/octet-stream","otf":"application/octet-stream", "woff":"font/woff", "woff2": "font/woff2",
  29. "js":"application/javascript","gz":"application/zip", "py":"text/plain", "map": "application/octet-stream"}
  30.  
  31.  
  32. class Response:
  33. def __init__(self, **kwargs):
  34. self.__dict__.update(kwargs)
  35. now = datetime.now()
  36. self.dateSent = self.modified = now.strftime("%a, %d %b %Y %H:%M:%S")
  37. def stringResponse(self):
  38. return respTemplate.format(**self.__dict__)
  39.  
  40. class Request:
  41. def __init__(self, request):
  42. self.good = True
  43. try:
  44. request = self.parseRequest(request)
  45. self.method = request["method"]
  46. self.doc = request["doc"]
  47. self.vers = request["vers"]
  48. self.header = request["header"]
  49. self.body = request["body"]
  50. except:
  51. self.good = False
  52.  
  53. def parseRequest(self, request):
  54. req = request.strip("\r").split("\n")
  55. method,doc,vers = req[0].split(" ")
  56. header = req[1:-3]
  57. body = req[-1]
  58. headerDict = {}
  59. for param in header:
  60. pos = param.find(": ")
  61. key, val = param[:pos], param[pos+2:]
  62. headerDict.update({key: val})
  63. return {"method": method, "doc": doc, "vers": vers, "header": headerDict, "body": body}
  64.  
  65.  
  66. class Server:
  67. def __init__(self, host, port):
  68. self.host = host
  69. self.port = port
  70. self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  71. self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  72. self.sock.bind((self.host, self.port))
  73.  
  74. def listen(self):
  75. self.sock.listen(5)
  76. while True:
  77. client, address = self.sock.accept()
  78. client.settimeout(60)
  79. threading.Thread(target = self.listenToClient,args = (client,address)).start()
  80.  
  81. def listenToClient(self, client, address):
  82. size = 1024
  83. while True:
  84. try:
  85. data = client.recv(size)
  86. if data:
  87. # Set the response to echo back the recieved data
  88. req = Request(data.decode())
  89. self.handleRequest(req, client, address)
  90. client.shutdown()
  91. client.close()
  92. else:
  93. raise error('Client disconnected')
  94. except:
  95. client.close()
  96. return False
  97.  
  98. def handleRequest(self, request, conn, address):
  99. if request.good:
  100. # try:
  101. # print(str(request.method) + " " + str(request.doc), end=' ')
  102. # print("from {0}".format(address[0]))
  103. # except Exception as e:
  104. # print(e)
  105. document = self.serveDoc(request.doc, DOC_ROOT)
  106. statusNum=document["status"]
  107. else:
  108. document = self.serveDoc("/errors/400.html", DOC_ROOT)
  109. statusNum="400"
  110. body = document["body"]
  111.  
  112. statusCode=CODES[statusNum]
  113. dateSent = ""
  114. server = "BadHTTPServer"
  115. modified = ""
  116. length = len(body)
  117. contentType = document["mime"] # Try and identify MIME type from string
  118. connectionType = "Closed"
  119.  
  120.  
  121. resp = Response(
  122. statusNum=statusNum, statusCode=statusCode,
  123. dateSent = dateSent, server = server,
  124. modified = modified, length = length,
  125. contentType = contentType, connectionType = connectionType,
  126. body = body
  127. )
  128.  
  129. data = resp.stringResponse()
  130. if not data:
  131. return -1
  132. conn.send(data.encode())
  133. return 0
  134.  
  135. def serveDoc(self, path, docRoot):
  136. path = urllib.parse.unquote(path)
  137. try:
  138. info = "output = 'Document: {}'" # Keep the output for later debug
  139. exec(info.format(path)) # This is how you do string formatting, right?
  140. cwd = os.path.dirname(os.path.realpath(__file__))
  141. docRoot = os.path.join(cwd, docRoot)
  142. if path == "/":
  143. path = "/index.html"
  144. requested = os.path.join(docRoot, path[1:])
  145. if os.path.isfile(requested):
  146. mime = mimetypes.guess_type(requested)
  147. mime = (mime if mime[0] != None else "text/html")
  148. mime = MIMES[requested.split(".")[-1]]
  149. try:
  150. with open(requested, "r") as f:
  151. data = f.read()
  152. except:
  153. with open(requested, "rb") as f:
  154. data = f.read()
  155. status = "200"
  156. else:
  157. errorPage = os.path.join(docRoot, "errors", "404.html")
  158. mime = "text/html"
  159. with open(errorPage, "r") as f:
  160. data = f.read().format(path)
  161. status = "404"
  162. except Exception as e:
  163. print(e)
  164. errorPage = os.path.join(docRoot, "errors", "500.html")
  165. mime = "text/html"
  166. with open(errorPage, "r") as f:
  167. data = f.read()
  168. status = "500"
  169. return {"body": data, "mime": mime, "status": status}
  170.  
  171. myServer = Server('127.0.0.1', 4001)
  172. Server.listen(myServer)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement