Copied
This commit is contained in:
96
lib/httpserver/response.py
Normal file
96
lib/httpserver/response.py
Normal file
@@ -0,0 +1,96 @@
|
||||
# Components of HTTP/1.1 responses
|
||||
#
|
||||
# Use when manually composing an HTTP response
|
||||
# Expand as required for your use
|
||||
#
|
||||
# For HTTP/1.1 specification see: https://www.ietf.org/rfc/rfc2616.txt
|
||||
# For MIME types see: https://www.iana.org/assignments/media-types/media-types.xhtml
|
||||
#
|
||||
# Copyright 2021 (c) Erik de Lange
|
||||
# Released under MIT license
|
||||
|
||||
from lib.httpserver.sendfile import sendfile
|
||||
|
||||
|
||||
reason = {
|
||||
200: "OK",
|
||||
301: "Moved Permanently",
|
||||
302: "Found",
|
||||
400: "Bad Request",
|
||||
404: "Not Found",
|
||||
418: "I'm a teapot"
|
||||
}
|
||||
|
||||
mimetype = {
|
||||
"HTML": b"Content-Type: text/html\r\n",
|
||||
"EVENT_STREAM": b"Content-Type: text/event-stream\r\n",
|
||||
"X_ICON": b"Content-Type: image/x-icon\r\n",
|
||||
"JSON": b"Content-Type: application/json\r\n"
|
||||
}
|
||||
|
||||
response_header = {
|
||||
"CLOSE": b"Connection: close\r\n",
|
||||
"KEEP_ALIVE": b"Connection: keep-alive\r\n"
|
||||
}
|
||||
|
||||
|
||||
class HTTPResponse:
|
||||
def __init__(self, con, status, mimetype=None, close=True, header=None):
|
||||
""" Create a response object
|
||||
|
||||
:param int status: HTTP status code
|
||||
:param socket con: socket
|
||||
:param str mimetype: HTTP mime type
|
||||
:param bool close: if true close connection else keep alive
|
||||
:param dict header: key,value pairs for HTTP response header fields
|
||||
"""
|
||||
self.status = status
|
||||
self.con = con
|
||||
self.mimetype = mimetype
|
||||
self.close = close
|
||||
|
||||
if header is None:
|
||||
self.header = {}
|
||||
else:
|
||||
self.header = header
|
||||
|
||||
def redirect(self, location):
|
||||
""" Redirect client """
|
||||
self.con.write(f"HTTP/1.1 {self.status} {reason.get(self.status, 'NA')}\nLocation: {location}\n")
|
||||
self.con.write(response_header.get("CLOSE"))
|
||||
|
||||
def send_file(self, filepath: str = ""):
|
||||
""" Send response to stream writer """
|
||||
self.con.write(f"HTTP/1.1 {self.status} {reason.get(self.status, 'NA')}\n")
|
||||
if self.mimetype:
|
||||
self.con.write(mimetype.get(self.mimetype))
|
||||
|
||||
if self.close:
|
||||
self.con.write(response_header.get("CLOSE"))
|
||||
else:
|
||||
self.con.write(response_header.get("KEEP_ALIVE"))
|
||||
|
||||
if len(self.header) > 0:
|
||||
for key, value in self.header.items():
|
||||
self.con.write(f"{key}: {value}\n")
|
||||
|
||||
sendfile(self.con, filepath)
|
||||
|
||||
def send_raw(self, raw: bytes):
|
||||
""" Send response to stream writer """
|
||||
self.con.write(f"HTTP/1.1 {self.status} {reason.get(self.status, 'NA')}\n")
|
||||
if self.mimetype:
|
||||
self.con.write(mimetype.get(self.mimetype))
|
||||
|
||||
if self.close:
|
||||
self.con.write(response_header.get("CLOSE"))
|
||||
else:
|
||||
self.con.write(response_header.get("KEEP_ALIVE"))
|
||||
|
||||
if len(self.header) > 0:
|
||||
for key, value in self.header.items():
|
||||
self.con.write(f"{key}: {value};\n")
|
||||
|
||||
self.con.write(b'\r\n\r\n')
|
||||
self.con.write(raw)
|
||||
|
Reference in New Issue
Block a user