How to run a http server which serves a specific path?
PythonPython 3.xSimplehttpserverPython Problem Overview
this is my Python3 project hiearchy:
projet
\
script.py
web
\
index.html
From script.py
, I would like to run a http server which serve the content of the web
folder.
Here is suggested this code to run a simple http server:
import http.server
import socketserver
PORT = 8000
Handler = http.server.SimpleHTTPRequestHandler
httpd = socketserver.TCPServer(("", PORT), Handler)
print("serving at port", PORT)
httpd.serve_forever()
but this actually serve project
, not web
. How can I specify the path of the folder I want to serve?
Python Solutions
Solution 1 - Python
In Python 3.7 SimpleHTTPRequestHandler
can take a directory
argument:
import http.server
import socketserver
PORT = 8000
DIRECTORY = "web"
class Handler(http.server.SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, directory=DIRECTORY, **kwargs)
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print("serving at port", PORT)
httpd.serve_forever()
and from the command line:
python -m http.server --directory web
To get a little crazy... you could make handlers for arbitrary directories:
def handler_from(directory):
def _init(self, *args, **kwargs):
return http.server.SimpleHTTPRequestHandler.__init__(self, *args, directory=self.directory, **kwargs)
return type(f'HandlerFrom<{directory}>',
(http.server.SimpleHTTPRequestHandler,),
{'__init__': _init, 'directory': directory})
with socketserver.TCPServer(("", PORT), handler_from("web")) as httpd:
print("serving at port", PORT)
httpd.serve_forever()
Solution 2 - Python
If you just want serve static file you can do it by running SimpleHTTPServer module using python 2:
python -m SimpleHTTPServer
Or with python 3:
python3 -m http.server
This way you do not need to write any script.
Solution 3 - Python
https://docs.python.org/3/library/http.server.html#http.server.SimpleHTTPRequestHandler
> This class serves files from the current directory and below, directly > mapping the directory structure to HTTP requests.
So you just need to change the current directory prior to starting the server - see os.chdir
eg:
import http.server
import socketserver
import os
PORT = 8000
web_dir = os.path.join(os.path.dirname(__file__), 'web')
os.chdir(web_dir)
Handler = http.server.SimpleHTTPRequestHandler
httpd = socketserver.TCPServer(("", PORT), Handler)
print("serving at port", PORT)
httpd.serve_forever()
Solution 4 - Python
Just for completeness, here's how you can setup the actual server classes to serve files from an arbitrary directory:
try
# python 2
from SimpleHTTPServer import SimpleHTTPRequestHandler
from BaseHTTPServer import HTTPServer as BaseHTTPServer
except ImportError:
# python 3
from http.server import HTTPServer as BaseHTTPServer, SimpleHTTPRequestHandler
class HTTPHandler(SimpleHTTPRequestHandler):
"""This handler uses server.base_path instead of always using os.getcwd()"""
def translate_path(self, path):
path = SimpleHTTPRequestHandler.translate_path(self, path)
relpath = os.path.relpath(path, os.getcwd())
fullpath = os.path.join(self.server.base_path, relpath)
return fullpath
class HTTPServer(BaseHTTPServer):
"""The main server, you pass in base_path which is the path you want to serve requests from"""
def __init__(self, base_path, server_address, RequestHandlerClass=HTTPHandler):
self.base_path = base_path
BaseHTTPServer.__init__(self, server_address, RequestHandlerClass)
Then you can set any arbitrary path in your code:
web_dir = os.path.join(os.path.dirname(__file__), 'web')
httpd = HTTPServer(web_dir, ("", 8000))
httpd.serve_forever()
Solution 5 - Python
There's a shorter method for Python 3+:
import functools
Handler = functools.partial(http.server.SimpleHTTPRequestHandler, directory='/my/dir/goes/here')
Solution 6 - Python
You also can run the command line with
python3 -m http.server -d web 8000
Solution 7 - Python
Another easy method to serve from a specific directory.
Since you really only need to set the directory
parameter for the SimpleHTTPRequestHandler
, you can use functools.partial to prepare the handler class without instantiating the class.
from functools import partial
from http.server import HTTPServer, SimpleHTTPRequestHandler
from pathlib import Path
def start_httpd(directory: Path, port: int = 8000):
print(f"serving from {directory}...")
handler = partial(SimpleHTTPRequestHandler, directory=directory)
httpd = HTTPServer(('localhost', port), handler)
httpd.serve_forever()
Solution 8 - Python
If you just need a modern web static server,
deno
is an alternative file server
without any code
.
install deno with single line
https://github.com/denoland/deno_install#deno_install
file server
with single line
install deno install --allow-net --allow-read https://deno.land/std@0.125.0/http/file_server.ts
file-server
use deno file_server . --port=<port>
# Downloading https://deno.land/[email protected]/http/file_server.ts...
# HTTP server listening on http://0.0.0.0:<port>/
read more https://deno.land/manual/examples/file_server#using-the-codestdhttpcode-file-server