Parandatud joncardasise server
Allikas: Lambda
""" Author: Jonathan Cardasis, some fixes by T.Tammet """ import socket import signal # Allow socket destruction on Ctrl+C import sys import time import threading class WebServer(object): """ Class for describing simple HTTP server objects """ def __init__(self, port=8080): self.host = socket.gethostname().split('.')[0] # Default to any avialable network interface self.port = port self.content_dir = 'web' # Directory where webpage files are stored def start(self): """ Attempts to create and bind a socket to launch the server """ self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: print("Starting server on {host}:{port}".format(host=self.host, port=self.port)) self.socket.bind((self.host, self.port)) print("Server started on port {port}.".format(port=self.port)) except Exception as e: print("Error: Could not bind to port {port}".format(port=self.port)) self.shutdown() sys.exit(1) self._listen() # Start listening for connections def shutdown(self): """ Shuts down the server """ try: print("Shutting down server") s.socket.shutdown(socket.SHUT_RDWR) except Exception as e: pass # Pass if socket is already closed def _generate_headers(self, response_code): """ Generate HTTP response headers. Parameters: - response_code: HTTP response code to add to the header. 200 and 404 supported Returns: A formatted HTTP header for the given response_code """ header = '' if response_code == 200: header += 'HTTP/1.1 200 OK\n' elif response_code == 404: header += 'HTTP/1.1 404 Not Found\n' time_now = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime()) header += 'Date: {now}\n'.format(now=time_now) header += 'Server: Simple-Python-Server\n' header += 'Connection: close\n\n' # Signal that connection will be closed after completing the request return header def _listen(self): """ Listens on self.port for any incoming connections """ self.socket.listen(5) while True: (client, address) = self.socket.accept() client.settimeout(60) print("Recieved connection from {addr}".format(addr=address)) threading.Thread(target=self._handle_client, args=(client, address)).start() def _handle_client(self, client, address): """ Main loop for handling connecting clients and serving files from content_dir Parameters: - client: socket client from accept() - address: socket address from accept() """ PACKET_SIZE = 1024 while True: print("CLIENT",client) data = client.recv(PACKET_SIZE).decode() # Recieve data packet from client and decode if not data: break request_method = data.split(' ')[0] print("Method: {m}".format(m=request_method)) print("Request Body: {b}".format(b=data)) if request_method == "GET" or request_method == "HEAD": # Ex) "GET /index.html" split on space file_requested = data.split(' ')[1] # If get has parameters ('?'), ignore them file_requested = file_requested.split('?')[0] if file_requested == "/": file_requested = "/index.html" filepath_to_serve = self.content_dir + file_requested print("Serving web page [{fp}]".format(fp=filepath_to_serve)) # Load and Serve files content try: f = open(filepath_to_serve, 'rb') if request_method == "GET": # Read only for GET response_data = f.read() f.close() response_header = self._generate_headers(200) except Exception as e: print("File not found. Serving 404 page.") response_header = self._generate_headers(404) if request_method == "GET": # Temporary 404 Response Page response_data = "<html><body><center><h1>Error 404: File not found</h1></center><p>Head back to dry land</a>.</p></body></html>" response = response_header.encode() if request_method == "GET": response += response_data client.send(response) client.close() break else: print("Unknown HTTP request method: {method}".format(method=request_method)) def shutdownServer(sig, unused): """ Shutsdown server from a SIGINT recieved signal """ server.shutdown() sys.exit(1) signal.signal(signal.SIGINT, shutdownServer) server = WebServer(8080) server.start() print("Press Ctrl+C to shut down server.")