""" Composer for HTTP responses This module contains a composer, which can compose responses to HTTP requests from a client. """ import re import time from config import config from message import Response from resource import Resource, FileExistError, FileAccessError import weblogging as logging 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 = Response() if re.search(r'\/\.\.?(\/|$)', request.uri): response.code = 403 response.set_header('Connection', 'close') response.body = 'Don\'t even think about it.' response.set_content_length() return response return self.serve(request.uri, request=request) def serve(self, uri, code=200, etag=None, request=None, error_page=False): response = Response() try: resource = Resource(uri) req = request if req != None and ( resource.etag_match(req.get_header('If-None-Match')) or \ not resource.etag_match(req.get_header('If-Match') or '*')): response.code = 304 else: response.code = code response.body = resource.get_content() response.set_header('ETag', resource.generate_etag()) response.set_header('Connection', 'close') response.set_header('Content-Type', resource.get_content_type()) response.set_content_length() except FileExistError: if not error_page: return self.serve(config('error404'), code=404, error_page=True) else: response.code = code response.set_header('Connection', 'close') response.body = 'Error %d' % code response.set_content_length() except FileAccessError: return self.serve(config('error403'), code=403, error_page=True) 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())