该脚本的主要用处是作为http服务器使用,并且可以输出请求/响应的http头部。
import http.server
import time
import socketserver
import os
import threading
import socket
PORT = 8000
class MyThreadingHTTPServer(socketserver.ThreadingTCPServer):
allow_reuse_address = 1 # Seems to make sense in testing environment
def server_bind(self):
"""Override server_bind to store the server name."""
socketserver.TCPServer.server_bind(self)
host, port = self.socket.getsockname()[:2]
self.server_name = socket.getfqdn(host)
self.server_port = port
#Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
class MyThreadingHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
def dumpRequestHeaders(self):
print( '[%s]raw_requestline=%s self.path=%s headers=\n%s\n' % (threading.current_thread(),self.raw_requestline, self.path, self.headers) )
def do_GET(self):
#if self.path.endswith(".htm") or self.path.endswith(".html") or self.path.endswith("/"):
self.dumpRequestHeaders() #Add to see WebKit version;
#
if self.path.endswith(".mp4"):
http.server.SimpleHTTPRequestHandler.do_GET(self)
return
if self.path.startswith("/ajax/"):
self.send_response(200)
self.send_header("Content-Type", "text/html") #maybe use json?
self.send_header("Cache-control", "no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, no-transform")
self.end_headers()
self.wfile.write(b"Ajax response data by python script...")
#self.wfile.close()
return
"""Serve a GET request."""
f = self.send_head()
if f:
#Get file size:
f.seek(0, os.SEEK_END)
filesize = f.tell()
f.seek(0, os.SEEK_SET)
#self.copyfile(f, self.wfile)
#print "do_GET: sending body for %s, filesize=%d" % (self.path, filesize)
bytes_sent = 0
if( self.path.endswith(".html") or self.path=="/" ):
print( "Make a manual broken response for html" )
READ_BUFFER_SIZE = 32;
buf = f.read(READ_BUFFER_SIZE)
while buf:
#time.sleep(1)
self.wfile.write(buf)
bytes_sent = bytes_sent + len(buf)
print( "%d bytes sent, %d left to send" % (bytes_sent, filesize - bytes_sent) )
if bytes_sent>80:
pass
#raise Exception("io error!")
buf = f.read(READ_BUFFER_SIZE)
else:
self.copyfile(f, self.wfile)
f.close()
#'''
#self.copyfile(f, self.wfile)
def is_image_request(self, path):
return path.lower().endswith( (".png",".jpg",".gif") )
def send_head(self):
"""
overwrite send_head to set Last-Modified & Expires to disable browser cache;
"""
path = self.translate_path(self.path)
f = None
if os.path.isdir(path):
if not self.path.endswith('/'):
# redirect browser - doing basically what apache does
self.send_response(301)
self.send_header("Location", self.path + "/")
self.end_headers()
return None
for index in "index.html", "index.htm":
index = os.path.join(path, index)
if os.path.exists(index):
path = index
break
else:
return self.list_directory(path)
ctype = self.guess_type(path)
try:
# Always read in binary mode. Opening files in text mode may cause
# newline translations, making the actual size of the content
# transmitted *less* than the content-length!
f = open(path, 'rb')
except IOError:
self.send_error(404, "File not found")
return None
self.send_response(200)
response_headers = {}
response_headers["Content-Type"]=ctype
fs = os.fstat(f.fileno())
response_headers["Content-Length"]=str(fs[6])
response_headers["Last-Modified"]=self.date_time_string(time.time())
response_headers["Expires"]=self.date_time_string(time.time()+5)
response_headers["Cache-control"]="no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, no-transform"
#simple_offline_cache needs to override this;
response_headers["Pragma"]="no-cache"
response_headers["Connection"]="close" #HTTP/1.1 assume connection reuse
response_headers_list=[]
for k, v in response_headers.items():
response_headers_list.append('%s: %s' % (k, v)) #multiple print's is not thread-safe;
self.send_header(k, v)
print( '[%s][%s]response headers=\n%s\n' % (threading.current_thread(),self.path, '\n'.join(response_headers_list)) )
self.end_headers()
return f
s = MyThreadingHTTPServer(("", PORT), MyThreadingHTTPRequestHandler)
sa = s.socket.getsockname()
print("Serving Dump-Request-Headers Test Server on", sa[0], "port", sa[1], "...")
s.serve_forever()