Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an alternative of RewriteRule / .htaccess for a Python http.server.HTTPServer?

Can my server module (with http.server.HTTPServer) use something like the RewriteRule for redirect all traffic into a single cgi script? I'd like to be able to do what's shown here in this other question, but for my python server.

Can it be done using something like .htaccess, or is there another way?

Also, can this be done even for a simple localhost development server?
I am serving files for development via, for example, http://localhost:8000/html/index.html, and I would like to hide the /html subfolder from the URL even in development.
How can that be achieved?

like image 385
fj123x Avatar asked Sep 04 '13 21:09

fj123x


2 Answers

John Moutafis's answer was helpful to get me started, but needed some fine tuning to run on python3, beyond his comments about imports.

The imports should be

from http.server import HTTPServer, SimpleHTTPRequestHandler

and you'll also need to change the urllib import to:

from urllib.parse import unquote

Then the main should be something like:

if __name__ == '__main__':
    myServer = HTTPServer(('0.0.0.0', 8000), RequestHandler)
    print("Ready to begin serving files.")
    try:
        myServer.serve_forever()
    except KeyboardInterrupt:
        pass

    myServer.server_close()
    print("Exiting.")
like image 56
Moshe Sambol Avatar answered Sep 28 '22 08:09

Moshe Sambol


You can use a custom script to initialize your server and define your Routes in it, such as suggested in this article:

Python 2:

server.py

import os
import posixpath
import urllib
import BaseHTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler

# modify this to add additional routes
ROUTES = (  <- this is the "good stuff", make aliases for your paths
    # [url_prefix ,  directory_path]
    ['/media', '/var/www/media'],
    ['',       '/var/www/site']  # empty string for the 'default' match
) 

class RequestHandler(SimpleHTTPRequestHandler):

    def translate_path(self, path):
        """translate path given routes"""

        # set default root to cwd
        root = os.getcwd()

        # look up routes and set root directory accordingly
        for pattern, rootdir in ROUTES:
            if path.startswith(pattern):
                # found match!
                path = path[len(pattern):]  # consume path up to pattern len
                root = rootdir
                break

        # normalize path and prepend root directory
        path = path.split('?',1)[0]
        path = path.split('#',1)[0]
        path = posixpath.normpath(urllib.unquote(path))
        words = path.split('/')
        words = filter(None, words)

        path = root
        for word in words:
            drive, word = os.path.splitdrive(word)
            head, word = os.path.split(word)
            if word in (os.curdir, os.pardir):
                continue
            path = os.path.join(path, word)

        return path

if __name__ == '__main__':
    BaseHTTPServer.test(RequestHandler, BaseHTTPServer.HTTPServer)

Then run your script:

python server.py

Python 3:

In Python 3 the BaseHTTPServer and the SimpleHTTPServer modules have been merged into the http.server module. So you will have to modify the above script as follows:

Change the

import BaseHTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler

to

import http.server

(if you do this then the calls should be modified to http.server.SimpleHTTPRequest etc.)

or

from http.server import BaseHTTPServer, SimpleHTTPServer, SimpleHTTPRequestHandler

(with this option calls remain the same as the original script)

then run the server script: python server.py


IN YOUR CASE:

You should modify the ROUTES variable to suite your needs.
For example, you want to hide the /html folder from your url:

ROUTES = (
    ['', '/exact/path/to/folder/html'],
    ['/another_url_path', '/exact/path/to/another/folder'],
    ...
)

Now if you hit: http://localhost:8000/index.html you will be in your home page.


Note:

This script by default will serve the contained files in the folder that is in when executed to the domain url (ex. I have server.py on the Documents folder, then when I run it, http://localhost:8000 url will server my Documents folder).
You can change this behavior by the Routes (see the 'default' match comment on the code) or by placing the script in your projects root folder and start it from there.

like image 41
John Moutafis Avatar answered Sep 28 '22 07:09

John Moutafis