Last active
December 15, 2015 03:29
-
-
Save chenzx/5194501 to your computer and use it in GitHub Desktop.
A Python Script Overrideing SimpleHTTPServer to supply HTTP response body slow-speed sending back behavior
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import SimpleHTTPServer | |
| import BaseHTTPServer | |
| import time | |
| import SocketServer | |
| import os | |
| import threading | |
| import socket | |
| PORT = 8888 | |
| 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 MySlowHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): | |
| def do_GET(self): | |
| #SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) | |
| """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.is_image_request(self.path) ): | |
| print "Make slow response body for image" | |
| READ_BUFFER_SIZE = 128; | |
| 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) | |
| buf = f.read(READ_BUFFER_SIZE) | |
| else: | |
| self.copyfile(f, self.wfile) | |
| f.close() | |
| 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) | |
| self.send_header("Content-type", ctype) | |
| fs = os.fstat(f.fileno()) | |
| self.send_header("Content-Length", str(fs[6])) | |
| #self.send_header("Last-Modified", self.date_time_string(fs.st_mtime)) | |
| self.send_header("Last-Modified", self.date_time_string(time.time())) | |
| self.send_header("Expires", self.date_time_string(time.time()+5)) | |
| self.send_header("Cache-control", "no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, no-transform") | |
| self.send_header("Pragma", "no-cache") | |
| self.end_headers() | |
| return f | |
| s = MyThreadingHTTPServer(("", PORT), MySlowHTTPRequestHandler) | |
| s.serve_forever() | |
| """ | |
| THREADS_NUM = 10 | |
| threads = [] | |
| for i in range(THREADS_NUM): | |
| s = BaseHTTPServer.HTTPServer(("", PORT), MySlowHTTPRequestHandler) | |
| s.allow_reuse_address = 1 | |
| t = threading.Thread( | |
| name='MySlowHTTPServer serving', | |
| target=s.serve_forever, | |
| kwargs={'poll_interval':0.01}) | |
| t.daemon = True # In case this function raises. | |
| threads.append((t, s)) | |
| print "threads'num = %d" % (len(threads)) | |
| for t, s in threads: | |
| t.start() | |
| for t, s in threads: | |
| t.join() | |
| """ |
Author
Author
How to make an IO exception: raise "error"
(This will cause the thread to exception-abort)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
SimpleHTTPServer has problem: one request is NOT done. another one will not start.