1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
   | import select import socket from http.server import BaseHTTPRequestHandler, HTTPServer from socketserver import ThreadingMixIn from urllib.parse import urlparse
 
  class RequestHandler(BaseHTTPRequestHandler):
  	def _recv_data_from_remote(self, sock): 		data = b'' 		while True: 			recv_data = sock.recv(4096) 			if not recv_data: 				break 			data += recv_data 		sock.close() 		return data
  	def send_data(self, sock, data): 		 		bytes_sent = 0 		while True: 			r = sock.send(data[bytes_sent:]) 			if r < 0: 				return r 			bytes_sent += r 			if bytes_sent == len(data): 				return bytes_sent
  	def handle_tcp(self, sock, remote): 		 		try: 			fdset = [sock, remote] 			while True: 				 				r, w, e = select.select(fdset, [], []) 				if sock in r: 					try: 						data = sock.recv(4096) 						if len(data) <= 0: 							break 						result = self.send_data(remote, data) 						if result < len(data): 							raise Exception('failed to send all data') 					except: 						pass
  				if remote in r: 					try: 						data = remote.recv(4096) 						if len(data) <= 0: 							break 						result = self.send_data(sock, data) 						if result < len(data): 							raise Exception('failed to send all data') 					except: 						pass 		except Exception as e: 			raise (e) 		finally: 			sock.close() 			remote.close()
  	def do_CONNECT(self): 		self.log_message(f"CONNECT {self.path}")
  		uri = self.path.split(":") 		host, port = uri[0], int(uri[1]) 		host_ip = socket.gethostbyname(host)
  		remote_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 		remote_sock.connect((host_ip, port)) 		 		self.wfile.write( 		    "{protocol_version} 200 Connection Established\r\n\r\n".format(protocol_version=self.protocol_version 		                                                                   ).encode() 		)
  		 		self.handle_tcp(self.connection, remote_sock)
  	
  	def do_http(self, method: str): 		self.log_message(f"{method} {self.path}") 		uri = urlparse(self.path) 		host, path = uri.hostname, uri.path 		host_ip = socket.gethostbyname(host) 		port = uri.port or 80
  		 		del self.headers['Proxy-Connection'] 		self.headers['Connection'] = 'close'
  		 		send_data = "{method} {path} {protocol_version}\r\n".format( 		    method=method, path=path, protocol_version=self.protocol_version 		) 		headers = '' 		for key, value in self.headers.items(): 			headers += "{key}: {value}\r\n".format(key=key, value=value) 		headers += '\r\n' 		send_data += headers
  		sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 		sock.connect((host_ip, port)) 		 		sock.sendall(send_data.encode()) 		try: 			data = self._recv_data_from_remote(sock) 			self.wfile.write(data) 		except: 			self.wfile.write(b"EOF")
  	def do_GET(self): 		self.do_http("GET")
  	def do_HEAD(self): 		self.do_http("HEAD")
  	def do_POST(self): 		self.do_http("POST")
 
  class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): 	pass
 
  if __name__ == '__main__': 	server = ThreadedHTTPServer(('', 8080), RequestHandler) 	server.serve_forever()
   |