Skip to content

Instantly share code, notes, and snippets.

@lionelyoung
Forked from mauler/http_server_auth.py
Last active September 4, 2022 15:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save lionelyoung/8cad668d4d30fa392842fa08d50d2bc6 to your computer and use it in GitHub Desktop.
Save lionelyoung/8cad668d4d30fa392842fa08d50d2bc6 to your computer and use it in GitHub Desktop.
Python3 http.server supporting basic HTTP Auth (username/password)
# Extended python -m http.serve with --username and --password parameters for
# basic auth, based on https://gist.github.com/fxsjy/5465353
# Usage: python -m http_server_auth -u USERNAME -p PASSWORD -d .
from functools import partial
from http.server import SimpleHTTPRequestHandler, test
import base64
import os
class AuthHTTPRequestHandler(SimpleHTTPRequestHandler):
""" Main class to present webpages and authentication. """
def __init__(self, *args, **kwargs):
username = kwargs.pop("username")
password = kwargs.pop("password")
self._auth = base64.b64encode(f"{username}:{password}".encode()).decode()
super().__init__(*args)
def do_HEAD(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
def do_AUTHHEAD(self):
self.send_response(401)
self.send_header("WWW-Authenticate", 'Basic realm="Test"')
self.send_header("Content-type", "text/html")
self.end_headers()
def do_GET(self):
""" Present frontpage with user authentication. """
if self.headers.get("Authorization") == None:
self.do_AUTHHEAD()
self.wfile.write(b"no auth header received")
elif self.headers.get("Authorization") == "Basic " + self._auth:
SimpleHTTPRequestHandler.do_GET(self)
else:
self.do_AUTHHEAD()
self.wfile.write(self.headers.get("Authorization").encode())
self.wfile.write(b"not authenticated")
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--cgi", action="store_true", help="Run as CGI Server")
parser.add_argument(
"--bind",
"-b",
metavar="ADDRESS",
default="127.0.0.1",
help="Specify alternate bind address " "[default: all interfaces]",
)
parser.add_argument(
"--directory",
"-d",
default=os.getcwd(),
help="Specify alternative directory " "[default:current directory]",
)
parser.add_argument(
"port",
action="store",
default=8000,
type=int,
nargs="?",
help="Specify alternate port [default: 8000]",
)
parser.add_argument("--username", "-u", metavar="USERNAME")
parser.add_argument("--password", "-p", metavar="PASSWORD")
args = parser.parse_args()
handler_class = partial(
AuthHTTPRequestHandler,
username=args.username,
password=args.password,
directory=args.directory,
)
test(HandlerClass=handler_class, port=args.port, bind=args.bind)
@ArneBachmannDLR
Copy link

I think it's somewhat misleading to name the utility function do_AUTHHEAD. do_X methods are called by the SimpleHTTPServer directly, while do_AUTHHEAD is a utility function called from do_X. It made understanding the code later difficult for me, at least.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment