Skip to content

Instantly share code, notes, and snippets.

@ntohidi
Forked from dragermrb/server.py
Created October 18, 2021 05:10
Show Gist options
  • Save ntohidi/beadee1b7539a715d4dbb7c26474ecb4 to your computer and use it in GitHub Desktop.
Save ntohidi/beadee1b7539a715d4dbb7c26474ecb4 to your computer and use it in GitHub Desktop.
Python 3 HTTP Server with Basic Authentication
import http.server
import cgi
import base64
import json
from urllib.parse import urlparse, parse_qs
class CustomServerHandler(http.server.BaseHTTPRequestHandler):
def do_HEAD(self):
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
def do_AUTHHEAD(self):
self.send_response(401)
self.send_header(
'WWW-Authenticate', 'Basic realm="Demo Realm"')
self.send_header('Content-type', 'application/json')
self.end_headers()
def do_GET(self):
key = self.server.get_auth_key()
''' Present frontpage with user authentication. '''
if self.headers.get('Authorization') == None:
self.do_AUTHHEAD()
response = {
'success': False,
'error': 'No auth header received'
}
self.wfile.write(bytes(json.dumps(response), 'utf-8'))
elif self.headers.get('Authorization') == 'Basic ' + str(key):
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
getvars = self._parse_GET()
response = {
'path': self.path,
'get_vars': str(getvars)
}
base_path = urlparse(self.path).path
if base_path == '/path1':
# Do some work
pass
elif base_path == '/path2':
# Do some work
pass
self.wfile.write(bytes(json.dumps(response), 'utf-8'))
else:
self.do_AUTHHEAD()
response = {
'success': False,
'error': 'Invalid credentials'
}
self.wfile.write(bytes(json.dumps(response), 'utf-8'))
def do_POST(self):
key = self.server.get_auth_key()
''' Present frontpage with user authentication. '''
if self.headers.get('Authorization') == None:
self.do_AUTHHEAD()
response = {
'success': False,
'error': 'No auth header received'
}
self.wfile.write(bytes(json.dumps(response), 'utf-8'))
elif self.headers.get('Authorization') == 'Basic ' + str(key):
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
postvars = self._parse_POST()
getvars = self._parse_GET()
response = {
'path': self.path,
'get_vars': str(getvars),
'get_vars': str(postvars)
}
base_path = urlparse(self.path).path
if base_path == '/path1':
# Do some work
pass
elif base_path == '/path2':
# Do some work
pass
self.wfile.write(bytes(json.dumps(response), 'utf-8'))
else:
self.do_AUTHHEAD()
response = {
'success': False,
'error': 'Invalid credentials'
}
self.wfile.write(bytes(json.dumps(response), 'utf-8'))
response = {
'path': self.path,
'get_vars': str(getvars),
'get_vars': str(postvars)
}
self.wfile.write(bytes(json.dumps(response), 'utf-8'))
def _parse_POST(self):
ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
if ctype == 'multipart/form-data':
postvars = cgi.parse_multipart(self.rfile, pdict)
elif ctype == 'application/x-www-form-urlencoded':
length = int(self.headers.getheader('content-length'))
postvars = cgi.parse_qs(
self.rfile.read(length), keep_blank_values=1)
else:
postvars = {}
return postvars
def _parse_GET(self):
getvars = parse_qs(urlparse(self.path).query)
return getvars
class CustomHTTPServer(http.server.HTTPServer):
key = ''
def __init__(self, address, handlerClass=CustomServerHandler):
super().__init__(address, handlerClass)
def set_auth(self, username, password):
self.key = base64.b64encode(
bytes('%s:%s' % (username, password), 'utf-8')).decode('ascii')
def get_auth_key(self):
return self.key
if __name__ == '__main__':
server = CustomHTTPServer(, ('', 8888))
server.set_auth('demo', 'demo')
server.serve_forever()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment