python-simple-http-server
There are no other dependencies needed to run this project. However, if you want to run the unitests in the tests folder, you need to install websocket via pip:
python3 -m pip install websocket-client
How to use
Install
python3 -m pip install simple_http_server
Minimum code / component requirement setup
Minimum code to get things started should have at least one controller function,
using the route and server modules from simple_http_server
hello, upload ok!" hi, Beside using the default values, you can also use variable annotations to specify your controller function's variables.
value from your path. " We recommend using functional programing to write controller functions. but if you realy want to use Object, you can use @request_map in a class method. For doing this, every time a new request comes, a new MyController object will be created.
If you want a singleton, you can add a @controller decorator to the class.
You can also add the @request_map to your class, this will be as the part of the url.
You can specify the init variables in @controller decorator.
From 0.7.0 , @request_map support regular expression mapping.
Regular expression mapping a class:
Defaultly, the session is stored in local, you can extend SessionFactory and Session classes to implement your own session storage requirement (like store all data in redis or memcache)
There is an offical Redis implementation here: https://github.com/keijack/python-simple-http-server-redis-session.git
Websocket
To handle a websocket session, you should handle multiple events, so it’s more reasonable to use a class rather than functions to do it.
In this framework, you should use @websocket_handler to decorate the class you want to handle websocket session. Specific event listener methods should be defined in a fixed way. However, the easiest way to do it is to inherit simple_http_server.WebsocketHandler class, and choose the event you want to implement. But this inheritance is not compulsory.
You can configure endpoit or regexp in @websocket_handler to setup which url the class should handle. Alongside, there is a singleton field, which is set to True by default. Which means that all connections are handle by ONE object of this class. If this field is set to False , objects will be created when every WebsocketSession try to connect.
Error pages
You can use @error_message to specify your own error page. See:
This server support filters, you can use request_filter decorator to define your filters.
If you want to specify the host and port:
If you want to specify the resources path:
From 0.12.0 , you can use coroutine tasks than threads to handle requests, you can set the prefer_coroutine parameter in start method to enable the coroutine mode.
From 0.13.0 , coroutine mode uses the coroutine server, that means all requests will use the async I/O rather than block I/O. So you can now use async def to define all your controllers including the Websocket event callback methods.
If you call the server starting in a async function, you can all its async version, by doing this, there sever will use the same event loop with your other async functions.
The default logger is try to write logs to the screen, you can specify the logger handler to write it to a file.
If you want to add a handler rather than replace the inner one, you can use:
If you want to change the logger level:
You can get a stand alone logger which is independent from the framework one via a new class logger.LoggerFactory .
You can use this module in WSGI apps.
The code that process websocket comes from the following project: https://github.com/Pithikos/python-websocket-server
Creating a Simple HTTP Server using Python
Do you know we can create a web application using core Python without using any of the most popular frameworks in Python like Django, Flask, etc?
We can simply use a Python built-in module called http.server that handles different types of HTTP methods like GET, POST, HEAD, and OPTIONS.
Here in this blog post, we create a simple HTML form that takes user inputs as POST requests and displays saved records from GET requests.
For saving the user inputs we will use the simple database SQLite3 which is supported by default in Python.
Do you know that we can simply run the python http server in the terminal?
For that, we should just install python in our system and go to the terminal, and type the following commands:
python3 -m http.server 8000
Here we choose server port number 8000. You can specify different port numbers according to your preferences.
As I am using Windows, you can see the list of directories present in the C drive. From this site, you can navigate to different folders and open the files.
Implementation
Now let’s start the actual implementation by creating a new directory called Python Server. I assumed that you have already installed Python on your local machine.
$ mkdir Python_Server $ cd Python_Server/ /Python_Server$ code .
Note: I am using VS Code as an editor and Linux OS.
Create directories inside the Python_Server directory to structure the code in an understandable format by dividing separate sections for HTML templates and databases.
/Python_Server$ mkdir database /Python_Server$ mkdir templates
The file structure for this project looks like this:
. ├── database │ ├── database.py │ └── user_records.db ├── templates │ ├── form.html │ └── show_records.html └── web_server.py
Now create two HTML templates: form.html and show_records.html inside the templates directory.
Python HTTP Server Form
show_records.html
table < font-family: arial, sans-serif; border-collapse: collapse; width: 100%; >td, th < border: 1px solid #dddddd; text-align: left; padding: 8px; >tr:nth-child(even)Python HTTP Server (Records in sqlite3 database)
Name | Country |
---|
Creating a sqlite3 database in Python is easy, we don’t have to install any third-party dependencies. Simply create a new python file called database.py inside the database directory as:
from sqlite3 import connect from sqlite3.dbapi2 import Cursor DB_NAME = "database/user_records.db" # database name # create database inside database folder if not exists connection = connect(DB_NAME) cursor = connection.cursor() def create_table(): """function to create table inside database""" # create table user inside database if not exists table_script = '''CREATE TABLE IF NOT EXISTS User( full_name VARCHAR(255), country VARCHAR(150) ); ''' cursor.executescript(table_script) connection.commit() def insert_record(fullname, country): """function to insert record inside table""" cursor.execute("INSERT INTO User(full_name, country) VALUES(?, ?)", (fullname, country)) connection.commit() def fetch_records(): """function to fetch User records""" data = cursor.execute("SELECT * FROM User") return data
Up to this point, we created HTML templates and set up a database according to our requirements with two fields to store i.e full_name and country.
Now let’s import the database.py module functions into a new python file called web_server.py that handles GET and POST requests respectively.
web_server.py
import sys import cgi from http.server import HTTPServer, SimpleHTTPRequestHandler from database.database import create_table, insert_record, fetch_records HOST_NAME = "localhost" PORT = 8080 def read_html_template(path): """function to read HTML file""" try: with open(path) as f: file = f.read() except Exception as e: file = e return file def show_records(self): """function to show records in template""" file = read_html_template(self.path) # fetch records from database table_data = fetch_records() table_row = "" for data in table_data: table_row += "" for item in data: table_row += " " # replace > in template by table_row file = file.replace(">", table_row) self.send_response(200, "OK") self.end_headers() self.wfile.write(bytes(file, "utf-8")) class PythonServer(SimpleHTTPRequestHandler): """Python HTTP Server that handles GET and POST requests""" def do_GET(self): if self.path == '/': self.path = './templates/form.html' file = read_html_template(self.path) self.send_response(200, "OK") self.end_headers() self.wfile.write(bytes(file, "utf-8")) if self.path == '/show_records': self.path = './templates/show_records.html' # call show_records function to show users entered show_records(self) def do_POST(self): if self.path == '/success': ctype, pdict = cgi.parse_header(self.headers.get('content-type')) pdict['boundary'] = bytes(pdict['boundary'], 'utf-8') if ctype == 'multipart/form-data': fields = cgi.parse_multipart(self.rfile, pdict) full_name = fields.get("full_name")[0] country = fields.get("country")[0] # create table User if it runs first time else not create_table() # insert record into User table insert_record(full_name, country) html = f"" table_row += item table_row += " " table_row += "Form data successfully recorded.
" self.send_response(200, "OK") self.end_headers() self.wfile.write(bytes(html, "utf-8")) if __name__ == "__main__": server = HTTPServer((HOST_NAME, PORT), PythonServer) print(f"Server started http://:") try: server.serve_forever() except KeyboardInterrupt: server.server_close() print("Server stopped successfully") sys.exit(0)
Run the Python server by running the web_server.py script as:
/Python_Server$ python3 web_server.py
When you execute, the prompt message shows in the terminal as:
Server started http://localhost:8080
Go to your browser and open the prompted URL and you will see the form appear when you hit that URL as:
Add some data into the form and see the records that you have entered in the URL: http://localhost:8080/show_records as:
Conclusion
Hence, we successfully created a simple HTTP server using core Python that handles form data through the POST method and the data into the sqlite3 database. We also display all the stored data in the /show_records URL.
Note: http.server python method is not recommended for production use cases as it only implements basic security checks.
If you have any questions regarding this post, feel free to drop a message in the comment section.
For the code of this project, check out the GitHub repo.