Skip to content

Instantly share code, notes, and snippets.

@TheoLeeCJ
Last active October 20, 2025 12:05
Show Gist options
  • Select an option

  • Save TheoLeeCJ/e07c2c91459cdba19c0b6ffe28bfdae9 to your computer and use it in GitHub Desktop.

Select an option

Save TheoLeeCJ/e07c2c91459cdba19c0b6ffe28bfdae9 to your computer and use it in GitHub Desktop.
CORS Anywhere as a single Python file
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