how can I force specific mime types for python's http.server?

147 views Asked by At

I have a bunch of files without extensions, so http.server is serving them all as application/octet-stream and this is causing problems...

Rather than giving them extensions, I would like a way to define a dictionary that would be filename -> mimetype. And then have GET requests to http.server look up the filename in that dictionary object, and set the Content-type header to its value.

Is there a way to do this?

1

There are 1 answers

0
Fynn On BEST ANSWER

You can use the extensions_map attribute of SimpleHTTPRequestHandler. When adding a mapping from the empty string to your preferred type, it will serve files without extension as that.

from http.server import SimpleHTTPRequestHandler
from socketserver import TCPServer


def run():
    Handler = SimpleHTTPRequestHandler
    Handler.extensions_map = {'': 'text/plain'}
    with TCPServer(('', 8000), Handler) as httpd:
        httpd.serve_forever()


if __name__ == '__main__':
    run()

Here's the output of curl -I localhost:8000/myfile (with a corresponding file put in the appropriate place).

HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.11.7
Date: Tue, 16 Jan 2024 23:35:28 GMT
Content-type: text/plain
Content-Length: 26
Last-Modified: Tue, 16 Jan 2024 23:33:49 GMT

If you want to serve different types and really map from individual file names to the types, it's somewhat more involved.

You have to subclass and overwrite the behaviour of SimpleHTTPRequestHandler.guess_type. Start reading here.

Should probably be something like this:

def guess_type(self, path):
    from pathlib import Path
    path_name = Path(path).name
    return self.extensions_map.get(path_name, 'application/octet-stream')

This is a sledgehammer job, and I suggest you don't use this example as is and do some sensible error handling instead. You get the idea.