pythoncorssimplehttpserver

Enable access control on simple HTTP server


I have the following shell script for a very simple HTTP server:

#!/bin/sh

echo "Serving at http://localhost:3000"
python -m SimpleHTTPServer 3000

I was wondering how I can enable or add a CORS header like Access-Control-Allow-Origin: * to this server?


Solution

  • Unfortunately, the simple HTTP server is really that simple that it does not allow any customization, especially not for the headers it sends. You can however create a simple HTTP server yourself, using most of SimpleHTTPRequestHandler, and just add that desired header.

    For that, simply create a file simple-cors-http-server.py (or whatever) and, depending on the Python version you are using, put one of the following codes inside.

    Then you can do python simple-cors-http-server.py and it will launch your modified server which will set the CORS header for every response.

    With the shebang at the top, make the file executable and put it into your PATH, and you can just run it using simple-cors-http-server.py too.

    Python 3 solution

    Python 3 uses SimpleHTTPRequestHandler and HTTPServer from the http.server module to run the server:

    #!/usr/bin/env python3
    from http.server import HTTPServer, SimpleHTTPRequestHandler, test
    import sys
    
    class CORSRequestHandler (SimpleHTTPRequestHandler):
        def end_headers (self):
            self.send_header('Access-Control-Allow-Origin', '*')
            SimpleHTTPRequestHandler.end_headers(self)
    
    if __name__ == '__main__':
        test(CORSRequestHandler, HTTPServer, port=int(sys.argv[1]) if len(sys.argv) > 1 else 8000)
    

    Python 2 solution

    Python 2 uses SimpleHTTPServer.SimpleHTTPRequestHandler and the BaseHTTPServer module to run the server.

    #!/usr/bin/env python2
    from SimpleHTTPServer import SimpleHTTPRequestHandler
    import BaseHTTPServer
    
    class CORSRequestHandler (SimpleHTTPRequestHandler):
        def end_headers (self):
            self.send_header('Access-Control-Allow-Origin', '*')
            SimpleHTTPRequestHandler.end_headers(self)
    
    if __name__ == '__main__':
        BaseHTTPServer.test(CORSRequestHandler, BaseHTTPServer.HTTPServer)
    

    Python 2 & 3 solution

    If you need compatibility for both Python 3 and Python 2, you could use this polyglot script that works in both versions. It first tries to import from the Python 3 locations, and otherwise falls back to Python 2:

    #!/usr/bin/env python
    try:
        # Python 3
        from http.server import HTTPServer, SimpleHTTPRequestHandler, test as test_orig
        import sys
        def test (*args):
            test_orig(*args, port=int(sys.argv[1]) if len(sys.argv) > 1 else 8000)
    except ImportError: # Python 2
        from BaseHTTPServer import HTTPServer, test
        from SimpleHTTPServer import SimpleHTTPRequestHandler
    
    class CORSRequestHandler (SimpleHTTPRequestHandler):
        def end_headers (self):
            self.send_header('Access-Control-Allow-Origin', '*')
            SimpleHTTPRequestHandler.end_headers(self)
    
    if __name__ == '__main__':
        test(CORSRequestHandler, HTTPServer)