Created
February 8, 2024 21:06
-
-
Save ilmich/58866d0c28af11539ae4eb4a6fd0e142 to your computer and use it in GitHub Desktop.
simple-reverse-proxy-python
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
| #!/usr/bin/env python3 | |
| from http.server import BaseHTTPRequestHandler,HTTPServer | |
| import argparse, os, random, sys, requests | |
| import http.server | |
| from socketserver import ThreadingMixIn | |
| import threading | |
| hostname = '' | |
| def merge_two_dicts(x, y): | |
| return x | y | |
| def set_header(): | |
| headers = { | |
| 'Host': hostname, | |
| 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36' | |
| } | |
| return headers | |
| class ProxyHTTPRequestHandler(BaseHTTPRequestHandler): | |
| protocol_version = 'HTTP/1.1' | |
| def do_HEAD(self): | |
| self.do_GET(body=False) | |
| return | |
| def do_GET(self, body=True): | |
| sent = False | |
| try: | |
| url = 'https://{}{}'.format(hostname, self.path) | |
| req_header = self.parse_headers() | |
| resp = requests.get(url, headers=merge_two_dicts(req_header, set_header()), allow_redirects=False) | |
| sent = True | |
| self.send_response(resp.status_code) | |
| self.send_resp_headers(resp) | |
| if body: | |
| self.wfile.write(resp.content) | |
| return | |
| finally: | |
| if not sent: | |
| self.send_error(404, 'error trying to proxy') | |
| def do_POST(self, body=True): | |
| sent = False | |
| try: | |
| url = 'https://{}{}'.format(hostname, self.path) | |
| content_len = int(self.headers.getheader('content-length', 0)) | |
| post_body = self.rfile.read(content_len) | |
| req_header = self.parse_headers() | |
| resp = requests.post(url, data=post_body, headers=merge_two_dicts(req_header, set_header()), allow_redirects=False) | |
| sent = True | |
| self.send_response(resp.status_code) | |
| self.send_resp_headers(resp) | |
| if body: | |
| self.wfile.write(resp.content) | |
| return | |
| finally: | |
| if not sent: | |
| self.send_error(404, 'error trying to proxy') | |
| def parse_headers(self): | |
| req_header = {} | |
| for line in self.headers: | |
| #line_parts = [o.strip() for o in line.split(':', 1)] | |
| #print(len(line_parts)) | |
| #if len(line_parts) == 2: | |
| # req_header[line_parts[0]] = line_parts[1] | |
| req_header[line] = self.headers.get(line) | |
| return req_header | |
| def send_resp_headers(self, resp): | |
| respheaders = resp.headers | |
| for key in respheaders: | |
| if key not in ['Content-Encoding', 'Transfer-Encoding', 'content-encoding', 'transfer-encoding', 'content-length', 'Content-Length']: | |
| self.send_header(key, respheaders[key]) | |
| self.send_header('Content-Length', len(resp.content)) | |
| self.end_headers() | |
| def log_message(self, format, *args): | |
| pass | |
| def parse_args(argv=sys.argv[1:]): | |
| parser = argparse.ArgumentParser(description='Proxy HTTP requests') | |
| parser.add_argument('--port', dest='port', type=int, default=9999, | |
| help='serve HTTP requests on specified port (default: random)') | |
| parser.add_argument('--hostname', dest='hostname', type=str, default='en.wikipedia.org', | |
| help='hostname to be processd (default: en.wikipedia.org)') | |
| args = parser.parse_args(argv) | |
| return args | |
| class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): | |
| """Handle requests in a separate thread.""" | |
| pass | |
| def main(argv=sys.argv[1:]): | |
| global hostname | |
| args = parse_args(argv) | |
| hostname = args.hostname | |
| print('http server is starting on {} port {}...'.format(args.hostname, args.port)) | |
| server_address = ('127.0.0.1', args.port) | |
| httpd = http.server.ThreadingHTTPServer(server_address, ProxyHTTPRequestHandler) | |
| print('http server is running as reverse proxy') | |
| httpd.serve_forever() | |
| if __name__ == '__main__': | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment