Last active
October 20, 2025 12:05
-
-
Save TheoLeeCJ/e07c2c91459cdba19c0b6ffe28bfdae9 to your computer and use it in GitHub Desktop.
CORS Anywhere as a single Python file
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 http.server | |
| import socketserver | |
| import requests | |
| # Removed unused imports from urllib.parse | |
| # --- Configuration --- | |
| PORT = 8080 | |
| TARGET_URL_PREFIX = "/" # The prefix in the path before the target URL (e.g. /http://target.com) | |
| # --- CORS Headers to add to the response --- | |
| CORS_HEADERS = { | |
| 'Access-Control-Allow-Origin': '*', | |
| 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', | |
| 'Access-Control-Allow-Headers': 'X-Requested-With, Content-Type, Authorization', | |
| 'Access-Control-Max-Age': '86400', # 24 hours | |
| } | |
| class CORSProxyHandler(http.server.BaseHTTPRequestHandler): | |
| def do_OPTIONS(self): | |
| """Handle preflight requests.""" | |
| self.send_response(200) | |
| # --- FIX: Explicitly add the standard HTTP Allow header --- | |
| # This header lists the methods allowed by the server on this resource. | |
| allowed_methods = CORS_HEADERS['Access-Control-Allow-Methods'] | |
| self.send_header('Allow', allowed_methods) | |
| # Add CORS headers | |
| for header, value in CORS_HEADERS.items(): | |
| self.send_header(header, value) | |
| self.end_headers() | |
| def handle_request(self): | |
| """Generic method to handle GET, POST, PUT, DELETE requests.""" | |
| # 1. Determine the target URL | |
| if self.path.startswith(TARGET_URL_PREFIX): | |
| target_url = self.path[len(TARGET_URL_PREFIX):] | |
| else: | |
| self.send_error(400, "Invalid target URL format.") | |
| return | |
| # Simple validation | |
| if not target_url.startswith(('http://', 'https://')): | |
| self.send_error(400, f"Target URL must start with http:// or https://: {target_url}") | |
| return | |
| print(f"[{self.command}] Proxying request to: {target_url}") | |
| try: | |
| # 2. Extract request body and headers for the outgoing request | |
| content_length = int(self.headers.get('Content-Length', 0)) | |
| request_body = self.rfile.read(content_length) if content_length > 0 else None | |
| # Headers to forward (excluding hop-by-hop headers and those set by requests) | |
| forward_headers = { | |
| k: v for k, v in self.headers.items() | |
| if k.lower() not in ['host', 'content-length', 'connection', 'transfer-encoding'] | |
| } | |
| # 3. Make the request to the target URL using python-requests | |
| response = requests.request( | |
| method=self.command, | |
| url=target_url, | |
| headers=forward_headers, | |
| data=request_body, | |
| allow_redirects=True, | |
| stream=True # Use streaming to handle potentially large responses | |
| ) | |
| # 4. Send the response back to the client | |
| # Send status code | |
| self.send_response(response.status_code) | |
| # Add custom CORS headers first | |
| for header, value in CORS_HEADERS.items(): | |
| self.send_header(header, value) | |
| # Forward headers from the target response | |
| for header, value in response.headers.items(): | |
| # Skip headers that might interfere with the client/proxy connection | |
| if header.lower() not in ['content-encoding', 'transfer-encoding', 'connection']: | |
| self.send_header(header, value) | |
| self.end_headers() | |
| # Stream the content to the client | |
| for chunk in response.iter_content(chunk_size=8192): | |
| if chunk: # filter out keep-alive new chunks | |
| self.wfile.write(chunk) | |
| except requests.exceptions.RequestException as e: | |
| print(f"Error during proxy request: {e}") | |
| self.send_error(500, f"Error reaching target: {e}") | |
| except Exception as e: | |
| print(f"An unexpected error occurred: {e}") | |
| self.send_error(500, "An unexpected internal error occurred.") | |
| # Map all relevant HTTP methods to the generic handler | |
| do_GET = handle_request | |
| do_POST = handle_request | |
| do_PUT = handle_request | |
| do_DELETE = handle_request | |
| do_PATCH = handle_request | |
| do_HEAD = handle_request | |
| if __name__ == "__main__": | |
| with socketserver.TCPServer(("", PORT), CORSProxyHandler) as httpd: | |
| print(f"Serving CORS proxy at port {PORT}") | |
| print(f"Usage: http://localhost:{PORT}/<target_url>") | |
| print("Press Ctrl+C to stop.") | |
| try: | |
| httpd.serve_forever() | |
| except KeyboardInterrupt: | |
| print("\nStopping server.") | |
| httpd.server_close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment