86 lines
3.1 KiB
Python
86 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import os
|
|
import sys
|
|
import http
|
|
|
|
from http.server import *
|
|
|
|
class GZHTTPRequestHandler(SimpleHTTPRequestHandler):
|
|
|
|
def send_head(self):
|
|
self.original_path = self.path
|
|
path = self.translated_path = super().translate_path(self.path)
|
|
self.content_type = super().guess_type(self.translated_path)
|
|
self.content_encoding = None
|
|
accepted = []
|
|
if 'Accept-Encoding' in self.headers:
|
|
accepted = self.headers['Accept-Encoding']
|
|
accepted = [ e.strip() for e in accepted.split(',') ]
|
|
pathgz = path + '.gz'
|
|
if os.path.isfile(pathgz) and 'gzip' in accepted:
|
|
self.translated_path = pathgz
|
|
self.content_encoding = 'gzip'
|
|
return super().send_head()
|
|
|
|
def translate_path(self, path):
|
|
if path == self.original_path:
|
|
return self.translated_path
|
|
return super().translate_path(path)
|
|
|
|
def guess_type(self, path):
|
|
if path == self.translated_path:
|
|
return self.content_type
|
|
return super().guess_type(path)
|
|
|
|
def send_response_only(self, code, message=None):
|
|
super().send_response_only(code, message)
|
|
if code == http.HTTPStatus.OK:
|
|
# disable caching
|
|
self.send_header('Cache-Control', 'no-store, must-revalidate')
|
|
self.send_header('Expires', '0')
|
|
# set content encoding
|
|
if self.content_encoding:
|
|
self.send_header('Content-Encoding', self.content_encoding)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
import argparse
|
|
import contextlib
|
|
|
|
directory = os.path.dirname(__file__ or os.getcwd())
|
|
directory = os.path.normpath(os.path.join(directory, 'html'))
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('-b', '--bind', metavar='ADDRESS', default='127.0.0.1',
|
|
help='bind to this address (default: all interfaces)')
|
|
parser.add_argument('-d', '--directory', default=directory,
|
|
help='serve this directory (default: %(default)s)')
|
|
parser.add_argument('-p', '--protocol', metavar='VERSION',
|
|
default='HTTP/1.0',
|
|
help='conform to this HTTP version (default: %(default)s)')
|
|
parser.add_argument('port', default=8000, type=int, nargs='?',
|
|
help='bind to this port (default: %(default)s)')
|
|
args = parser.parse_args()
|
|
handler_class = GZHTTPRequestHandler
|
|
|
|
# copied from http.server
|
|
class DualStackServer(ThreadingHTTPServer):
|
|
def server_bind(self):
|
|
# suppress exception when protocol is IPv4
|
|
with contextlib.suppress(Exception):
|
|
self.socket.setsockopt(
|
|
socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
|
|
return super().server_bind()
|
|
def finish_request(self, request, client_address):
|
|
self.RequestHandlerClass(request, client_address, self,
|
|
directory=args.directory)
|
|
|
|
http.server.test(
|
|
HandlerClass=handler_class,
|
|
ServerClass=DualStackServer,
|
|
port=args.port,
|
|
bind=args.bind,
|
|
protocol=args.protocol,
|
|
)
|