From 436f26b4eb1b38089396374876908fdb06d3c015 Mon Sep 17 00:00:00 2001 From: Camil Staps Date: Wed, 2 Mar 2016 21:37:50 +0100 Subject: Added framework project 1 --- project1/proj1_s4498062/webhttp/__init__.py | 9 +++ project1/proj1_s4498062/webhttp/__init__.pyc | Bin 0 -> 499 bytes project1/proj1_s4498062/webhttp/composer.py | 50 +++++++++++++++ project1/proj1_s4498062/webhttp/message.py | 90 +++++++++++++++++++++++++++ project1/proj1_s4498062/webhttp/message.pyc | Bin 0 -> 3726 bytes project1/proj1_s4498062/webhttp/parser.py | 66 ++++++++++++++++++++ project1/proj1_s4498062/webhttp/parser.pyc | Bin 0 -> 2717 bytes project1/proj1_s4498062/webhttp/resource.py | 86 +++++++++++++++++++++++++ project1/proj1_s4498062/webhttp/server.py | 59 ++++++++++++++++++ project1/proj1_s4498062/webhttp/server.pyc | Bin 0 -> 2794 bytes 10 files changed, 360 insertions(+) create mode 100644 project1/proj1_s4498062/webhttp/__init__.py create mode 100644 project1/proj1_s4498062/webhttp/__init__.pyc create mode 100644 project1/proj1_s4498062/webhttp/composer.py create mode 100644 project1/proj1_s4498062/webhttp/message.py create mode 100644 project1/proj1_s4498062/webhttp/message.pyc create mode 100644 project1/proj1_s4498062/webhttp/parser.py create mode 100644 project1/proj1_s4498062/webhttp/parser.pyc create mode 100644 project1/proj1_s4498062/webhttp/resource.py create mode 100644 project1/proj1_s4498062/webhttp/server.py create mode 100644 project1/proj1_s4498062/webhttp/server.pyc (limited to 'project1/proj1_s4498062/webhttp') diff --git a/project1/proj1_s4498062/webhttp/__init__.py b/project1/proj1_s4498062/webhttp/__init__.py new file mode 100644 index 0000000..d501a0e --- /dev/null +++ b/project1/proj1_s4498062/webhttp/__init__.py @@ -0,0 +1,9 @@ +"""HTTP Package + +This package contains the following modules: + * message: Module for HTTP responses/requests + * composer: Module for composing responses to requests + * parser: Module for parsing HTTP responses/requests + * util: Module with utility functions + * server: Module which contains a HTTP server +""" diff --git a/project1/proj1_s4498062/webhttp/__init__.pyc b/project1/proj1_s4498062/webhttp/__init__.pyc new file mode 100644 index 0000000..d86ce3e Binary files /dev/null and b/project1/proj1_s4498062/webhttp/__init__.pyc differ diff --git a/project1/proj1_s4498062/webhttp/composer.py b/project1/proj1_s4498062/webhttp/composer.py new file mode 100644 index 0000000..dfac7a1 --- /dev/null +++ b/project1/proj1_s4498062/webhttp/composer.py @@ -0,0 +1,50 @@ +""" Composer for HTTP responses + +This module contains a composer, which can compose responses to +HTTP requests from a client. +""" + +import time + +import webhttp.message +import webhttp.resource + + +class ResponseComposer: + """Class that composes a HTTP response to a HTTP request""" + + def __init__(self, timeout): + """Initialize the ResponseComposer + + Args: + timeout (int): connection timeout + """ + self.timeout = timeout + + def compose_response(self, request): + """Compose a response to a request + + Args: + request (webhttp.Request): request from client + + Returns: + webhttp.Response: response to request + + """ + response = webhttp.message.Response() + + # Stub code + response.code = 200 + response.set_header("Content-Length", 4) + response.set_header("Connection", "close") + response.body = "Test" + + return response + + def make_date_string(self): + """Make string of date and time + + Returns: + str: formatted string of date and time + """ + return time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime()) diff --git a/project1/proj1_s4498062/webhttp/message.py b/project1/proj1_s4498062/webhttp/message.py new file mode 100644 index 0000000..fb47f88 --- /dev/null +++ b/project1/proj1_s4498062/webhttp/message.py @@ -0,0 +1,90 @@ +"""HTTP Messages + +This modules contains classes for representing HTTP responses and requests. +""" + +reasondict = { + # Dictionary for code reasons + # Format: code : "Reason" + 500 : "Internal Server Error" +} + + +class Message(object): + """Class that stores a HTTP Message""" + + def __init__(self): + """Initialize the Message""" + self.version = "HTTP/1.1" + self.startline = "" + self.body = "" + self.headerdict = dict() + + def set_header(self, name, value): + """Add a header and its value + + Args: + name (str): name of header + value (str): value of header + """ + self.headerdict[name] = value + + def get_header(self, name): + """Get the value of a header + + Args: + name (str): name of header + + Returns: + str: value of header, empty if header does not exist + """ + if name in self.headerdict: + return self.headerdict[name] + else: + return "" + + def __str__(self): + """Convert the Message to a string + + Returns: + str: representation the can be sent over socket + """ + message = "" + return message + + +class Request(Message): + """Class that stores a HTTP request""" + + def __init__(self): + """Initialize the Request""" + super(Request, self).__init__() + self.method = "" + self.uri = "" + + def __str__(self): + """Convert the Request to a string + + Returns: + str: representation the can be sent over socket + """ + self.startline = "" + return super(Request, self).__str__() + + +class Response(Message): + """Class that stores a HTTP Response""" + + def __init__(self): + """Initialize the Response""" + super(Response, self).__init__() + self.code = 500 + + def __str__(self): + """Convert the Response to a string + + Returns: + str: representation the can be sent over socket + """ + self.startline = "" + return super(Response, self).__str__() diff --git a/project1/proj1_s4498062/webhttp/message.pyc b/project1/proj1_s4498062/webhttp/message.pyc new file mode 100644 index 0000000..432142c Binary files /dev/null and b/project1/proj1_s4498062/webhttp/message.pyc differ diff --git a/project1/proj1_s4498062/webhttp/parser.py b/project1/proj1_s4498062/webhttp/parser.py new file mode 100644 index 0000000..f3809c3 --- /dev/null +++ b/project1/proj1_s4498062/webhttp/parser.py @@ -0,0 +1,66 @@ +"""HTTP response and request parsers + +This module contains parses for HTTP response and HTTP requests. +""" + +import webhttp.message + + +class RequestParser: + """Class that parses a HTTP request""" + + def __init__(self): + """Initialize the RequestParser""" + pass + + def parse_requests(self, buff): + """Parse requests in a buffer + + Args: + buff (str): the buffer contents received from socket + + Returns: + list of webhttp.Request + """ + requests = split_requests(buff) + + http_requests = [] + for request in requests: + http_request = webhttp.message.Request() + http_requests.append(http_request) + + return http_requests + + def split_requests(self, buff): + """Split multiple requests + + Arguments: + buff (str): the buffer contents received from socket + + Returns: + list of str + """ + requests = buff.split('\r\n\r\n') + requests = filter(None, requests) + requests = [r + '\r\n\r\n' for r in requests] + requests = [r.lstrip() for r in requests] + return requests + + +class ResponseParser: + """Class that parses a HTTP response""" + def __init__(self): + """Initialize the ResponseParser""" + pass + + def parse_response(self, buff): + """Parse responses in buffer + + Args: + buff (str): the buffer contents received from socket + + Returns: + webhttp.Response + """ + response = webhttp.message.Response() + return response diff --git a/project1/proj1_s4498062/webhttp/parser.pyc b/project1/proj1_s4498062/webhttp/parser.pyc new file mode 100644 index 0000000..c5d9ced Binary files /dev/null and b/project1/proj1_s4498062/webhttp/parser.pyc differ diff --git a/project1/proj1_s4498062/webhttp/resource.py b/project1/proj1_s4498062/webhttp/resource.py new file mode 100644 index 0000000..dc20067 --- /dev/null +++ b/project1/proj1_s4498062/webhttp/resource.py @@ -0,0 +1,86 @@ +"""Resources + +This module contains a handler class for resources. +""" + +import os +import mimetype +import urlparse + + +class FileExistError(Exception): + """Exception which is raised when file does not exist""" + pass + + +class FileAccessError(Exception): + """Exception which is raised when file exists, but cannot be accessed""" + pass + + +class Resource: + """Class for representing a Resource (file)""" + + def __init__(self, uri): + """Initialize the resource" + + Raises: + FileExistError: if resource does not exist + FileAccessError: if resource exists, but cannot be accessed + + Args: + uri (str): Uniform Resource Identifier + """ + self.uri = uri + out = urlparse.urlparse(uri) + self.path = os.path.join("content", out.path.lstrip("/")) + if os.path.isdir(self.path): + self.path = os.path.join(self.path, "index.html") + if not os.path.isfile(self.path): + raise FileExistError + if not os.access(self.path, os.R_OK): + raise FileAccessError + + def generate_etag(self): + """Generate the ETag for the resource + + Returns: + str: ETag for the resource + """ + stat = os.stat(self.path) + etag = "" + return etag + + def get_content(self): + """Get the contents of the resource + + Returns: + str: Contents of the resource + """ + return open(self.path).read() + + def get_content_type(self): + """Get the content type, i.e "text/html" + + Returns: + str: type of content in the resource + """ + mimetype = mimetypes.guess_type(self.path) + return mimetype[0] + + def get_content_encoding(self): + """Get the content encoding, i.e "gzip" + + Returns: + str: encoding used for the resource + """ + mimetype = mimetypes.guess_type(self.path) + return mimetype[1] + + def get_content_length(self): + """Get the length of the resource + + Returns: + int: length of resource in bytes + """ + return os.path.getsize(self.path) diff --git a/project1/proj1_s4498062/webhttp/server.py b/project1/proj1_s4498062/webhttp/server.py new file mode 100644 index 0000000..b540ac4 --- /dev/null +++ b/project1/proj1_s4498062/webhttp/server.py @@ -0,0 +1,59 @@ +"""HTTP Server + +This module contains a HTTP server +""" + +import threading +import socket + + +class ConnectionHandler(threading.Thread): + """Connection Handler for HTTP Server""" + + def __init__(self, conn_socket, addr, timeout): + """Initialize the HTTP Connection Handler + + Args: + conn_socket (socket): socket used for connection with client + addr (str): ip address of client + timeout (int): seconds until timeout + """ + super(HTTPConnectionHandler, self).__init__() + self.daemon = True + self.conn_socket = conn_socket + self.addr = addr + self.timeout = timeout + + def handle_connection(self): + """Handle a new connection""" + pass + + def run(self): + """Run the thread of the connection handler""" + self.handle_connection() + + +class Server: + """HTTP Server""" + + def __init__(self, hostname, server_port, timeout): + """Initialize the HTTP server + + Args: + hostname (str): hostname of the server + server_port (int): port that the server is listening on + timeout (int): seconds until timeout + """ + self.hostname = hostname + self.server_port = server_port + self.timeout = timeout + self.done = False + + def run(self): + """Run the HTTP Server and start listening""" + while not self.done: + pass + + def shutdown(self): + """Safely shut down the HTTP server""" + self.done = True diff --git a/project1/proj1_s4498062/webhttp/server.pyc b/project1/proj1_s4498062/webhttp/server.pyc new file mode 100644 index 0000000..7981ff7 Binary files /dev/null and b/project1/proj1_s4498062/webhttp/server.pyc differ -- cgit v1.2.3