{{announcement.body}}
{{announcement.title}}

Extending Python’s Simple HTTP Server

DZone 's Guide to

Extending Python’s Simple HTTP Server

This article is a continuation of a topic from Gallant's book, "WebAssembly in Action". Make sure you're familiar with Python for this tutorial!

· Web Dev Zone ·
Free Resource

Over the past few days, I started putting together some notes for an article about an upcoming WebAssembly feature in the Firefox browser. The trick with the feature is that, to enable it, the webserver needs to return certain headers.

Because the article I’m going to write will be a continuation of a topic from my book, “WebAssembly in Action”, I thought it would be best to continue to use Python as the local webserver.

As it turns out, running Python’s web server from the command line doesn’t give an option to include response headers. Fortunately, it’s not hard to extend the webserver which you’ll learn how to do in this article.

As a bonus, there’s another advantage of extending Python’s local web server. WebAssembly files (.wasm) need to be served with the ‘application/wasm’ Media Type but Python didn’t have that value specified in versions older than 3.7.5. By extending the web server, you can include the Media Type without needing to modify any of Python’s files which simplifies getting up and running with WebAssembly.

The Python code that you’ll need to write is slightly different between the 2.x and 3.x versions of Python so the first thing you need to do is determine which version you have on your machine.

Python’s Version

To check which version of Python you have installed, open a console window, and run the following command: python --version

You should see the version displayed similar to the following image:

admin command prompt

If you have Python 3.x installed, skip the following section and go to the “Extending Python 3's web server” section.

Extending Python 2's Web Server

The first thing that you need to do is create a file for the python code and name it wasm-server.py

Open the file in the editor of your choice and then add the following import statements:

Python
 




xxxxxxxxxx
1


 
1
import SimpleHTTPServer
2
import SocketServer



Next, define a subclass of the SimpleHTTPServer.SimpleHTTPRequestHandler and override the end_handlers method. We won’t return any additional headers in this article but this method allows you to return additional response headers like CORS (Cross-Origin Resource Sharing) for example. End the method by calling the base class so that it will run its code too. Add the following code to your wasm-server.py file after the import statements:

Python
 




x




1
class WasmHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
2
    def end_headers(self):
3
        # Include additional response headers here. CORS for example:
4
        #self.send_header('Access-Control-Allow-Origin', '*')
5
        SimpleHTTPServer.SimpleHTTPRequestHandler.end_headers(self)



Insert a couple of line feeds after the end_headers method and then add the following Media Type for WebAssembly files:

Python
 




xxxxxxxxxx
1


 
1
WasmHandler.extensions_map['.wasm'] = 'application/wasm'



You’re now going to add some code that will start up the webserver. Python files can be loaded by other files (modules) or run directly. You’ll be running it directly but, if it were to be loaded by another module, you wouldn’t want to start up the web server in that case because the calling module will likely handle that. To check if the module is being run directly, you check the __name__ variable to see if it holds the string “__main__” which is set by the Python interpreter when running directly.

Following the WasmHandler.extensions_map line of code, add a couple of line feeds and then the following code to start up the web server when the module is run directly:

Python
 




xxxxxxxxxx
1


1
if __name__ == '__main__':
2
    PORT = 8080
3
    httpd = SocketServer.TCPServer(("", PORT), WasmHandler)
4
    print("Listening on port {}. Press Ctrl+C to stop.".format(PORT))
5
    httpd.serve_forever()



Save the wasm-server.py file.

The following section will show the steps needed to extend Python’s web server if you’re using version 3.x. Skip the following section if you completed the previous section “Extending Python 2's web server”.

Extending Python 3's Web Server

The first thing that you need to do is create a file for the python code and name it wasm-server.py

Open the file in the editor of your choice and then add the following import statements:

Python
 




xxxxxxxxxx
1


 
1
import sys
2
import socketserver
3
from http.server import SimpleHTTPRequestHandler



Next, define a subclass of the SimpleHTTPRequestHandler and override the end_handlers method. We won’t return any additional headers in this article but this method allows you to return additional response headers like CORS (Cross-Origin Resource Sharing) for example. End the method by calling the base class so that it will run its code too. Add the following code to your wasm-server.py file after the import statements:

Python
 




xxxxxxxxxx
1


 
1
class WasmHandler(SimpleHTTPRequestHandler):
2
    def end_headers(self):
3
        # Include additional response headers here. CORS for example:
4
        #self.send_header('Access-Control-Allow-Origin', '*')
5
        SimpleHTTPRequestHandler.end_headers(self)



In Python 3.7.5, the WebAssembly Media Type was added but it didn’t exist before that version. Insert a couple of line feeds after the end_headers method and then add the following code that checks to see if the version of Python is less than 3.7.5. If so, include the Media Type for WebAssembly files:

Python
 




xxxxxxxxxx
1


1
if sys.version_info < (3, 7, 5):
2
    WasmHandler.extensions_map['.wasm'] = 'application/wasm'



You’re now going to add some code that will start up the webserver. Python files can be loaded by other files (modules) or run directly. You’ll be running it directly but, if it were to be loaded by another module, you wouldn’t want to start up the web server in that case because the calling module will likely handle that. To check if the module is being run directly, you check the __name__ variable to see if it holds the string “__main__” which is set by the Python interpreter when running directly.

Following the WasmHandler.extensions_map line of code, add a couple of line feeds and then the following code to start up the web server when the module is run directly:

Python
 




xxxxxxxxxx
1


 
1
if __name__ == '__main__':
2
    PORT = 8080
3
    with socketserver.TCPServer(("", PORT), WasmHandler) as httpd:
4
        print("Listening on port {}. Press Ctrl+C to stop.".format(PORT))
5
        httpd.serve_forever()



Save the wasm-server.py file.

Now that you have your wasm-server.py file created, it’s time to test it.

Running the Extended Web Server

You can test your extended web server by opening a console window and executing the following command: python wasm-server.py

You should see output similar to the following displayed:
wasm-server.py

If you place an HTML file in that folder called test.html, for example, you could open your browser, type the following into the address bar and Python’s simple HTTP server will serve it: http://localhost:8080/test.html

Summary

In this article, you learned how to extend Python’s Simple HTTP Server so that you can return additional response headers if need be.

You also learned how to include the WebAssembly Media Type, application/wasm, if the version of Python in use is doesn’t include it.

As of version 3.7.5, Python includes the necessary WebAssembly Media Type.

Source Code
The source code for this article can be found in the following GitHub repository: https://github.com/cggallant/blog_post_code/tree/master/2020%20-%20July%20-%20Extending%20Python%E2%80%99s%20Simple%20HTTP%20Server

Disclaimer: I was not paid to write this article but I am paid royalties on the sale of the book "WebAssembly in Action" which I mentioned in this article.

Topics:
python, simplehttpserver, tutorial, web dev, webassembly

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}