Skip to content

Instantly share code, notes, and snippets.

@wildonion
Created October 28, 2020 20:11
Show Gist options
  • Select an option

  • Save wildonion/cd2e90f6329cde8cb9d8c603dd0cdcb5 to your computer and use it in GitHub Desktop.

Select an option

Save wildonion/cd2e90f6329cde8cb9d8c603dd0cdcb5 to your computer and use it in GitHub Desktop.
a simple http server
#!/usr/bin/python
# build a httpserver like flask
# python http webserver using http module(watch?v=hFNZ6kdBgO0) or socket module(watch?v=_najJkyK46g) or flask module(watch?v=vyCboBjK4us) or watch?v=2KeSfeIo2MI
import socket # Networking support
import signal # Signal support (server shutdown on signal receive)
import time # Current time
class Server:
""" Class describing a simple HTTP server objects."""
def __init__(self, port = 80):
""" Constructor """
self.host = '' # <-- works on all avaivable network interfaces
self.port = port
self.www_dir = 'www' # Directory where webpage files are stored
def activate_server(self):
""" Attempts to aquire the socket and launch the server """
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try: # user provided in the __init__() port may be unavaivable
print("Launching HTTP server on ", self.host, ":",self.port)
self.socket.bind((self.host, self.port))
except Exception as e:
print ("Warning: Could not aquite port:",self.port,"\n")
print ("I will try a higher port")
# store to user provideed port locally for later (in case 8080 fails)
user_port = self.port
self.port = 8080
try:
print("Launching HTTP server on ", self.host, ":",self.port)
self.socket.bind((self.host, self.port))
except Exception as e:
print("ERROR: Failed to acquire sockets for ports ", user_port, " and 8080. ")
print("Try running the Server in a privileged user mode.")
self.shutdown()
import sys
sys.exit(1)
print ("Server successfully acquired the socket with port:", self.port)
print ("Press Ctrl+C to shut down the server and exit.")
self._wait_for_connections()
def shutdown(self):
""" Shut down the server """
try:
print("Shutting down the server")
s.socket.shutdown(socket.SHUT_RDWR)
except Exception as e:
print("Warning: could not shut down the socket. Maybe it was already closed?",e)
def _gen_headers(self, code):
""" Generates HTTP response Headers. Ommits the first line! """
# determine response code
h = ''
if (code == 200):
h = 'HTTP/1.1 200 OK\n'
elif(code == 404):
h = 'HTTP/1.1 404 Not Found\n'
# write further headers
current_date = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
h += 'Date: ' + current_date +'\n'
h += 'Server: Simple-Python-HTTP-Server\n'
h += 'Connection: close\n\n' # signal that the conection wil be closed after complting the request
return h
def _wait_for_connections(self):
""" Main loop awaiting connections """
while True:
print ("Awaiting New connection")
self.socket.listen(3) # maximum number of queued connections
conn, addr = self.socket.accept()
# conn - socket to client
# addr - clients address
print("Got connection from:", addr)
data = conn.recv(1024) #receive data from client
string = bytes.decode(data) #decode it to string
#determine request method (HEAD and GET are supported)
request_method = string.split(' ')[0]
print ("Method: ", request_method)
print ("Request body: ", string)
#if string[0:3] == 'GET':
if (request_method == 'GET') | (request_method == 'HEAD'):
#file_requested = string[4:]
# split on space "GET /file.html" -into-> ('GET','file.html',...)
file_requested = string.split(' ')
file_requested = file_requested[1] # get 2nd element
#Check for URL arguments. Disregard them
file_requested = file_requested.split('?')[0] # disregard anything after '?'
if (file_requested == '/'): # in case no file is specified by the browser
file_requested = '/index.html' # load index.html by default
file_requested = self.www_dir + file_requested
print ("Serving web page [",file_requested,"]")
## Load file content
try:
file_handler = open(file_requested,'rb')
if (request_method == 'GET'): #only read the file when GET
response_content = file_handler.read() # read file content
file_handler.close()
response_headers = self._gen_headers( 200)
except Exception as e: #in case file was not found, generate 404 page
print ("Warning, file not found. Serving response code 404\n", e)
response_headers = self._gen_headers( 404)
if (request_method == 'GET'):
response_content = b"<html><body><p>Error 404: File not found</p><p>Python HTTP server</p></body></html>"
server_response = response_headers.encode() # return headers for GET and HEAD
if (request_method == 'GET'):
server_response += response_content # return additional conten for GET only
conn.send(server_response)
print ("Closing connection with client")
conn.close()
else:
print("Unknown HTTP request method:", request_method)
def graceful_shutdown(sig, dummy):
""" This function shuts down the server. It's triggered
by SIGINT signal """
s.shutdown() #shut down the server
import sys
sys.exit(1)
###########################################################
# shut down on ctrl+c
signal.signal(signal.SIGINT, graceful_shutdown)
print ("Starting web server")
s = Server(80) # construct server object
s.activate_server() # aquire the socket
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# -------------------------------------------------------
# web server using socket like laravel or django or flask
# -------------------------------------------------------
# import random
# import socket
# import time
# s = socket.socket() # Create a socket object
# host = socket.getfqdn() # Get local machine name
# port = 9082
# s.bind((host, port)) # Bind to the port
# print 'Starting server on', host, port
# print 'The Web server URL for this would be http://%s:%d/' % (host, port)
# s.listen(5) # Now wait for client connection.
# print 'Entering infinite loop; hit CTRL-C to exit'
# while True:
# # Establish connection with client.
# c, (client_host, client_port) = s.accept()
# print 'Got connection from', client_host, client_port
# c.recv(1000) # should receive request from client. (GET ....)
# c.send('HTTP/1.0 200 OK\n')
# c.send('Content-Type: text/html\n')
# c.send('\n') # header and body should be separated by additional newline
# c.send("""
# <html>
# <body>
# <h1>Hello World</h1> this is my server!
# </body>
# </html>
# """) # Use triple-quote string.
# c.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment