Small python script to run local, case-insensitive web server

Kremp

New Member
May 13, 2018
2
1
Hi all,

as a Linux user, I'm constantly frustrated by HTML games where the file names have a different case than what's written in the HTML file.

After getting sick and tired of mass-renaming files or fixing the HTML, I've made a tiny Python script that runs a local web-server,
and tries to find matching files while ignoring differences in upper/lowercase in folder or file names.

Should work on any reasonably new python 3. You just run it, and it will serve up the current working directory on localhost:8080.
It could actually be simplified with newest python version, but I wrote this a few months back and can't be bothered :)

Thrown out in the hope that someone will find it useful,
but I'm not really planning to do anything more with this, so don't be offended if I ignore suggestions or critisism.


Python:
#!/usr/bin/env python3
#
# Start local HTTP server, serving files from CWD.
# Will try case-insensitive matches if exact matches are not found.

from http.server import HTTPServer, SimpleHTTPRequestHandler, test
import os.path
import os

class NoMatch(Exception):
    pass


def find_match(folder: str, part: str):
    if os.path.exists(os.path.join(folder, part)):
        return part

    needle = part.lower()
    print(f"Looking for {needle} in {folder}")
    candidates = [f for f in os.listdir(folder) if f.lower() == needle]   

    if len(candidates) > 1:
        print(f"{folder}/{part}: multiple candidates {candidates}")
        raise NoMatch()
    elif len(candidates) == 0:
        print(f"{folder}/{part}: no candidates {candidates}")
        raise NoMatch()
    else:
        print(f"{folder}/{part}: Found {candidates[0]}")
        return candidates[0]


class CaseInsensitiveRequestHandler(SimpleHTTPRequestHandler):

    def translate_path(self, path):
        safe = super().translate_path(path)
        if os.path.exists(safe):
            return safe
        
        print(f"Cannot find {safe}")

        rel = os.path.relpath(safe, self.directory)
        parts = rel.split(os.path.sep)

        print(f"Looking for {rel}, as parts {parts}")


        builder = self.directory
        try:
            for part in parts:
                match = find_match(builder, part)
                builder = os.path.join(builder, match)
            print(f"Build result: {builder}")
            return builder
        except NoMatch:
            return safe


PORT = 8080

if __name__ == "__main__":
    with HTTPServer(("", PORT), CaseInsensitiveRequestHandler) as httpd:
        print(f"Serving at http://localhost:{PORT}/")
        httpd.serve_forever()