Repository files navigation

🚀 python-proxy

A powerful, transparent HTTP proxy server with intelligent traffic modification capabilities.

Python-Proxy Flow

**~ nginx with superpowers** • Zero-code configurationProduction-ready


✨ Overview

Python-proxy is a high-performance, asynchronous HTTP proxy server built on aiohttp that sits between clients and backend servers, allowing you to intercept, inspect, and modify HTTP traffic in real-time. Unlike traditional proxies that simply forward traffic, python-proxy provides a sophisticated hook system that enables you to transform requests and responses on-the-fly.

🎯 What Makes It Special?

💡 Think of it as ~ nginx with superpowers Get the reliability and performance of a production-grade proxy, combined with the flexibility to programmatically modify any aspect of HTTP traffic.

Common Use Cases:

  • 🔐 Add authentication headers
  • 📊 Inject analytics scripts into web pages
  • 🧪 Mock API responses for testing
  • 🔗 Rewrite URLs and links
  • 🛡️ Sanitize sensitive data
  • 🎲 Implement custom routing logic

🎨 Developer Experience First

# Zero-code configuration - just edit YAML!post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "link_rewrite"params:
from_domain: "example.com"to_domain: "example.com.local"

🟢 Start Simple: Use built-in YAML hooks for redirects, text replacement, and HTML modifications

🟡 Scale Up: Write custom Python hooks with full access to request/response data

🔵 Go Advanced: Implement rate limiting, caching, A/B testing, or external API integration

Async architecture ensures modifications don't compromise performance, handling thousands of concurrent connections efficiently.

🌍 Perfect For Every Environment

EnvironmentUse CaseBenefits
🔧 DevelopmentTest API responsesNo backend changes needed
🧪 QA/TestingInject test dataSimulate edge cases easily
🚀 ProductionContent transformationAdd security headers on-the-fly
🔬 SecurityTraffic analysisIntercept and modify requests

Seamless nginx integration for production deployments - handle SSL termination and load balancing while python-proxy focuses on intelligent content modification.

🛠️ Extensible Architecture

Built-in hooks handle common operations:

  • ↩️ 301/302 redirects
  • 📝 JSON field manipulation
  • 🏗️ HTML element modifications (XPath)
  • 🔗 Link rewriting
  • 🌐 Content fetching from external sources

Python hook system provides:

  • 🔍 Automatic discovery
  • 🎯 Decorator support
  • ⚠️ Comprehensive error handling
  • 🎛️ Full programmatic access

Whether you're a developer needing quick traffic manipulation or a DevOps engineer building sophisticated proxy infrastructure, python-proxy scales from simple scripts to enterprise deployments.


🎁 Features

  • Async/Await Architecture: Built on aiohttp for high-performance async I/O
  • 📤 Request Modification: Modify requests before they're proxied (headers, body, URL, etc.)
  • 📥 Response Modification: Modify responses after receiving from target (HTML injection, content replacement, etc.)
  • 🎣 Hook System: Simple Python-based hook system with automatic discovery
  • ⚙️ Configuration-Based Hooks: Powerful built-in hooks (redirects, rewrites, HTML/text transformation) via YAML config - no coding required!
  • 🔧 Flexible Configuration: Configure via CLI arguments, environment variables, or YAML config file
  • 🎯 Header-Based Routing: Route requests to different targets using X-Proxy-Server header

📦 Installation

# Install from source
pip install -e .# Or install dependencies directly
pip install -r requirements.txt

💡 Requirements: Python 3.8 or higher


🚀 Quick Start

💻 Basic Usage

# Start proxy on default port 8080
python-proxy
# Start with custom port
python-proxy --port 3128
# Proxy all requests to a specific target
python-proxy --target http://example.com
# Use a configuration file
python-proxy --config config.yaml

⚡ Quick Start with realmo.com.local (Default Configuration)

🎯 The default config.yaml is pre-configured for proxying realmo.com locally with automatic link rewriting!

# 1️⃣ Add to /etc/hostsecho"127.0.0.1 realmo.com.local"| sudo tee -a /etc/hosts
# 2️⃣ Set up port 80 capability (one-time)
./scripts/setup_port80.sh
# 3️⃣ Start proxy with default config
python-proxy --config config.yaml
# 4️⃣ Browse to http://realmo.com.local

✨ What this does:

  • 🔄 Proxies realmo.com.localrealmo.com:80
  • 🔗 Automatically rewrites all realmo.com links to realmo.com.local
  • 🎯 Keeps all traffic flowing through the proxy for testing/development

📚 See examples/REALMO_SETUP.md for detailed guide and customization options.

🔓 Running on Port 80 (Privileged Port)

✅ Quick Install (Recommended):

# Install wrapper and set up port 80 capability
./scripts/setup_port80.sh
# Now use from anywhere
python-proxy --host 192.168.2.7 --port 80

🔧 Manual Setup:

# One-time setup (resolves symlinks if needed)
sudo setcap 'cap_net_bind_service=+ep'$(readlink -f $(which python3))# Now run without sudo
python-proxy --host 192.168.2.7 --port 80

📚 See examples/port80_setup.md for detailed instructions and alternatives.

🌐 Using Environment Variables

export PROXY_PORT=8080
export PROXY_TARGET=http://example.com
export PROXY_HOOKS_DIR=./hooks
python-proxy

📡 Making Requests Through the Proxy

The proxy supports multiple ways to specify the backend target:

  1. X-Proxy-Server - Simple host or host:port format
  2. Default target - Configured via CLI or config file
  3. Automatic .local domains - Requests to hostname.local automatically route to hostname
# Using X-Proxy-Server (simple format)
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com" \
http://example.com/page
# Using X-Proxy-Server with custom port
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com:8080" \
http://example.com/page
# Override the Host header sent to backend
curl -x http://localhost:8080 \
-H "X-Proxy-Server: 192.168.1.100:8080" \
-H "X-Proxy-Host: myapp.example.com" \
http://example.com/page
# With default target configured
curl -x http://localhost:8080 http://example.com/page

Header Reference

  • X-Proxy-Server: Backend server as host or host:port

    • Default port: 80 (http) if not specified
    • Port 443 automatically uses HTTPS
    • Examples: example.com, example.com:8080, 192.168.1.100:3000
  • X-Proxy-Host: Override the Host header sent to backend server

    • Useful for virtual hosting or when backend expects specific hostname
    • Example: myapp.example.com

Automatic .local Domain Routing

The proxy automatically strips the .local suffix from hostnames and routes to the actual domain on port 80 (standard HTTP). Any port specified in the .local request is ignored. This is useful for local development and testing.

# Request to example.com.local routes to example.com:80
curl -x http://localhost:8080 http://example.com.local/page
# Port in .local URL is ignored - still routes to port 80
curl -x http://localhost:8080 http://api.example.com.local:8080/data
# → Routes to api.example.com:80# Configure in /etc/hosts for easy testing:# 127.0.0.1 myapp.com.local
curl -x http://localhost:8080 http://myapp.com.local/

Behavior:

  • hostname.localhostname:80
  • hostname.local:XXXXhostname:80 (port ignored)
  • Always uses HTTP (port 80), not HTTPS

Use cases:

  • Local development: Test production URLs locally
  • /etc/hosts testing: Add .local entries to route through proxy
  • Network testing: Intercept specific domains without DNS changes

Example /etc/hosts setup:

# Add .local entries that proxy will strip and forward to port 80
127.0.0.1 api.example.com.local
127.0.0.1 cdn.example.com.local

Then requests to api.example.com.local:8080 go through your proxy to api.example.com:80.

🎣 Configuration-Based Hooks

NEW! Configure powerful hooks directly in your YAML config - no Python coding required!

Perfect for redirects, URL rewrites, content modification, and more.

💡 Quick Example

# config.yamlhost: "0.0.0.0"port: 8080hook_mappings:
# Pre-hooks (execute before backend, can skip backend call)pre_hooks:
- hostname: "example.com"url_pattern: "/old-page"hook: "redirect_301"params:
location: "https://example.com/new-page"# Post-hooks (execute after backend, modify response)post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "text_rewrite"params:
pattern: "OldCompany"replacement: "NewCompany"

🔌 Built-in hooks include:

TypeHooksPurpose
⬅️ Pre-hooksredirect_301, redirect_302, gone_410, not_found_404, static_htmlExecute before backend
➡️ Post-hooksurl_rewrite, text_rewrite, link_rewrite, html_rewrite, xpath_replace_from_url, json_modifyModify responses

✨ Features:

  • 🌐 Hostname patterns with wildcards (*.example.com)
  • 🔍 URL patterns with glob (/api/*) or regex (regex:^/api/v[0-9]+/)
  • ⏭️ Pre-hooks can skip backend calls (redirects, errors)
  • 🔧 Post-hooks modify content (HTML, text, JSON)
  • 📁 Organize hooks with includes: Separate hooks by hostname into dedicated files

📚 Learn more:


🔗 Nginx Integration

Use python-proxy with nginx as a frontend reverse proxy for production deployments.

Nginx Integration

Nginx handles: SSL termination, load balancing Python-proxy handles: Hook-based content modification

📚 See examples/NginxIntegration.md for complete configuration:

  • 🌐 Proxy entire site or specific paths
  • 🎯 Dynamic backend routing based on URL patterns
  • ⚖️ Load balancing with multiple python-proxy instances
  • 🔒 Production-ready setup with SSL/TLS
  • ⚡ Performance optimization and security best practices

🐍 Creating Custom Python Hooks

🎓 New to hooks? Start with Creating Custom Hooks - For Beginners A complete step-by-step tutorial with real-world examples!

For advanced use cases, you can write custom Python hooks. Place them in a hooks directory.

💡 Simple Hook Example

Create a file hooks/my_hooks.py:

asyncdefbefore_request(request, request_data):
"""Modify request before proxying."""# Add custom headerrequest_data["headers"]["X-Custom"] ="MyValue"returnrequest_dataasyncdefafter_response(response, body):
"""Modify response after receiving."""# Modify HTML contentifb"<html>"inbody:
body=body.replace(b"</body>", b"<!-- Modified --></body>")
returnbody

Then run with:

python-proxy --hooks ./hooks --target http://example.com

🚀 Advanced Hooks with Decorators

frompython_proxy.hooksimportbefore_request, after_response@before_requestasyncdefadd_auth(request, request_data):
"""Add authentication to API requests."""if"api.example.com"inrequest_data["url"]:
request_data["headers"]["Authorization"] ="Bearer TOKEN"returnrequest_data@after_responseasyncdefinject_script(response, body):
"""Inject JavaScript into HTML pages."""content_type=response.headers.get("Content-Type", "")
if"text/html"incontent_type:
html=body.decode("utf-8", errors="ignore")
script='<script>console.log("Proxied!")</script>'html=html.replace("</head>", f"{script}</head>")
returnhtml.encode("utf-8")
returnbody

📚 Learn more:


⚙️ Configuration

📝 Configuration File (YAML)

Create config.yaml:

host: "0.0.0.0"port: 8080target_host: "http://example.com"timeout: 30hooks_dir: "./hooks"log_level: "INFO"

🔢 Configuration Priority

  1. 🥇 CLI arguments (highest priority)
  2. 🥈 Configuration file (--config)
  3. 🥉 Environment variables
  4. 4️⃣ Default values (lowest priority)

🔓 Running on Port 80

⚠️ Ports below 1024 require special permissions. The proxy provides helpful error messages and multiple solutions.

# ✅ Quick setup (recommended)
./scripts/setup_port80.sh
# 🔧 Or manually
sudo setcap 'cap_net_bind_service=+ep'$(which python3)
python-proxy --host 192.168.2.7 --port 80

🔀 Other options:

  • 🔴 Run with sudo (not recommended for production)
  • 🔀 Use iptables port forwarding
  • ⚙️ Use systemd socket activation

📚 See examples/port80_setup.md for complete guide.


🛠️ Development

📥 Install Development Dependencies

pip install -r requirements-dev.txt

🧪 Run Tests

# Run all tests
pytest
# Run with coverage
pytest --cov=python_proxy
# Run specific test file
pytest tests/test_config.py

🔍 Linting

# Run ruff linter
ruff check .# Auto-fix issues
ruff check --fix .

🎯 Use Cases

Use CaseDescriptionBenefits
🕷️ Web ScrapingModify headers, inject credentialsBypass restrictions
🔧 DevelopmentTest different API responsesNo backend changes
🔐 Security TestingAnalyze and modify trafficFind vulnerabilities
💉 Content InjectionAdd scripts, styles, or contentTesting & analytics
🧪 API TestingModify requests/responsesSimulate edge cases
📊 Traffic AnalysisLog and analyze HTTP trafficDebug & monitor

📜 License

Copyright (C) 2025 Sergey Porfirievparf@difive.com

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

📄 License: GPL v2 - See LICENSE file for details.


Made with ❤️ by Sergey Porfiriev

⭐ Star this repo if you find it useful! • 🐛 Report issues • 💡 Contribute

About

Transparent Python Proxy (~ nginx), allows modification of select pages BEFORE proxying or AFTER

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

🚀 python-proxy

A powerful, transparent HTTP proxy server with intelligent traffic modification capabilities.

Python-Proxy Flow

**~ nginx with superpowers** • Zero-code configurationProduction-ready


✨ Overview

Python-proxy is a high-performance, asynchronous HTTP proxy server built on aiohttp that sits between clients and backend servers, allowing you to intercept, inspect, and modify HTTP traffic in real-time. Unlike traditional proxies that simply forward traffic, python-proxy provides a sophisticated hook system that enables you to transform requests and responses on-the-fly.

🎯 What Makes It Special?

💡 Think of it as ~ nginx with superpowers Get the reliability and performance of a production-grade proxy, combined with the flexibility to programmatically modify any aspect of HTTP traffic.

Common Use Cases:

  • 🔐 Add authentication headers
  • 📊 Inject analytics scripts into web pages
  • 🧪 Mock API responses for testing
  • 🔗 Rewrite URLs and links
  • 🛡️ Sanitize sensitive data
  • 🎲 Implement custom routing logic

🎨 Developer Experience First

# Zero-code configuration - just edit YAML!post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "link_rewrite"params:
from_domain: "example.com"to_domain: "example.com.local"

🟢 Start Simple: Use built-in YAML hooks for redirects, text replacement, and HTML modifications

🟡 Scale Up: Write custom Python hooks with full access to request/response data

🔵 Go Advanced: Implement rate limiting, caching, A/B testing, or external API integration

Async architecture ensures modifications don't compromise performance, handling thousands of concurrent connections efficiently.

🌍 Perfect For Every Environment

EnvironmentUse CaseBenefits
🔧 DevelopmentTest API responsesNo backend changes needed
🧪 QA/TestingInject test dataSimulate edge cases easily
🚀 ProductionContent transformationAdd security headers on-the-fly
🔬 SecurityTraffic analysisIntercept and modify requests

Seamless nginx integration for production deployments - handle SSL termination and load balancing while python-proxy focuses on intelligent content modification.

🛠️ Extensible Architecture

Built-in hooks handle common operations:

  • ↩️ 301/302 redirects
  • 📝 JSON field manipulation
  • 🏗️ HTML element modifications (XPath)
  • 🔗 Link rewriting
  • 🌐 Content fetching from external sources

Python hook system provides:

  • 🔍 Automatic discovery
  • 🎯 Decorator support
  • ⚠️ Comprehensive error handling
  • 🎛️ Full programmatic access

Whether you're a developer needing quick traffic manipulation or a DevOps engineer building sophisticated proxy infrastructure, python-proxy scales from simple scripts to enterprise deployments.


🎁 Features

  • Async/Await Architecture: Built on aiohttp for high-performance async I/O
  • 📤 Request Modification: Modify requests before they're proxied (headers, body, URL, etc.)
  • 📥 Response Modification: Modify responses after receiving from target (HTML injection, content replacement, etc.)
  • 🎣 Hook System: Simple Python-based hook system with automatic discovery
  • ⚙️ Configuration-Based Hooks: Powerful built-in hooks (redirects, rewrites, HTML/text transformation) via YAML config - no coding required!
  • 🔧 Flexible Configuration: Configure via CLI arguments, environment variables, or YAML config file
  • 🎯 Header-Based Routing: Route requests to different targets using X-Proxy-Server header

📦 Installation

# Install from source
pip install -e .# Or install dependencies directly
pip install -r requirements.txt

💡 Requirements: Python 3.8 or higher


🚀 Quick Start

💻 Basic Usage

# Start proxy on default port 8080
python-proxy
# Start with custom port
python-proxy --port 3128
# Proxy all requests to a specific target
python-proxy --target http://example.com
# Use a configuration file
python-proxy --config config.yaml

⚡ Quick Start with realmo.com.local (Default Configuration)

🎯 The default config.yaml is pre-configured for proxying realmo.com locally with automatic link rewriting!

# 1️⃣ Add to /etc/hostsecho"127.0.0.1 realmo.com.local"| sudo tee -a /etc/hosts
# 2️⃣ Set up port 80 capability (one-time)
./scripts/setup_port80.sh
# 3️⃣ Start proxy with default config
python-proxy --config config.yaml
# 4️⃣ Browse to http://realmo.com.local

✨ What this does:

  • 🔄 Proxies realmo.com.localrealmo.com:80
  • 🔗 Automatically rewrites all realmo.com links to realmo.com.local
  • 🎯 Keeps all traffic flowing through the proxy for testing/development

📚 See examples/REALMO_SETUP.md for detailed guide and customization options.

🔓 Running on Port 80 (Privileged Port)

✅ Quick Install (Recommended):

# Install wrapper and set up port 80 capability
./scripts/setup_port80.sh
# Now use from anywhere
python-proxy --host 192.168.2.7 --port 80

🔧 Manual Setup:

# One-time setup (resolves symlinks if needed)
sudo setcap 'cap_net_bind_service=+ep'$(readlink -f $(which python3))# Now run without sudo
python-proxy --host 192.168.2.7 --port 80

📚 See examples/port80_setup.md for detailed instructions and alternatives.

🌐 Using Environment Variables

export PROXY_PORT=8080
export PROXY_TARGET=http://example.com
export PROXY_HOOKS_DIR=./hooks
python-proxy

📡 Making Requests Through the Proxy

The proxy supports multiple ways to specify the backend target:

  1. X-Proxy-Server - Simple host or host:port format
  2. Default target - Configured via CLI or config file
  3. Automatic .local domains - Requests to hostname.local automatically route to hostname
# Using X-Proxy-Server (simple format)
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com" \
http://example.com/page
# Using X-Proxy-Server with custom port
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com:8080" \
http://example.com/page
# Override the Host header sent to backend
curl -x http://localhost:8080 \
-H "X-Proxy-Server: 192.168.1.100:8080" \
-H "X-Proxy-Host: myapp.example.com" \
http://example.com/page
# With default target configured
curl -x http://localhost:8080 http://example.com/page

Header Reference

  • X-Proxy-Server: Backend server as host or host:port

    • Default port: 80 (http) if not specified
    • Port 443 automatically uses HTTPS
    • Examples: example.com, example.com:8080, 192.168.1.100:3000
  • X-Proxy-Host: Override the Host header sent to backend server

    • Useful for virtual hosting or when backend expects specific hostname
    • Example: myapp.example.com

Automatic .local Domain Routing

The proxy automatically strips the .local suffix from hostnames and routes to the actual domain on port 80 (standard HTTP). Any port specified in the .local request is ignored. This is useful for local development and testing.

# Request to example.com.local routes to example.com:80
curl -x http://localhost:8080 http://example.com.local/page
# Port in .local URL is ignored - still routes to port 80
curl -x http://localhost:8080 http://api.example.com.local:8080/data
# → Routes to api.example.com:80# Configure in /etc/hosts for easy testing:# 127.0.0.1 myapp.com.local
curl -x http://localhost:8080 http://myapp.com.local/

Behavior:

  • hostname.localhostname:80
  • hostname.local:XXXXhostname:80 (port ignored)
  • Always uses HTTP (port 80), not HTTPS

Use cases:

  • Local development: Test production URLs locally
  • /etc/hosts testing: Add .local entries to route through proxy
  • Network testing: Intercept specific domains without DNS changes

Example /etc/hosts setup:

# Add .local entries that proxy will strip and forward to port 80
127.0.0.1 api.example.com.local
127.0.0.1 cdn.example.com.local

Then requests to api.example.com.local:8080 go through your proxy to api.example.com:80.

🎣 Configuration-Based Hooks

NEW! Configure powerful hooks directly in your YAML config - no Python coding required!

Perfect for redirects, URL rewrites, content modification, and more.

💡 Quick Example

# config.yamlhost: "0.0.0.0"port: 8080hook_mappings:
# Pre-hooks (execute before backend, can skip backend call)pre_hooks:
- hostname: "example.com"url_pattern: "/old-page"hook: "redirect_301"params:
location: "https://example.com/new-page"# Post-hooks (execute after backend, modify response)post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "text_rewrite"params:
pattern: "OldCompany"replacement: "NewCompany"

🔌 Built-in hooks include:

TypeHooksPurpose
⬅️ Pre-hooksredirect_301, redirect_302, gone_410, not_found_404, static_htmlExecute before backend
➡️ Post-hooksurl_rewrite, text_rewrite, link_rewrite, html_rewrite, xpath_replace_from_url, json_modifyModify responses

✨ Features:

  • 🌐 Hostname patterns with wildcards (*.example.com)
  • 🔍 URL patterns with glob (/api/*) or regex (regex:^/api/v[0-9]+/)
  • ⏭️ Pre-hooks can skip backend calls (redirects, errors)
  • 🔧 Post-hooks modify content (HTML, text, JSON)
  • 📁 Organize hooks with includes: Separate hooks by hostname into dedicated files

📚 Learn more:


🔗 Nginx Integration

Use python-proxy with nginx as a frontend reverse proxy for production deployments.

Nginx Integration

Nginx handles: SSL termination, load balancing Python-proxy handles: Hook-based content modification

📚 See examples/NginxIntegration.md for complete configuration:

  • 🌐 Proxy entire site or specific paths
  • 🎯 Dynamic backend routing based on URL patterns
  • ⚖️ Load balancing with multiple python-proxy instances
  • 🔒 Production-ready setup with SSL/TLS
  • ⚡ Performance optimization and security best practices

🐍 Creating Custom Python Hooks

🎓 New to hooks? Start with Creating Custom Hooks - For Beginners A complete step-by-step tutorial with real-world examples!

For advanced use cases, you can write custom Python hooks. Place them in a hooks directory.

💡 Simple Hook Example

Create a file hooks/my_hooks.py:

asyncdefbefore_request(request, request_data):
"""Modify request before proxying."""# Add custom headerrequest_data["headers"]["X-Custom"] ="MyValue"returnrequest_dataasyncdefafter_response(response, body):
"""Modify response after receiving."""# Modify HTML contentifb"<html>"inbody:
body=body.replace(b"</body>", b"<!-- Modified --></body>")
returnbody

Then run with:

python-proxy --hooks ./hooks --target http://example.com

🚀 Advanced Hooks with Decorators

frompython_proxy.hooksimportbefore_request, after_response@before_requestasyncdefadd_auth(request, request_data):
"""Add authentication to API requests."""if"api.example.com"inrequest_data["url"]:
request_data["headers"]["Authorization"] ="Bearer TOKEN"returnrequest_data@after_responseasyncdefinject_script(response, body):
"""Inject JavaScript into HTML pages."""content_type=response.headers.get("Content-Type", "")
if"text/html"incontent_type:
html=body.decode("utf-8", errors="ignore")
script='<script>console.log("Proxied!")</script>'html=html.replace("</head>", f"{script}</head>")
returnhtml.encode("utf-8")
returnbody

📚 Learn more:


⚙️ Configuration

📝 Configuration File (YAML)

Create config.yaml:

host: "0.0.0.0"port: 8080target_host: "http://example.com"timeout: 30hooks_dir: "./hooks"log_level: "INFO"

🔢 Configuration Priority

  1. 🥇 CLI arguments (highest priority)
  2. 🥈 Configuration file (--config)
  3. 🥉 Environment variables
  4. 4️⃣ Default values (lowest priority)

🔓 Running on Port 80

⚠️ Ports below 1024 require special permissions. The proxy provides helpful error messages and multiple solutions.

# ✅ Quick setup (recommended)
./scripts/setup_port80.sh
# 🔧 Or manually
sudo setcap 'cap_net_bind_service=+ep'$(which python3)
python-proxy --host 192.168.2.7 --port 80

🔀 Other options:

  • 🔴 Run with sudo (not recommended for production)
  • 🔀 Use iptables port forwarding
  • ⚙️ Use systemd socket activation

📚 See examples/port80_setup.md for complete guide.


🛠️ Development

📥 Install Development Dependencies

pip install -r requirements-dev.txt

🧪 Run Tests

# Run all tests
pytest
# Run with coverage
pytest --cov=python_proxy
# Run specific test file
pytest tests/test_config.py

🔍 Linting

# Run ruff linter
ruff check .# Auto-fix issues
ruff check --fix .

🎯 Use Cases

Use CaseDescriptionBenefits
🕷️ Web ScrapingModify headers, inject credentialsBypass restrictions
🔧 DevelopmentTest different API responsesNo backend changes
🔐 Security TestingAnalyze and modify trafficFind vulnerabilities
💉 Content InjectionAdd scripts, styles, or contentTesting & analytics
🧪 API TestingModify requests/responsesSimulate edge cases
📊 Traffic AnalysisLog and analyze HTTP trafficDebug & monitor

📜 License

Copyright (C) 2025 Sergey Porfirievparf@difive.com

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

📄 License: GPL v2 - See LICENSE file for details.


Made with ❤️ by Sergey Porfiriev

⭐ Star this repo if you find it useful! • 🐛 Report issues • 💡 Contribute

About

Transparent Python Proxy (~ nginx), allows modification of select pages BEFORE proxying or AFTER

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

🚀 python-proxy

A powerful, transparent HTTP proxy server with intelligent traffic modification capabilities.

Python-Proxy Flow

**~ nginx with superpowers** • Zero-code configurationProduction-ready


✨ Overview

Python-proxy is a high-performance, asynchronous HTTP proxy server built on aiohttp that sits between clients and backend servers, allowing you to intercept, inspect, and modify HTTP traffic in real-time. Unlike traditional proxies that simply forward traffic, python-proxy provides a sophisticated hook system that enables you to transform requests and responses on-the-fly.

🎯 What Makes It Special?

💡 Think of it as ~ nginx with superpowers Get the reliability and performance of a production-grade proxy, combined with the flexibility to programmatically modify any aspect of HTTP traffic.

Common Use Cases:

  • 🔐 Add authentication headers
  • 📊 Inject analytics scripts into web pages
  • 🧪 Mock API responses for testing
  • 🔗 Rewrite URLs and links
  • 🛡️ Sanitize sensitive data
  • 🎲 Implement custom routing logic

🎨 Developer Experience First

# Zero-code configuration - just edit YAML!post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "link_rewrite"params:
from_domain: "example.com"to_domain: "example.com.local"

🟢 Start Simple: Use built-in YAML hooks for redirects, text replacement, and HTML modifications

🟡 Scale Up: Write custom Python hooks with full access to request/response data

🔵 Go Advanced: Implement rate limiting, caching, A/B testing, or external API integration

Async architecture ensures modifications don't compromise performance, handling thousands of concurrent connections efficiently.

🌍 Perfect For Every Environment

EnvironmentUse CaseBenefits
🔧 DevelopmentTest API responsesNo backend changes needed
🧪 QA/TestingInject test dataSimulate edge cases easily
🚀 ProductionContent transformationAdd security headers on-the-fly
🔬 SecurityTraffic analysisIntercept and modify requests

Seamless nginx integration for production deployments - handle SSL termination and load balancing while python-proxy focuses on intelligent content modification.

🛠️ Extensible Architecture

Built-in hooks handle common operations:

  • ↩️ 301/302 redirects
  • 📝 JSON field manipulation
  • 🏗️ HTML element modifications (XPath)
  • 🔗 Link rewriting
  • 🌐 Content fetching from external sources

Python hook system provides:

  • 🔍 Automatic discovery
  • 🎯 Decorator support
  • ⚠️ Comprehensive error handling
  • 🎛️ Full programmatic access

Whether you're a developer needing quick traffic manipulation or a DevOps engineer building sophisticated proxy infrastructure, python-proxy scales from simple scripts to enterprise deployments.


🎁 Features

  • Async/Await Architecture: Built on aiohttp for high-performance async I/O
  • 📤 Request Modification: Modify requests before they're proxied (headers, body, URL, etc.)
  • 📥 Response Modification: Modify responses after receiving from target (HTML injection, content replacement, etc.)
  • 🎣 Hook System: Simple Python-based hook system with automatic discovery
  • ⚙️ Configuration-Based Hooks: Powerful built-in hooks (redirects, rewrites, HTML/text transformation) via YAML config - no coding required!
  • 🔧 Flexible Configuration: Configure via CLI arguments, environment variables, or YAML config file
  • 🎯 Header-Based Routing: Route requests to different targets using X-Proxy-Server header

📦 Installation

# Install from source
pip install -e .# Or install dependencies directly
pip install -r requirements.txt

💡 Requirements: Python 3.8 or higher


🚀 Quick Start

💻 Basic Usage

# Start proxy on default port 8080
python-proxy
# Start with custom port
python-proxy --port 3128
# Proxy all requests to a specific target
python-proxy --target http://example.com
# Use a configuration file
python-proxy --config config.yaml

⚡ Quick Start with realmo.com.local (Default Configuration)

🎯 The default config.yaml is pre-configured for proxying realmo.com locally with automatic link rewriting!

# 1️⃣ Add to /etc/hostsecho"127.0.0.1 realmo.com.local"| sudo tee -a /etc/hosts
# 2️⃣ Set up port 80 capability (one-time)
./scripts/setup_port80.sh
# 3️⃣ Start proxy with default config
python-proxy --config config.yaml
# 4️⃣ Browse to http://realmo.com.local

✨ What this does:

  • 🔄 Proxies realmo.com.localrealmo.com:80
  • 🔗 Automatically rewrites all realmo.com links to realmo.com.local
  • 🎯 Keeps all traffic flowing through the proxy for testing/development

📚 See examples/REALMO_SETUP.md for detailed guide and customization options.

🔓 Running on Port 80 (Privileged Port)

✅ Quick Install (Recommended):

# Install wrapper and set up port 80 capability
./scripts/setup_port80.sh
# Now use from anywhere
python-proxy --host 192.168.2.7 --port 80

🔧 Manual Setup:

# One-time setup (resolves symlinks if needed)
sudo setcap 'cap_net_bind_service=+ep'$(readlink -f $(which python3))# Now run without sudo
python-proxy --host 192.168.2.7 --port 80

📚 See examples/port80_setup.md for detailed instructions and alternatives.

🌐 Using Environment Variables

export PROXY_PORT=8080
export PROXY_TARGET=http://example.com
export PROXY_HOOKS_DIR=./hooks
python-proxy

📡 Making Requests Through the Proxy

The proxy supports multiple ways to specify the backend target:

  1. X-Proxy-Server - Simple host or host:port format
  2. Default target - Configured via CLI or config file
  3. Automatic .local domains - Requests to hostname.local automatically route to hostname
# Using X-Proxy-Server (simple format)
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com" \
http://example.com/page
# Using X-Proxy-Server with custom port
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com:8080" \
http://example.com/page
# Override the Host header sent to backend
curl -x http://localhost:8080 \
-H "X-Proxy-Server: 192.168.1.100:8080" \
-H "X-Proxy-Host: myapp.example.com" \
http://example.com/page
# With default target configured
curl -x http://localhost:8080 http://example.com/page

Header Reference

  • X-Proxy-Server: Backend server as host or host:port

    • Default port: 80 (http) if not specified
    • Port 443 automatically uses HTTPS
    • Examples: example.com, example.com:8080, 192.168.1.100:3000
  • X-Proxy-Host: Override the Host header sent to backend server

    • Useful for virtual hosting or when backend expects specific hostname
    • Example: myapp.example.com

Automatic .local Domain Routing

The proxy automatically strips the .local suffix from hostnames and routes to the actual domain on port 80 (standard HTTP). Any port specified in the .local request is ignored. This is useful for local development and testing.

# Request to example.com.local routes to example.com:80
curl -x http://localhost:8080 http://example.com.local/page
# Port in .local URL is ignored - still routes to port 80
curl -x http://localhost:8080 http://api.example.com.local:8080/data
# → Routes to api.example.com:80# Configure in /etc/hosts for easy testing:# 127.0.0.1 myapp.com.local
curl -x http://localhost:8080 http://myapp.com.local/

Behavior:

  • hostname.localhostname:80
  • hostname.local:XXXXhostname:80 (port ignored)
  • Always uses HTTP (port 80), not HTTPS

Use cases:

  • Local development: Test production URLs locally
  • /etc/hosts testing: Add .local entries to route through proxy
  • Network testing: Intercept specific domains without DNS changes

Example /etc/hosts setup:

# Add .local entries that proxy will strip and forward to port 80
127.0.0.1 api.example.com.local
127.0.0.1 cdn.example.com.local

Then requests to api.example.com.local:8080 go through your proxy to api.example.com:80.

🎣 Configuration-Based Hooks

NEW! Configure powerful hooks directly in your YAML config - no Python coding required!

Perfect for redirects, URL rewrites, content modification, and more.

💡 Quick Example

# config.yamlhost: "0.0.0.0"port: 8080hook_mappings:
# Pre-hooks (execute before backend, can skip backend call)pre_hooks:
- hostname: "example.com"url_pattern: "/old-page"hook: "redirect_301"params:
location: "https://example.com/new-page"# Post-hooks (execute after backend, modify response)post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "text_rewrite"params:
pattern: "OldCompany"replacement: "NewCompany"

🔌 Built-in hooks include:

TypeHooksPurpose
⬅️ Pre-hooksredirect_301, redirect_302, gone_410, not_found_404, static_htmlExecute before backend
➡️ Post-hooksurl_rewrite, text_rewrite, link_rewrite, html_rewrite, xpath_replace_from_url, json_modifyModify responses

✨ Features:

  • 🌐 Hostname patterns with wildcards (*.example.com)
  • 🔍 URL patterns with glob (/api/*) or regex (regex:^/api/v[0-9]+/)
  • ⏭️ Pre-hooks can skip backend calls (redirects, errors)
  • 🔧 Post-hooks modify content (HTML, text, JSON)
  • 📁 Organize hooks with includes: Separate hooks by hostname into dedicated files

📚 Learn more:


🔗 Nginx Integration

Use python-proxy with nginx as a frontend reverse proxy for production deployments.

Nginx Integration

Nginx handles: SSL termination, load balancing Python-proxy handles: Hook-based content modification

📚 See examples/NginxIntegration.md for complete configuration:

  • 🌐 Proxy entire site or specific paths
  • 🎯 Dynamic backend routing based on URL patterns
  • ⚖️ Load balancing with multiple python-proxy instances
  • 🔒 Production-ready setup with SSL/TLS
  • ⚡ Performance optimization and security best practices

🐍 Creating Custom Python Hooks

🎓 New to hooks? Start with Creating Custom Hooks - For Beginners A complete step-by-step tutorial with real-world examples!

For advanced use cases, you can write custom Python hooks. Place them in a hooks directory.

💡 Simple Hook Example

Create a file hooks/my_hooks.py:

asyncdefbefore_request(request, request_data):
"""Modify request before proxying."""# Add custom headerrequest_data["headers"]["X-Custom"] ="MyValue"returnrequest_dataasyncdefafter_response(response, body):
"""Modify response after receiving."""# Modify HTML contentifb"<html>"inbody:
body=body.replace(b"</body>", b"<!-- Modified --></body>")
returnbody

Then run with:

python-proxy --hooks ./hooks --target http://example.com

🚀 Advanced Hooks with Decorators

frompython_proxy.hooksimportbefore_request, after_response@before_requestasyncdefadd_auth(request, request_data):
"""Add authentication to API requests."""if"api.example.com"inrequest_data["url"]:
request_data["headers"]["Authorization"] ="Bearer TOKEN"returnrequest_data@after_responseasyncdefinject_script(response, body):
"""Inject JavaScript into HTML pages."""content_type=response.headers.get("Content-Type", "")
if"text/html"incontent_type:
html=body.decode("utf-8", errors="ignore")
script='<script>console.log("Proxied!")</script>'html=html.replace("</head>", f"{script}</head>")
returnhtml.encode("utf-8")
returnbody

📚 Learn more:


⚙️ Configuration

📝 Configuration File (YAML)

Create config.yaml:

host: "0.0.0.0"port: 8080target_host: "http://example.com"timeout: 30hooks_dir: "./hooks"log_level: "INFO"

🔢 Configuration Priority

  1. 🥇 CLI arguments (highest priority)
  2. 🥈 Configuration file (--config)
  3. 🥉 Environment variables
  4. 4️⃣ Default values (lowest priority)

🔓 Running on Port 80

⚠️ Ports below 1024 require special permissions. The proxy provides helpful error messages and multiple solutions.

# ✅ Quick setup (recommended)
./scripts/setup_port80.sh
# 🔧 Or manually
sudo setcap 'cap_net_bind_service=+ep'$(which python3)
python-proxy --host 192.168.2.7 --port 80

🔀 Other options:

  • 🔴 Run with sudo (not recommended for production)
  • 🔀 Use iptables port forwarding
  • ⚙️ Use systemd socket activation

📚 See examples/port80_setup.md for complete guide.


🛠️ Development

📥 Install Development Dependencies

pip install -r requirements-dev.txt

🧪 Run Tests

# Run all tests
pytest
# Run with coverage
pytest --cov=python_proxy
# Run specific test file
pytest tests/test_config.py

🔍 Linting

# Run ruff linter
ruff check .# Auto-fix issues
ruff check --fix .

🎯 Use Cases

Use CaseDescriptionBenefits
🕷️ Web ScrapingModify headers, inject credentialsBypass restrictions
🔧 DevelopmentTest different API responsesNo backend changes
🔐 Security TestingAnalyze and modify trafficFind vulnerabilities
💉 Content InjectionAdd scripts, styles, or contentTesting & analytics
🧪 API TestingModify requests/responsesSimulate edge cases
📊 Traffic AnalysisLog and analyze HTTP trafficDebug & monitor

📜 License

Copyright (C) 2025 Sergey Porfirievparf@difive.com

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

📄 License: GPL v2 - See LICENSE file for details.


Made with ❤️ by Sergey Porfiriev

⭐ Star this repo if you find it useful! • 🐛 Report issues • 💡 Contribute

About

Transparent Python Proxy (~ nginx), allows modification of select pages BEFORE proxying or AFTER

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

🚀 python-proxy

A powerful, transparent HTTP proxy server with intelligent traffic modification capabilities.

Python-Proxy Flow

**~ nginx with superpowers** • Zero-code configurationProduction-ready


✨ Overview

Python-proxy is a high-performance, asynchronous HTTP proxy server built on aiohttp that sits between clients and backend servers, allowing you to intercept, inspect, and modify HTTP traffic in real-time. Unlike traditional proxies that simply forward traffic, python-proxy provides a sophisticated hook system that enables you to transform requests and responses on-the-fly.

🎯 What Makes It Special?

💡 Think of it as ~ nginx with superpowers Get the reliability and performance of a production-grade proxy, combined with the flexibility to programmatically modify any aspect of HTTP traffic.

Common Use Cases:

  • 🔐 Add authentication headers
  • 📊 Inject analytics scripts into web pages
  • 🧪 Mock API responses for testing
  • 🔗 Rewrite URLs and links
  • 🛡️ Sanitize sensitive data
  • 🎲 Implement custom routing logic

🎨 Developer Experience First

# Zero-code configuration - just edit YAML!post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "link_rewrite"params:
from_domain: "example.com"to_domain: "example.com.local"

🟢 Start Simple: Use built-in YAML hooks for redirects, text replacement, and HTML modifications

🟡 Scale Up: Write custom Python hooks with full access to request/response data

🔵 Go Advanced: Implement rate limiting, caching, A/B testing, or external API integration

Async architecture ensures modifications don't compromise performance, handling thousands of concurrent connections efficiently.

🌍 Perfect For Every Environment

EnvironmentUse CaseBenefits
🔧 DevelopmentTest API responsesNo backend changes needed
🧪 QA/TestingInject test dataSimulate edge cases easily
🚀 ProductionContent transformationAdd security headers on-the-fly
🔬 SecurityTraffic analysisIntercept and modify requests

Seamless nginx integration for production deployments - handle SSL termination and load balancing while python-proxy focuses on intelligent content modification.

🛠️ Extensible Architecture

Built-in hooks handle common operations:

  • ↩️ 301/302 redirects
  • 📝 JSON field manipulation
  • 🏗️ HTML element modifications (XPath)
  • 🔗 Link rewriting
  • 🌐 Content fetching from external sources

Python hook system provides:

  • 🔍 Automatic discovery
  • 🎯 Decorator support
  • ⚠️ Comprehensive error handling
  • 🎛️ Full programmatic access

Whether you're a developer needing quick traffic manipulation or a DevOps engineer building sophisticated proxy infrastructure, python-proxy scales from simple scripts to enterprise deployments.


🎁 Features

  • Async/Await Architecture: Built on aiohttp for high-performance async I/O
  • 📤 Request Modification: Modify requests before they're proxied (headers, body, URL, etc.)
  • 📥 Response Modification: Modify responses after receiving from target (HTML injection, content replacement, etc.)
  • 🎣 Hook System: Simple Python-based hook system with automatic discovery
  • ⚙️ Configuration-Based Hooks: Powerful built-in hooks (redirects, rewrites, HTML/text transformation) via YAML config - no coding required!
  • 🔧 Flexible Configuration: Configure via CLI arguments, environment variables, or YAML config file
  • 🎯 Header-Based Routing: Route requests to different targets using X-Proxy-Server header

📦 Installation

# Install from source
pip install -e .# Or install dependencies directly
pip install -r requirements.txt

💡 Requirements: Python 3.8 or higher


🚀 Quick Start

💻 Basic Usage

# Start proxy on default port 8080
python-proxy
# Start with custom port
python-proxy --port 3128
# Proxy all requests to a specific target
python-proxy --target http://example.com
# Use a configuration file
python-proxy --config config.yaml

⚡ Quick Start with realmo.com.local (Default Configuration)

🎯 The default config.yaml is pre-configured for proxying realmo.com locally with automatic link rewriting!

# 1️⃣ Add to /etc/hostsecho"127.0.0.1 realmo.com.local"| sudo tee -a /etc/hosts
# 2️⃣ Set up port 80 capability (one-time)
./scripts/setup_port80.sh
# 3️⃣ Start proxy with default config
python-proxy --config config.yaml
# 4️⃣ Browse to http://realmo.com.local

✨ What this does:

  • 🔄 Proxies realmo.com.localrealmo.com:80
  • 🔗 Automatically rewrites all realmo.com links to realmo.com.local
  • 🎯 Keeps all traffic flowing through the proxy for testing/development

📚 See examples/REALMO_SETUP.md for detailed guide and customization options.

🔓 Running on Port 80 (Privileged Port)

✅ Quick Install (Recommended):

# Install wrapper and set up port 80 capability
./scripts/setup_port80.sh
# Now use from anywhere
python-proxy --host 192.168.2.7 --port 80

🔧 Manual Setup:

# One-time setup (resolves symlinks if needed)
sudo setcap 'cap_net_bind_service=+ep'$(readlink -f $(which python3))# Now run without sudo
python-proxy --host 192.168.2.7 --port 80

📚 See examples/port80_setup.md for detailed instructions and alternatives.

🌐 Using Environment Variables

export PROXY_PORT=8080
export PROXY_TARGET=http://example.com
export PROXY_HOOKS_DIR=./hooks
python-proxy

📡 Making Requests Through the Proxy

The proxy supports multiple ways to specify the backend target:

  1. X-Proxy-Server - Simple host or host:port format
  2. Default target - Configured via CLI or config file
  3. Automatic .local domains - Requests to hostname.local automatically route to hostname
# Using X-Proxy-Server (simple format)
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com" \
http://example.com/page
# Using X-Proxy-Server with custom port
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com:8080" \
http://example.com/page
# Override the Host header sent to backend
curl -x http://localhost:8080 \
-H "X-Proxy-Server: 192.168.1.100:8080" \
-H "X-Proxy-Host: myapp.example.com" \
http://example.com/page
# With default target configured
curl -x http://localhost:8080 http://example.com/page

Header Reference

  • X-Proxy-Server: Backend server as host or host:port

    • Default port: 80 (http) if not specified
    • Port 443 automatically uses HTTPS
    • Examples: example.com, example.com:8080, 192.168.1.100:3000
  • X-Proxy-Host: Override the Host header sent to backend server

    • Useful for virtual hosting or when backend expects specific hostname
    • Example: myapp.example.com

Automatic .local Domain Routing

The proxy automatically strips the .local suffix from hostnames and routes to the actual domain on port 80 (standard HTTP). Any port specified in the .local request is ignored. This is useful for local development and testing.

# Request to example.com.local routes to example.com:80
curl -x http://localhost:8080 http://example.com.local/page
# Port in .local URL is ignored - still routes to port 80
curl -x http://localhost:8080 http://api.example.com.local:8080/data
# → Routes to api.example.com:80# Configure in /etc/hosts for easy testing:# 127.0.0.1 myapp.com.local
curl -x http://localhost:8080 http://myapp.com.local/

Behavior:

  • hostname.localhostname:80
  • hostname.local:XXXXhostname:80 (port ignored)
  • Always uses HTTP (port 80), not HTTPS

Use cases:

  • Local development: Test production URLs locally
  • /etc/hosts testing: Add .local entries to route through proxy
  • Network testing: Intercept specific domains without DNS changes

Example /etc/hosts setup:

# Add .local entries that proxy will strip and forward to port 80
127.0.0.1 api.example.com.local
127.0.0.1 cdn.example.com.local

Then requests to api.example.com.local:8080 go through your proxy to api.example.com:80.

🎣 Configuration-Based Hooks

NEW! Configure powerful hooks directly in your YAML config - no Python coding required!

Perfect for redirects, URL rewrites, content modification, and more.

💡 Quick Example

# config.yamlhost: "0.0.0.0"port: 8080hook_mappings:
# Pre-hooks (execute before backend, can skip backend call)pre_hooks:
- hostname: "example.com"url_pattern: "/old-page"hook: "redirect_301"params:
location: "https://example.com/new-page"# Post-hooks (execute after backend, modify response)post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "text_rewrite"params:
pattern: "OldCompany"replacement: "NewCompany"

🔌 Built-in hooks include:

TypeHooksPurpose
⬅️ Pre-hooksredirect_301, redirect_302, gone_410, not_found_404, static_htmlExecute before backend
➡️ Post-hooksurl_rewrite, text_rewrite, link_rewrite, html_rewrite, xpath_replace_from_url, json_modifyModify responses

✨ Features:

  • 🌐 Hostname patterns with wildcards (*.example.com)
  • 🔍 URL patterns with glob (/api/*) or regex (regex:^/api/v[0-9]+/)
  • ⏭️ Pre-hooks can skip backend calls (redirects, errors)
  • 🔧 Post-hooks modify content (HTML, text, JSON)
  • 📁 Organize hooks with includes: Separate hooks by hostname into dedicated files

📚 Learn more:


🔗 Nginx Integration

Use python-proxy with nginx as a frontend reverse proxy for production deployments.

Nginx Integration

Nginx handles: SSL termination, load balancing Python-proxy handles: Hook-based content modification

📚 See examples/NginxIntegration.md for complete configuration:

  • 🌐 Proxy entire site or specific paths
  • 🎯 Dynamic backend routing based on URL patterns
  • ⚖️ Load balancing with multiple python-proxy instances
  • 🔒 Production-ready setup with SSL/TLS
  • ⚡ Performance optimization and security best practices

🐍 Creating Custom Python Hooks

🎓 New to hooks? Start with Creating Custom Hooks - For Beginners A complete step-by-step tutorial with real-world examples!

For advanced use cases, you can write custom Python hooks. Place them in a hooks directory.

💡 Simple Hook Example

Create a file hooks/my_hooks.py:

asyncdefbefore_request(request, request_data):
"""Modify request before proxying."""# Add custom headerrequest_data["headers"]["X-Custom"] ="MyValue"returnrequest_dataasyncdefafter_response(response, body):
"""Modify response after receiving."""# Modify HTML contentifb"<html>"inbody:
body=body.replace(b"</body>", b"<!-- Modified --></body>")
returnbody

Then run with:

python-proxy --hooks ./hooks --target http://example.com

🚀 Advanced Hooks with Decorators

frompython_proxy.hooksimportbefore_request, after_response@before_requestasyncdefadd_auth(request, request_data):
"""Add authentication to API requests."""if"api.example.com"inrequest_data["url"]:
request_data["headers"]["Authorization"] ="Bearer TOKEN"returnrequest_data@after_responseasyncdefinject_script(response, body):
"""Inject JavaScript into HTML pages."""content_type=response.headers.get("Content-Type", "")
if"text/html"incontent_type:
html=body.decode("utf-8", errors="ignore")
script='<script>console.log("Proxied!")</script>'html=html.replace("</head>", f"{script}</head>")
returnhtml.encode("utf-8")
returnbody

📚 Learn more:


⚙️ Configuration

📝 Configuration File (YAML)

Create config.yaml:

host: "0.0.0.0"port: 8080target_host: "http://example.com"timeout: 30hooks_dir: "./hooks"log_level: "INFO"

🔢 Configuration Priority

  1. 🥇 CLI arguments (highest priority)
  2. 🥈 Configuration file (--config)
  3. 🥉 Environment variables
  4. 4️⃣ Default values (lowest priority)

🔓 Running on Port 80

⚠️ Ports below 1024 require special permissions. The proxy provides helpful error messages and multiple solutions.

# ✅ Quick setup (recommended)
./scripts/setup_port80.sh
# 🔧 Or manually
sudo setcap 'cap_net_bind_service=+ep'$(which python3)
python-proxy --host 192.168.2.7 --port 80

🔀 Other options:

  • 🔴 Run with sudo (not recommended for production)
  • 🔀 Use iptables port forwarding
  • ⚙️ Use systemd socket activation

📚 See examples/port80_setup.md for complete guide.


🛠️ Development

📥 Install Development Dependencies

pip install -r requirements-dev.txt

🧪 Run Tests

# Run all tests
pytest
# Run with coverage
pytest --cov=python_proxy
# Run specific test file
pytest tests/test_config.py

🔍 Linting

# Run ruff linter
ruff check .# Auto-fix issues
ruff check --fix .

🎯 Use Cases

Use CaseDescriptionBenefits
🕷️ Web ScrapingModify headers, inject credentialsBypass restrictions
🔧 DevelopmentTest different API responsesNo backend changes
🔐 Security TestingAnalyze and modify trafficFind vulnerabilities
💉 Content InjectionAdd scripts, styles, or contentTesting & analytics
🧪 API TestingModify requests/responsesSimulate edge cases
📊 Traffic AnalysisLog and analyze HTTP trafficDebug & monitor

📜 License

Copyright (C) 2025 Sergey Porfirievparf@difive.com

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

📄 License: GPL v2 - See LICENSE file for details.


Made with ❤️ by Sergey Porfiriev

⭐ Star this repo if you find it useful! • 🐛 Report issues • 💡 Contribute

About

Transparent Python Proxy (~ nginx), allows modification of select pages BEFORE proxying or AFTER

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

🚀 python-proxy

A powerful, transparent HTTP proxy server with intelligent traffic modification capabilities.

Python-Proxy Flow

**~ nginx with superpowers** • Zero-code configurationProduction-ready


✨ Overview

Python-proxy is a high-performance, asynchronous HTTP proxy server built on aiohttp that sits between clients and backend servers, allowing you to intercept, inspect, and modify HTTP traffic in real-time. Unlike traditional proxies that simply forward traffic, python-proxy provides a sophisticated hook system that enables you to transform requests and responses on-the-fly.

🎯 What Makes It Special?

💡 Think of it as ~ nginx with superpowers Get the reliability and performance of a production-grade proxy, combined with the flexibility to programmatically modify any aspect of HTTP traffic.

Common Use Cases:

  • 🔐 Add authentication headers
  • 📊 Inject analytics scripts into web pages
  • 🧪 Mock API responses for testing
  • 🔗 Rewrite URLs and links
  • 🛡️ Sanitize sensitive data
  • 🎲 Implement custom routing logic

🎨 Developer Experience First

# Zero-code configuration - just edit YAML!post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "link_rewrite"params:
from_domain: "example.com"to_domain: "example.com.local"

🟢 Start Simple: Use built-in YAML hooks for redirects, text replacement, and HTML modifications

🟡 Scale Up: Write custom Python hooks with full access to request/response data

🔵 Go Advanced: Implement rate limiting, caching, A/B testing, or external API integration

Async architecture ensures modifications don't compromise performance, handling thousands of concurrent connections efficiently.

🌍 Perfect For Every Environment

EnvironmentUse CaseBenefits
🔧 DevelopmentTest API responsesNo backend changes needed
🧪 QA/TestingInject test dataSimulate edge cases easily
🚀 ProductionContent transformationAdd security headers on-the-fly
🔬 SecurityTraffic analysisIntercept and modify requests

Seamless nginx integration for production deployments - handle SSL termination and load balancing while python-proxy focuses on intelligent content modification.

🛠️ Extensible Architecture

Built-in hooks handle common operations:

  • ↩️ 301/302 redirects
  • 📝 JSON field manipulation
  • 🏗️ HTML element modifications (XPath)
  • 🔗 Link rewriting
  • 🌐 Content fetching from external sources

Python hook system provides:

  • 🔍 Automatic discovery
  • 🎯 Decorator support
  • ⚠️ Comprehensive error handling
  • 🎛️ Full programmatic access

Whether you're a developer needing quick traffic manipulation or a DevOps engineer building sophisticated proxy infrastructure, python-proxy scales from simple scripts to enterprise deployments.


🎁 Features

  • Async/Await Architecture: Built on aiohttp for high-performance async I/O
  • 📤 Request Modification: Modify requests before they're proxied (headers, body, URL, etc.)
  • 📥 Response Modification: Modify responses after receiving from target (HTML injection, content replacement, etc.)
  • 🎣 Hook System: Simple Python-based hook system with automatic discovery
  • ⚙️ Configuration-Based Hooks: Powerful built-in hooks (redirects, rewrites, HTML/text transformation) via YAML config - no coding required!
  • 🔧 Flexible Configuration: Configure via CLI arguments, environment variables, or YAML config file
  • 🎯 Header-Based Routing: Route requests to different targets using X-Proxy-Server header

📦 Installation

# Install from source
pip install -e .# Or install dependencies directly
pip install -r requirements.txt

💡 Requirements: Python 3.8 or higher


🚀 Quick Start

💻 Basic Usage

# Start proxy on default port 8080
python-proxy
# Start with custom port
python-proxy --port 3128
# Proxy all requests to a specific target
python-proxy --target http://example.com
# Use a configuration file
python-proxy --config config.yaml

⚡ Quick Start with realmo.com.local (Default Configuration)

🎯 The default config.yaml is pre-configured for proxying realmo.com locally with automatic link rewriting!

# 1️⃣ Add to /etc/hostsecho"127.0.0.1 realmo.com.local"| sudo tee -a /etc/hosts
# 2️⃣ Set up port 80 capability (one-time)
./scripts/setup_port80.sh
# 3️⃣ Start proxy with default config
python-proxy --config config.yaml
# 4️⃣ Browse to http://realmo.com.local

✨ What this does:

  • 🔄 Proxies realmo.com.localrealmo.com:80
  • 🔗 Automatically rewrites all realmo.com links to realmo.com.local
  • 🎯 Keeps all traffic flowing through the proxy for testing/development

📚 See examples/REALMO_SETUP.md for detailed guide and customization options.

🔓 Running on Port 80 (Privileged Port)

✅ Quick Install (Recommended):

# Install wrapper and set up port 80 capability
./scripts/setup_port80.sh
# Now use from anywhere
python-proxy --host 192.168.2.7 --port 80

🔧 Manual Setup:

# One-time setup (resolves symlinks if needed)
sudo setcap 'cap_net_bind_service=+ep'$(readlink -f $(which python3))# Now run without sudo
python-proxy --host 192.168.2.7 --port 80

📚 See examples/port80_setup.md for detailed instructions and alternatives.

🌐 Using Environment Variables

export PROXY_PORT=8080
export PROXY_TARGET=http://example.com
export PROXY_HOOKS_DIR=./hooks
python-proxy

📡 Making Requests Through the Proxy

The proxy supports multiple ways to specify the backend target:

  1. X-Proxy-Server - Simple host or host:port format
  2. Default target - Configured via CLI or config file
  3. Automatic .local domains - Requests to hostname.local automatically route to hostname
# Using X-Proxy-Server (simple format)
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com" \
http://example.com/page
# Using X-Proxy-Server with custom port
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com:8080" \
http://example.com/page
# Override the Host header sent to backend
curl -x http://localhost:8080 \
-H "X-Proxy-Server: 192.168.1.100:8080" \
-H "X-Proxy-Host: myapp.example.com" \
http://example.com/page
# With default target configured
curl -x http://localhost:8080 http://example.com/page

Header Reference

  • X-Proxy-Server: Backend server as host or host:port

    • Default port: 80 (http) if not specified
    • Port 443 automatically uses HTTPS
    • Examples: example.com, example.com:8080, 192.168.1.100:3000
  • X-Proxy-Host: Override the Host header sent to backend server

    • Useful for virtual hosting or when backend expects specific hostname
    • Example: myapp.example.com

Automatic .local Domain Routing

The proxy automatically strips the .local suffix from hostnames and routes to the actual domain on port 80 (standard HTTP). Any port specified in the .local request is ignored. This is useful for local development and testing.

# Request to example.com.local routes to example.com:80
curl -x http://localhost:8080 http://example.com.local/page
# Port in .local URL is ignored - still routes to port 80
curl -x http://localhost:8080 http://api.example.com.local:8080/data
# → Routes to api.example.com:80# Configure in /etc/hosts for easy testing:# 127.0.0.1 myapp.com.local
curl -x http://localhost:8080 http://myapp.com.local/

Behavior:

  • hostname.localhostname:80
  • hostname.local:XXXXhostname:80 (port ignored)
  • Always uses HTTP (port 80), not HTTPS

Use cases:

  • Local development: Test production URLs locally
  • /etc/hosts testing: Add .local entries to route through proxy
  • Network testing: Intercept specific domains without DNS changes

Example /etc/hosts setup:

# Add .local entries that proxy will strip and forward to port 80
127.0.0.1 api.example.com.local
127.0.0.1 cdn.example.com.local

Then requests to api.example.com.local:8080 go through your proxy to api.example.com:80.

🎣 Configuration-Based Hooks

NEW! Configure powerful hooks directly in your YAML config - no Python coding required!

Perfect for redirects, URL rewrites, content modification, and more.

💡 Quick Example

# config.yamlhost: "0.0.0.0"port: 8080hook_mappings:
# Pre-hooks (execute before backend, can skip backend call)pre_hooks:
- hostname: "example.com"url_pattern: "/old-page"hook: "redirect_301"params:
location: "https://example.com/new-page"# Post-hooks (execute after backend, modify response)post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "text_rewrite"params:
pattern: "OldCompany"replacement: "NewCompany"

🔌 Built-in hooks include:

TypeHooksPurpose
⬅️ Pre-hooksredirect_301, redirect_302, gone_410, not_found_404, static_htmlExecute before backend
➡️ Post-hooksurl_rewrite, text_rewrite, link_rewrite, html_rewrite, xpath_replace_from_url, json_modifyModify responses

✨ Features:

  • 🌐 Hostname patterns with wildcards (*.example.com)
  • 🔍 URL patterns with glob (/api/*) or regex (regex:^/api/v[0-9]+/)
  • ⏭️ Pre-hooks can skip backend calls (redirects, errors)
  • 🔧 Post-hooks modify content (HTML, text, JSON)
  • 📁 Organize hooks with includes: Separate hooks by hostname into dedicated files

📚 Learn more:


🔗 Nginx Integration

Use python-proxy with nginx as a frontend reverse proxy for production deployments.

Nginx Integration

Nginx handles: SSL termination, load balancing Python-proxy handles: Hook-based content modification

📚 See examples/NginxIntegration.md for complete configuration:

  • 🌐 Proxy entire site or specific paths
  • 🎯 Dynamic backend routing based on URL patterns
  • ⚖️ Load balancing with multiple python-proxy instances
  • 🔒 Production-ready setup with SSL/TLS
  • ⚡ Performance optimization and security best practices

🐍 Creating Custom Python Hooks

🎓 New to hooks? Start with Creating Custom Hooks - For Beginners A complete step-by-step tutorial with real-world examples!

For advanced use cases, you can write custom Python hooks. Place them in a hooks directory.

💡 Simple Hook Example

Create a file hooks/my_hooks.py:

asyncdefbefore_request(request, request_data):
"""Modify request before proxying."""# Add custom headerrequest_data["headers"]["X-Custom"] ="MyValue"returnrequest_dataasyncdefafter_response(response, body):
"""Modify response after receiving."""# Modify HTML contentifb"<html>"inbody:
body=body.replace(b"</body>", b"<!-- Modified --></body>")
returnbody

Then run with:

python-proxy --hooks ./hooks --target http://example.com

🚀 Advanced Hooks with Decorators

frompython_proxy.hooksimportbefore_request, after_response@before_requestasyncdefadd_auth(request, request_data):
"""Add authentication to API requests."""if"api.example.com"inrequest_data["url"]:
request_data["headers"]["Authorization"] ="Bearer TOKEN"returnrequest_data@after_responseasyncdefinject_script(response, body):
"""Inject JavaScript into HTML pages."""content_type=response.headers.get("Content-Type", "")
if"text/html"incontent_type:
html=body.decode("utf-8", errors="ignore")
script='<script>console.log("Proxied!")</script>'html=html.replace("</head>", f"{script}</head>")
returnhtml.encode("utf-8")
returnbody

📚 Learn more:


⚙️ Configuration

📝 Configuration File (YAML)

Create config.yaml:

host: "0.0.0.0"port: 8080target_host: "http://example.com"timeout: 30hooks_dir: "./hooks"log_level: "INFO"

🔢 Configuration Priority

  1. 🥇 CLI arguments (highest priority)
  2. 🥈 Configuration file (--config)
  3. 🥉 Environment variables
  4. 4️⃣ Default values (lowest priority)

🔓 Running on Port 80

⚠️ Ports below 1024 require special permissions. The proxy provides helpful error messages and multiple solutions.

# ✅ Quick setup (recommended)
./scripts/setup_port80.sh
# 🔧 Or manually
sudo setcap 'cap_net_bind_service=+ep'$(which python3)
python-proxy --host 192.168.2.7 --port 80

🔀 Other options:

  • 🔴 Run with sudo (not recommended for production)
  • 🔀 Use iptables port forwarding
  • ⚙️ Use systemd socket activation

📚 See examples/port80_setup.md for complete guide.


🛠️ Development

📥 Install Development Dependencies

pip install -r requirements-dev.txt

🧪 Run Tests

# Run all tests
pytest
# Run with coverage
pytest --cov=python_proxy
# Run specific test file
pytest tests/test_config.py

🔍 Linting

# Run ruff linter
ruff check .# Auto-fix issues
ruff check --fix .

🎯 Use Cases

Use CaseDescriptionBenefits
🕷️ Web ScrapingModify headers, inject credentialsBypass restrictions
🔧 DevelopmentTest different API responsesNo backend changes
🔐 Security TestingAnalyze and modify trafficFind vulnerabilities
💉 Content InjectionAdd scripts, styles, or contentTesting & analytics
🧪 API TestingModify requests/responsesSimulate edge cases
📊 Traffic AnalysisLog and analyze HTTP trafficDebug & monitor

📜 License

Copyright (C) 2025 Sergey Porfirievparf@difive.com

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

📄 License: GPL v2 - See LICENSE file for details.


Made with ❤️ by Sergey Porfiriev

⭐ Star this repo if you find it useful! • 🐛 Report issues • 💡 Contribute

About

Transparent Python Proxy (~ nginx), allows modification of select pages BEFORE proxying or AFTER

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

🚀 python-proxy

A powerful, transparent HTTP proxy server with intelligent traffic modification capabilities.

Python-Proxy Flow

**~ nginx with superpowers** • Zero-code configurationProduction-ready


✨ Overview

Python-proxy is a high-performance, asynchronous HTTP proxy server built on aiohttp that sits between clients and backend servers, allowing you to intercept, inspect, and modify HTTP traffic in real-time. Unlike traditional proxies that simply forward traffic, python-proxy provides a sophisticated hook system that enables you to transform requests and responses on-the-fly.

🎯 What Makes It Special?

💡 Think of it as ~ nginx with superpowers Get the reliability and performance of a production-grade proxy, combined with the flexibility to programmatically modify any aspect of HTTP traffic.

Common Use Cases:

  • 🔐 Add authentication headers
  • 📊 Inject analytics scripts into web pages
  • 🧪 Mock API responses for testing
  • 🔗 Rewrite URLs and links
  • 🛡️ Sanitize sensitive data
  • 🎲 Implement custom routing logic

🎨 Developer Experience First

# Zero-code configuration - just edit YAML!post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "link_rewrite"params:
from_domain: "example.com"to_domain: "example.com.local"

🟢 Start Simple: Use built-in YAML hooks for redirects, text replacement, and HTML modifications

🟡 Scale Up: Write custom Python hooks with full access to request/response data

🔵 Go Advanced: Implement rate limiting, caching, A/B testing, or external API integration

Async architecture ensures modifications don't compromise performance, handling thousands of concurrent connections efficiently.

🌍 Perfect For Every Environment

EnvironmentUse CaseBenefits
🔧 DevelopmentTest API responsesNo backend changes needed
🧪 QA/TestingInject test dataSimulate edge cases easily
🚀 ProductionContent transformationAdd security headers on-the-fly
🔬 SecurityTraffic analysisIntercept and modify requests

Seamless nginx integration for production deployments - handle SSL termination and load balancing while python-proxy focuses on intelligent content modification.

🛠️ Extensible Architecture

Built-in hooks handle common operations:

  • ↩️ 301/302 redirects
  • 📝 JSON field manipulation
  • 🏗️ HTML element modifications (XPath)
  • 🔗 Link rewriting
  • 🌐 Content fetching from external sources

Python hook system provides:

  • 🔍 Automatic discovery
  • 🎯 Decorator support
  • ⚠️ Comprehensive error handling
  • 🎛️ Full programmatic access

Whether you're a developer needing quick traffic manipulation or a DevOps engineer building sophisticated proxy infrastructure, python-proxy scales from simple scripts to enterprise deployments.


🎁 Features

  • Async/Await Architecture: Built on aiohttp for high-performance async I/O
  • 📤 Request Modification: Modify requests before they're proxied (headers, body, URL, etc.)
  • 📥 Response Modification: Modify responses after receiving from target (HTML injection, content replacement, etc.)
  • 🎣 Hook System: Simple Python-based hook system with automatic discovery
  • ⚙️ Configuration-Based Hooks: Powerful built-in hooks (redirects, rewrites, HTML/text transformation) via YAML config - no coding required!
  • 🔧 Flexible Configuration: Configure via CLI arguments, environment variables, or YAML config file
  • 🎯 Header-Based Routing: Route requests to different targets using X-Proxy-Server header

📦 Installation

# Install from source
pip install -e .# Or install dependencies directly
pip install -r requirements.txt

💡 Requirements: Python 3.8 or higher


🚀 Quick Start

💻 Basic Usage

# Start proxy on default port 8080
python-proxy
# Start with custom port
python-proxy --port 3128
# Proxy all requests to a specific target
python-proxy --target http://example.com
# Use a configuration file
python-proxy --config config.yaml

⚡ Quick Start with realmo.com.local (Default Configuration)

🎯 The default config.yaml is pre-configured for proxying realmo.com locally with automatic link rewriting!

# 1️⃣ Add to /etc/hostsecho"127.0.0.1 realmo.com.local"| sudo tee -a /etc/hosts
# 2️⃣ Set up port 80 capability (one-time)
./scripts/setup_port80.sh
# 3️⃣ Start proxy with default config
python-proxy --config config.yaml
# 4️⃣ Browse to http://realmo.com.local

✨ What this does:

  • 🔄 Proxies realmo.com.localrealmo.com:80
  • 🔗 Automatically rewrites all realmo.com links to realmo.com.local
  • 🎯 Keeps all traffic flowing through the proxy for testing/development

📚 See examples/REALMO_SETUP.md for detailed guide and customization options.

🔓 Running on Port 80 (Privileged Port)

✅ Quick Install (Recommended):

# Install wrapper and set up port 80 capability
./scripts/setup_port80.sh
# Now use from anywhere
python-proxy --host 192.168.2.7 --port 80

🔧 Manual Setup:

# One-time setup (resolves symlinks if needed)
sudo setcap 'cap_net_bind_service=+ep'$(readlink -f $(which python3))# Now run without sudo
python-proxy --host 192.168.2.7 --port 80

📚 See examples/port80_setup.md for detailed instructions and alternatives.

🌐 Using Environment Variables

export PROXY_PORT=8080
export PROXY_TARGET=http://example.com
export PROXY_HOOKS_DIR=./hooks
python-proxy

📡 Making Requests Through the Proxy

The proxy supports multiple ways to specify the backend target:

  1. X-Proxy-Server - Simple host or host:port format
  2. Default target - Configured via CLI or config file
  3. Automatic .local domains - Requests to hostname.local automatically route to hostname
# Using X-Proxy-Server (simple format)
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com" \
http://example.com/page
# Using X-Proxy-Server with custom port
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com:8080" \
http://example.com/page
# Override the Host header sent to backend
curl -x http://localhost:8080 \
-H "X-Proxy-Server: 192.168.1.100:8080" \
-H "X-Proxy-Host: myapp.example.com" \
http://example.com/page
# With default target configured
curl -x http://localhost:8080 http://example.com/page

Header Reference

  • X-Proxy-Server: Backend server as host or host:port

    • Default port: 80 (http) if not specified
    • Port 443 automatically uses HTTPS
    • Examples: example.com, example.com:8080, 192.168.1.100:3000
  • X-Proxy-Host: Override the Host header sent to backend server

    • Useful for virtual hosting or when backend expects specific hostname
    • Example: myapp.example.com

Automatic .local Domain Routing

The proxy automatically strips the .local suffix from hostnames and routes to the actual domain on port 80 (standard HTTP). Any port specified in the .local request is ignored. This is useful for local development and testing.

# Request to example.com.local routes to example.com:80
curl -x http://localhost:8080 http://example.com.local/page
# Port in .local URL is ignored - still routes to port 80
curl -x http://localhost:8080 http://api.example.com.local:8080/data
# → Routes to api.example.com:80# Configure in /etc/hosts for easy testing:# 127.0.0.1 myapp.com.local
curl -x http://localhost:8080 http://myapp.com.local/

Behavior:

  • hostname.localhostname:80
  • hostname.local:XXXXhostname:80 (port ignored)
  • Always uses HTTP (port 80), not HTTPS

Use cases:

  • Local development: Test production URLs locally
  • /etc/hosts testing: Add .local entries to route through proxy
  • Network testing: Intercept specific domains without DNS changes

Example /etc/hosts setup:

# Add .local entries that proxy will strip and forward to port 80
127.0.0.1 api.example.com.local
127.0.0.1 cdn.example.com.local

Then requests to api.example.com.local:8080 go through your proxy to api.example.com:80.

🎣 Configuration-Based Hooks

NEW! Configure powerful hooks directly in your YAML config - no Python coding required!

Perfect for redirects, URL rewrites, content modification, and more.

💡 Quick Example

# config.yamlhost: "0.0.0.0"port: 8080hook_mappings:
# Pre-hooks (execute before backend, can skip backend call)pre_hooks:
- hostname: "example.com"url_pattern: "/old-page"hook: "redirect_301"params:
location: "https://example.com/new-page"# Post-hooks (execute after backend, modify response)post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "text_rewrite"params:
pattern: "OldCompany"replacement: "NewCompany"

🔌 Built-in hooks include:

TypeHooksPurpose
⬅️ Pre-hooksredirect_301, redirect_302, gone_410, not_found_404, static_htmlExecute before backend
➡️ Post-hooksurl_rewrite, text_rewrite, link_rewrite, html_rewrite, xpath_replace_from_url, json_modifyModify responses

✨ Features:

  • 🌐 Hostname patterns with wildcards (*.example.com)
  • 🔍 URL patterns with glob (/api/*) or regex (regex:^/api/v[0-9]+/)
  • ⏭️ Pre-hooks can skip backend calls (redirects, errors)
  • 🔧 Post-hooks modify content (HTML, text, JSON)
  • 📁 Organize hooks with includes: Separate hooks by hostname into dedicated files

📚 Learn more:


🔗 Nginx Integration

Use python-proxy with nginx as a frontend reverse proxy for production deployments.

Nginx Integration

Nginx handles: SSL termination, load balancing Python-proxy handles: Hook-based content modification

📚 See examples/NginxIntegration.md for complete configuration:

  • 🌐 Proxy entire site or specific paths
  • 🎯 Dynamic backend routing based on URL patterns
  • ⚖️ Load balancing with multiple python-proxy instances
  • 🔒 Production-ready setup with SSL/TLS
  • ⚡ Performance optimization and security best practices

🐍 Creating Custom Python Hooks

🎓 New to hooks? Start with Creating Custom Hooks - For Beginners A complete step-by-step tutorial with real-world examples!

For advanced use cases, you can write custom Python hooks. Place them in a hooks directory.

💡 Simple Hook Example

Create a file hooks/my_hooks.py:

asyncdefbefore_request(request, request_data):
"""Modify request before proxying."""# Add custom headerrequest_data["headers"]["X-Custom"] ="MyValue"returnrequest_dataasyncdefafter_response(response, body):
"""Modify response after receiving."""# Modify HTML contentifb"<html>"inbody:
body=body.replace(b"</body>", b"<!-- Modified --></body>")
returnbody

Then run with:

python-proxy --hooks ./hooks --target http://example.com

🚀 Advanced Hooks with Decorators

frompython_proxy.hooksimportbefore_request, after_response@before_requestasyncdefadd_auth(request, request_data):
"""Add authentication to API requests."""if"api.example.com"inrequest_data["url"]:
request_data["headers"]["Authorization"] ="Bearer TOKEN"returnrequest_data@after_responseasyncdefinject_script(response, body):
"""Inject JavaScript into HTML pages."""content_type=response.headers.get("Content-Type", "")
if"text/html"incontent_type:
html=body.decode("utf-8", errors="ignore")
script='<script>console.log("Proxied!")</script>'html=html.replace("</head>", f"{script}</head>")
returnhtml.encode("utf-8")
returnbody

📚 Learn more:


⚙️ Configuration

📝 Configuration File (YAML)

Create config.yaml:

host: "0.0.0.0"port: 8080target_host: "http://example.com"timeout: 30hooks_dir: "./hooks"log_level: "INFO"

🔢 Configuration Priority

  1. 🥇 CLI arguments (highest priority)
  2. 🥈 Configuration file (--config)
  3. 🥉 Environment variables
  4. 4️⃣ Default values (lowest priority)

🔓 Running on Port 80

⚠️ Ports below 1024 require special permissions. The proxy provides helpful error messages and multiple solutions.

# ✅ Quick setup (recommended)
./scripts/setup_port80.sh
# 🔧 Or manually
sudo setcap 'cap_net_bind_service=+ep'$(which python3)
python-proxy --host 192.168.2.7 --port 80

🔀 Other options:

  • 🔴 Run with sudo (not recommended for production)
  • 🔀 Use iptables port forwarding
  • ⚙️ Use systemd socket activation

📚 See examples/port80_setup.md for complete guide.


🛠️ Development

📥 Install Development Dependencies

pip install -r requirements-dev.txt

🧪 Run Tests

# Run all tests
pytest
# Run with coverage
pytest --cov=python_proxy
# Run specific test file
pytest tests/test_config.py

🔍 Linting

# Run ruff linter
ruff check .# Auto-fix issues
ruff check --fix .

🎯 Use Cases

Use CaseDescriptionBenefits
🕷️ Web ScrapingModify headers, inject credentialsBypass restrictions
🔧 DevelopmentTest different API responsesNo backend changes
🔐 Security TestingAnalyze and modify trafficFind vulnerabilities
💉 Content InjectionAdd scripts, styles, or contentTesting & analytics
🧪 API TestingModify requests/responsesSimulate edge cases
📊 Traffic AnalysisLog and analyze HTTP trafficDebug & monitor

📜 License

Copyright (C) 2025 Sergey Porfirievparf@difive.com

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

📄 License: GPL v2 - See LICENSE file for details.


Made with ❤️ by Sergey Porfiriev

⭐ Star this repo if you find it useful! • 🐛 Report issues • 💡 Contribute

About

Transparent Python Proxy (~ nginx), allows modification of select pages BEFORE proxying or AFTER

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

🚀 python-proxy

A powerful, transparent HTTP proxy server with intelligent traffic modification capabilities.

Python-Proxy Flow

**~ nginx with superpowers** • Zero-code configurationProduction-ready


✨ Overview

Python-proxy is a high-performance, asynchronous HTTP proxy server built on aiohttp that sits between clients and backend servers, allowing you to intercept, inspect, and modify HTTP traffic in real-time. Unlike traditional proxies that simply forward traffic, python-proxy provides a sophisticated hook system that enables you to transform requests and responses on-the-fly.

🎯 What Makes It Special?

💡 Think of it as ~ nginx with superpowers Get the reliability and performance of a production-grade proxy, combined with the flexibility to programmatically modify any aspect of HTTP traffic.

Common Use Cases:

  • 🔐 Add authentication headers
  • 📊 Inject analytics scripts into web pages
  • 🧪 Mock API responses for testing
  • 🔗 Rewrite URLs and links
  • 🛡️ Sanitize sensitive data
  • 🎲 Implement custom routing logic

🎨 Developer Experience First

# Zero-code configuration - just edit YAML!post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "link_rewrite"params:
from_domain: "example.com"to_domain: "example.com.local"

🟢 Start Simple: Use built-in YAML hooks for redirects, text replacement, and HTML modifications

🟡 Scale Up: Write custom Python hooks with full access to request/response data

🔵 Go Advanced: Implement rate limiting, caching, A/B testing, or external API integration

Async architecture ensures modifications don't compromise performance, handling thousands of concurrent connections efficiently.

🌍 Perfect For Every Environment

EnvironmentUse CaseBenefits
🔧 DevelopmentTest API responsesNo backend changes needed
🧪 QA/TestingInject test dataSimulate edge cases easily
🚀 ProductionContent transformationAdd security headers on-the-fly
🔬 SecurityTraffic analysisIntercept and modify requests

Seamless nginx integration for production deployments - handle SSL termination and load balancing while python-proxy focuses on intelligent content modification.

🛠️ Extensible Architecture

Built-in hooks handle common operations:

  • ↩️ 301/302 redirects
  • 📝 JSON field manipulation
  • 🏗️ HTML element modifications (XPath)
  • 🔗 Link rewriting
  • 🌐 Content fetching from external sources

Python hook system provides:

  • 🔍 Automatic discovery
  • 🎯 Decorator support
  • ⚠️ Comprehensive error handling
  • 🎛️ Full programmatic access

Whether you're a developer needing quick traffic manipulation or a DevOps engineer building sophisticated proxy infrastructure, python-proxy scales from simple scripts to enterprise deployments.


🎁 Features

  • Async/Await Architecture: Built on aiohttp for high-performance async I/O
  • 📤 Request Modification: Modify requests before they're proxied (headers, body, URL, etc.)
  • 📥 Response Modification: Modify responses after receiving from target (HTML injection, content replacement, etc.)
  • 🎣 Hook System: Simple Python-based hook system with automatic discovery
  • ⚙️ Configuration-Based Hooks: Powerful built-in hooks (redirects, rewrites, HTML/text transformation) via YAML config - no coding required!
  • 🔧 Flexible Configuration: Configure via CLI arguments, environment variables, or YAML config file
  • 🎯 Header-Based Routing: Route requests to different targets using X-Proxy-Server header

📦 Installation

# Install from source
pip install -e .# Or install dependencies directly
pip install -r requirements.txt

💡 Requirements: Python 3.8 or higher


🚀 Quick Start

💻 Basic Usage

# Start proxy on default port 8080
python-proxy
# Start with custom port
python-proxy --port 3128
# Proxy all requests to a specific target
python-proxy --target http://example.com
# Use a configuration file
python-proxy --config config.yaml

⚡ Quick Start with realmo.com.local (Default Configuration)

🎯 The default config.yaml is pre-configured for proxying realmo.com locally with automatic link rewriting!

# 1️⃣ Add to /etc/hostsecho"127.0.0.1 realmo.com.local"| sudo tee -a /etc/hosts
# 2️⃣ Set up port 80 capability (one-time)
./scripts/setup_port80.sh
# 3️⃣ Start proxy with default config
python-proxy --config config.yaml
# 4️⃣ Browse to http://realmo.com.local

✨ What this does:

  • 🔄 Proxies realmo.com.localrealmo.com:80
  • 🔗 Automatically rewrites all realmo.com links to realmo.com.local
  • 🎯 Keeps all traffic flowing through the proxy for testing/development

📚 See examples/REALMO_SETUP.md for detailed guide and customization options.

🔓 Running on Port 80 (Privileged Port)

✅ Quick Install (Recommended):

# Install wrapper and set up port 80 capability
./scripts/setup_port80.sh
# Now use from anywhere
python-proxy --host 192.168.2.7 --port 80

🔧 Manual Setup:

# One-time setup (resolves symlinks if needed)
sudo setcap 'cap_net_bind_service=+ep'$(readlink -f $(which python3))# Now run without sudo
python-proxy --host 192.168.2.7 --port 80

📚 See examples/port80_setup.md for detailed instructions and alternatives.

🌐 Using Environment Variables

export PROXY_PORT=8080
export PROXY_TARGET=http://example.com
export PROXY_HOOKS_DIR=./hooks
python-proxy

📡 Making Requests Through the Proxy

The proxy supports multiple ways to specify the backend target:

  1. X-Proxy-Server - Simple host or host:port format
  2. Default target - Configured via CLI or config file
  3. Automatic .local domains - Requests to hostname.local automatically route to hostname
# Using X-Proxy-Server (simple format)
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com" \
http://example.com/page
# Using X-Proxy-Server with custom port
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com:8080" \
http://example.com/page
# Override the Host header sent to backend
curl -x http://localhost:8080 \
-H "X-Proxy-Server: 192.168.1.100:8080" \
-H "X-Proxy-Host: myapp.example.com" \
http://example.com/page
# With default target configured
curl -x http://localhost:8080 http://example.com/page

Header Reference

  • X-Proxy-Server: Backend server as host or host:port

    • Default port: 80 (http) if not specified
    • Port 443 automatically uses HTTPS
    • Examples: example.com, example.com:8080, 192.168.1.100:3000
  • X-Proxy-Host: Override the Host header sent to backend server

    • Useful for virtual hosting or when backend expects specific hostname
    • Example: myapp.example.com

Automatic .local Domain Routing

The proxy automatically strips the .local suffix from hostnames and routes to the actual domain on port 80 (standard HTTP). Any port specified in the .local request is ignored. This is useful for local development and testing.

# Request to example.com.local routes to example.com:80
curl -x http://localhost:8080 http://example.com.local/page
# Port in .local URL is ignored - still routes to port 80
curl -x http://localhost:8080 http://api.example.com.local:8080/data
# → Routes to api.example.com:80# Configure in /etc/hosts for easy testing:# 127.0.0.1 myapp.com.local
curl -x http://localhost:8080 http://myapp.com.local/

Behavior:

  • hostname.localhostname:80
  • hostname.local:XXXXhostname:80 (port ignored)
  • Always uses HTTP (port 80), not HTTPS

Use cases:

  • Local development: Test production URLs locally
  • /etc/hosts testing: Add .local entries to route through proxy
  • Network testing: Intercept specific domains without DNS changes

Example /etc/hosts setup:

# Add .local entries that proxy will strip and forward to port 80
127.0.0.1 api.example.com.local
127.0.0.1 cdn.example.com.local

Then requests to api.example.com.local:8080 go through your proxy to api.example.com:80.

🎣 Configuration-Based Hooks

NEW! Configure powerful hooks directly in your YAML config - no Python coding required!

Perfect for redirects, URL rewrites, content modification, and more.

💡 Quick Example

# config.yamlhost: "0.0.0.0"port: 8080hook_mappings:
# Pre-hooks (execute before backend, can skip backend call)pre_hooks:
- hostname: "example.com"url_pattern: "/old-page"hook: "redirect_301"params:
location: "https://example.com/new-page"# Post-hooks (execute after backend, modify response)post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "text_rewrite"params:
pattern: "OldCompany"replacement: "NewCompany"

🔌 Built-in hooks include:

TypeHooksPurpose
⬅️ Pre-hooksredirect_301, redirect_302, gone_410, not_found_404, static_htmlExecute before backend
➡️ Post-hooksurl_rewrite, text_rewrite, link_rewrite, html_rewrite, xpath_replace_from_url, json_modifyModify responses

✨ Features:

  • 🌐 Hostname patterns with wildcards (*.example.com)
  • 🔍 URL patterns with glob (/api/*) or regex (regex:^/api/v[0-9]+/)
  • ⏭️ Pre-hooks can skip backend calls (redirects, errors)
  • 🔧 Post-hooks modify content (HTML, text, JSON)
  • 📁 Organize hooks with includes: Separate hooks by hostname into dedicated files

📚 Learn more:


🔗 Nginx Integration

Use python-proxy with nginx as a frontend reverse proxy for production deployments.

Nginx Integration

Nginx handles: SSL termination, load balancing Python-proxy handles: Hook-based content modification

📚 See examples/NginxIntegration.md for complete configuration:

  • 🌐 Proxy entire site or specific paths
  • 🎯 Dynamic backend routing based on URL patterns
  • ⚖️ Load balancing with multiple python-proxy instances
  • 🔒 Production-ready setup with SSL/TLS
  • ⚡ Performance optimization and security best practices

🐍 Creating Custom Python Hooks

🎓 New to hooks? Start with Creating Custom Hooks - For Beginners A complete step-by-step tutorial with real-world examples!

For advanced use cases, you can write custom Python hooks. Place them in a hooks directory.

💡 Simple Hook Example

Create a file hooks/my_hooks.py:

asyncdefbefore_request(request, request_data):
"""Modify request before proxying."""# Add custom headerrequest_data["headers"]["X-Custom"] ="MyValue"returnrequest_dataasyncdefafter_response(response, body):
"""Modify response after receiving."""# Modify HTML contentifb"<html>"inbody:
body=body.replace(b"</body>", b"<!-- Modified --></body>")
returnbody

Then run with:

python-proxy --hooks ./hooks --target http://example.com

🚀 Advanced Hooks with Decorators

frompython_proxy.hooksimportbefore_request, after_response@before_requestasyncdefadd_auth(request, request_data):
"""Add authentication to API requests."""if"api.example.com"inrequest_data["url"]:
request_data["headers"]["Authorization"] ="Bearer TOKEN"returnrequest_data@after_responseasyncdefinject_script(response, body):
"""Inject JavaScript into HTML pages."""content_type=response.headers.get("Content-Type", "")
if"text/html"incontent_type:
html=body.decode("utf-8", errors="ignore")
script='<script>console.log("Proxied!")</script>'html=html.replace("</head>", f"{script}</head>")
returnhtml.encode("utf-8")
returnbody

📚 Learn more:


⚙️ Configuration

📝 Configuration File (YAML)

Create config.yaml:

host: "0.0.0.0"port: 8080target_host: "http://example.com"timeout: 30hooks_dir: "./hooks"log_level: "INFO"

🔢 Configuration Priority

  1. 🥇 CLI arguments (highest priority)
  2. 🥈 Configuration file (--config)
  3. 🥉 Environment variables
  4. 4️⃣ Default values (lowest priority)

🔓 Running on Port 80

⚠️ Ports below 1024 require special permissions. The proxy provides helpful error messages and multiple solutions.

# ✅ Quick setup (recommended)
./scripts/setup_port80.sh
# 🔧 Or manually
sudo setcap 'cap_net_bind_service=+ep'$(which python3)
python-proxy --host 192.168.2.7 --port 80

🔀 Other options:

  • 🔴 Run with sudo (not recommended for production)
  • 🔀 Use iptables port forwarding
  • ⚙️ Use systemd socket activation

📚 See examples/port80_setup.md for complete guide.


🛠️ Development

📥 Install Development Dependencies

pip install -r requirements-dev.txt

🧪 Run Tests

# Run all tests
pytest
# Run with coverage
pytest --cov=python_proxy
# Run specific test file
pytest tests/test_config.py

🔍 Linting

# Run ruff linter
ruff check .# Auto-fix issues
ruff check --fix .

🎯 Use Cases

Use CaseDescriptionBenefits
🕷️ Web ScrapingModify headers, inject credentialsBypass restrictions
🔧 DevelopmentTest different API responsesNo backend changes
🔐 Security TestingAnalyze and modify trafficFind vulnerabilities
💉 Content InjectionAdd scripts, styles, or contentTesting & analytics
🧪 API TestingModify requests/responsesSimulate edge cases
📊 Traffic AnalysisLog and analyze HTTP trafficDebug & monitor

📜 License

Copyright (C) 2025 Sergey Porfirievparf@difive.com

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

📄 License: GPL v2 - See LICENSE file for details.


Made with ❤️ by Sergey Porfiriev

⭐ Star this repo if you find it useful! • 🐛 Report issues • 💡 Contribute

About

Transparent Python Proxy (~ nginx), allows modification of select pages BEFORE proxying or AFTER

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

🚀 python-proxy

A powerful, transparent HTTP proxy server with intelligent traffic modification capabilities.

Python-Proxy Flow

**~ nginx with superpowers** • Zero-code configurationProduction-ready


✨ Overview

Python-proxy is a high-performance, asynchronous HTTP proxy server built on aiohttp that sits between clients and backend servers, allowing you to intercept, inspect, and modify HTTP traffic in real-time. Unlike traditional proxies that simply forward traffic, python-proxy provides a sophisticated hook system that enables you to transform requests and responses on-the-fly.

🎯 What Makes It Special?

💡 Think of it as ~ nginx with superpowers Get the reliability and performance of a production-grade proxy, combined with the flexibility to programmatically modify any aspect of HTTP traffic.

Common Use Cases:

  • 🔐 Add authentication headers
  • 📊 Inject analytics scripts into web pages
  • 🧪 Mock API responses for testing
  • 🔗 Rewrite URLs and links
  • 🛡️ Sanitize sensitive data
  • 🎲 Implement custom routing logic

🎨 Developer Experience First

# Zero-code configuration - just edit YAML!post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "link_rewrite"params:
from_domain: "example.com"to_domain: "example.com.local"

🟢 Start Simple: Use built-in YAML hooks for redirects, text replacement, and HTML modifications

🟡 Scale Up: Write custom Python hooks with full access to request/response data

🔵 Go Advanced: Implement rate limiting, caching, A/B testing, or external API integration

Async architecture ensures modifications don't compromise performance, handling thousands of concurrent connections efficiently.

🌍 Perfect For Every Environment

EnvironmentUse CaseBenefits
🔧 DevelopmentTest API responsesNo backend changes needed
🧪 QA/TestingInject test dataSimulate edge cases easily
🚀 ProductionContent transformationAdd security headers on-the-fly
🔬 SecurityTraffic analysisIntercept and modify requests

Seamless nginx integration for production deployments - handle SSL termination and load balancing while python-proxy focuses on intelligent content modification.

🛠️ Extensible Architecture

Built-in hooks handle common operations:

  • ↩️ 301/302 redirects
  • 📝 JSON field manipulation
  • 🏗️ HTML element modifications (XPath)
  • 🔗 Link rewriting
  • 🌐 Content fetching from external sources

Python hook system provides:

  • 🔍 Automatic discovery
  • 🎯 Decorator support
  • ⚠️ Comprehensive error handling
  • 🎛️ Full programmatic access

Whether you're a developer needing quick traffic manipulation or a DevOps engineer building sophisticated proxy infrastructure, python-proxy scales from simple scripts to enterprise deployments.


🎁 Features

  • Async/Await Architecture: Built on aiohttp for high-performance async I/O
  • 📤 Request Modification: Modify requests before they're proxied (headers, body, URL, etc.)
  • 📥 Response Modification: Modify responses after receiving from target (HTML injection, content replacement, etc.)
  • 🎣 Hook System: Simple Python-based hook system with automatic discovery
  • ⚙️ Configuration-Based Hooks: Powerful built-in hooks (redirects, rewrites, HTML/text transformation) via YAML config - no coding required!
  • 🔧 Flexible Configuration: Configure via CLI arguments, environment variables, or YAML config file
  • 🎯 Header-Based Routing: Route requests to different targets using X-Proxy-Server header

📦 Installation

# Install from source
pip install -e .# Or install dependencies directly
pip install -r requirements.txt

💡 Requirements: Python 3.8 or higher


🚀 Quick Start

💻 Basic Usage

# Start proxy on default port 8080
python-proxy
# Start with custom port
python-proxy --port 3128
# Proxy all requests to a specific target
python-proxy --target http://example.com
# Use a configuration file
python-proxy --config config.yaml

⚡ Quick Start with realmo.com.local (Default Configuration)

🎯 The default config.yaml is pre-configured for proxying realmo.com locally with automatic link rewriting!

# 1️⃣ Add to /etc/hostsecho"127.0.0.1 realmo.com.local"| sudo tee -a /etc/hosts
# 2️⃣ Set up port 80 capability (one-time)
./scripts/setup_port80.sh
# 3️⃣ Start proxy with default config
python-proxy --config config.yaml
# 4️⃣ Browse to http://realmo.com.local

✨ What this does:

  • 🔄 Proxies realmo.com.localrealmo.com:80
  • 🔗 Automatically rewrites all realmo.com links to realmo.com.local
  • 🎯 Keeps all traffic flowing through the proxy for testing/development

📚 See examples/REALMO_SETUP.md for detailed guide and customization options.

🔓 Running on Port 80 (Privileged Port)

✅ Quick Install (Recommended):

# Install wrapper and set up port 80 capability
./scripts/setup_port80.sh
# Now use from anywhere
python-proxy --host 192.168.2.7 --port 80

🔧 Manual Setup:

# One-time setup (resolves symlinks if needed)
sudo setcap 'cap_net_bind_service=+ep'$(readlink -f $(which python3))# Now run without sudo
python-proxy --host 192.168.2.7 --port 80

📚 See examples/port80_setup.md for detailed instructions and alternatives.

🌐 Using Environment Variables

export PROXY_PORT=8080
export PROXY_TARGET=http://example.com
export PROXY_HOOKS_DIR=./hooks
python-proxy

📡 Making Requests Through the Proxy

The proxy supports multiple ways to specify the backend target:

  1. X-Proxy-Server - Simple host or host:port format
  2. Default target - Configured via CLI or config file
  3. Automatic .local domains - Requests to hostname.local automatically route to hostname
# Using X-Proxy-Server (simple format)
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com" \
http://example.com/page
# Using X-Proxy-Server with custom port
curl -x http://localhost:8080 \
-H "X-Proxy-Server: example.com:8080" \
http://example.com/page
# Override the Host header sent to backend
curl -x http://localhost:8080 \
-H "X-Proxy-Server: 192.168.1.100:8080" \
-H "X-Proxy-Host: myapp.example.com" \
http://example.com/page
# With default target configured
curl -x http://localhost:8080 http://example.com/page

Header Reference

  • X-Proxy-Server: Backend server as host or host:port

    • Default port: 80 (http) if not specified
    • Port 443 automatically uses HTTPS
    • Examples: example.com, example.com:8080, 192.168.1.100:3000
  • X-Proxy-Host: Override the Host header sent to backend server

    • Useful for virtual hosting or when backend expects specific hostname
    • Example: myapp.example.com

Automatic .local Domain Routing

The proxy automatically strips the .local suffix from hostnames and routes to the actual domain on port 80 (standard HTTP). Any port specified in the .local request is ignored. This is useful for local development and testing.

# Request to example.com.local routes to example.com:80
curl -x http://localhost:8080 http://example.com.local/page
# Port in .local URL is ignored - still routes to port 80
curl -x http://localhost:8080 http://api.example.com.local:8080/data
# → Routes to api.example.com:80# Configure in /etc/hosts for easy testing:# 127.0.0.1 myapp.com.local
curl -x http://localhost:8080 http://myapp.com.local/

Behavior:

  • hostname.localhostname:80
  • hostname.local:XXXXhostname:80 (port ignored)
  • Always uses HTTP (port 80), not HTTPS

Use cases:

  • Local development: Test production URLs locally
  • /etc/hosts testing: Add .local entries to route through proxy
  • Network testing: Intercept specific domains without DNS changes

Example /etc/hosts setup:

# Add .local entries that proxy will strip and forward to port 80
127.0.0.1 api.example.com.local
127.0.0.1 cdn.example.com.local

Then requests to api.example.com.local:8080 go through your proxy to api.example.com:80.

🎣 Configuration-Based Hooks

NEW! Configure powerful hooks directly in your YAML config - no Python coding required!

Perfect for redirects, URL rewrites, content modification, and more.

💡 Quick Example

# config.yamlhost: "0.0.0.0"port: 8080hook_mappings:
# Pre-hooks (execute before backend, can skip backend call)pre_hooks:
- hostname: "example.com"url_pattern: "/old-page"hook: "redirect_301"params:
location: "https://example.com/new-page"# Post-hooks (execute after backend, modify response)post_hooks:
- hostname: "example.com"url_pattern: "/*"hook: "text_rewrite"params:
pattern: "OldCompany"replacement: "NewCompany"

🔌 Built-in hooks include:

TypeHooksPurpose
⬅️ Pre-hooksredirect_301, redirect_302, gone_410, not_found_404, static_htmlExecute before backend
➡️ Post-hooksurl_rewrite, text_rewrite, link_rewrite, html_rewrite, xpath_replace_from_url, json_modifyModify responses

✨ Features:

  • 🌐 Hostname patterns with wildcards (*.example.com)
  • 🔍 URL patterns with glob (/api/*) or regex (regex:^/api/v[0-9]+/)
  • ⏭️ Pre-hooks can skip backend calls (redirects, errors)
  • 🔧 Post-hooks modify content (HTML, text, JSON)
  • 📁 Organize hooks with includes: Separate hooks by hostname into dedicated files

📚 Learn more:


🔗 Nginx Integration

Use python-proxy with nginx as a frontend reverse proxy for production deployments.

Nginx Integration

Nginx handles: SSL termination, load balancing Python-proxy handles: Hook-based content modification

📚 See examples/NginxIntegration.md for complete configuration:

  • 🌐 Proxy entire site or specific paths
  • 🎯 Dynamic backend routing based on URL patterns
  • ⚖️ Load balancing with multiple python-proxy instances
  • 🔒 Production-ready setup with SSL/TLS
  • ⚡ Performance optimization and security best practices

🐍 Creating Custom Python Hooks

🎓 New to hooks? Start with Creating Custom Hooks - For Beginners A complete step-by-step tutorial with real-world examples!

For advanced use cases, you can write custom Python hooks. Place them in a hooks directory.

💡 Simple Hook Example

Create a file hooks/my_hooks.py:

asyncdefbefore_request(request, request_data):
"""Modify request before proxying."""# Add custom headerrequest_data["headers"]["X-Custom"] ="MyValue"returnrequest_dataasyncdefafter_response(response, body):
"""Modify response after receiving."""# Modify HTML contentifb"<html>"inbody:
body=body.replace(b"</body>", b"<!-- Modified --></body>")
returnbody

Then run with:

python-proxy --hooks ./hooks --target http://example.com

🚀 Advanced Hooks with Decorators

frompython_proxy.hooksimportbefore_request, after_response@before_requestasyncdefadd_auth(request, request_data):
"""Add authentication to API requests."""if"api.example.com"inrequest_data["url"]:
request_data["headers"]["Authorization"] ="Bearer TOKEN"returnrequest_data@after_responseasyncdefinject_script(response, body):
"""Inject JavaScript into HTML pages."""content_type=response.headers.get("Content-Type", "")
if"text/html"incontent_type:
html=body.decode("utf-8", errors="ignore")
script='<script>console.log("Proxied!")</script>'html=html.replace("</head>", f"{script}</head>")
returnhtml.encode("utf-8")
returnbody

📚 Learn more:


⚙️ Configuration

📝 Configuration File (YAML)

Create config.yaml:

host: "0.0.0.0"port: 8080target_host: "http://example.com"timeout: 30hooks_dir: "./hooks"log_level: "INFO"

🔢 Configuration Priority

  1. 🥇 CLI arguments (highest priority)
  2. 🥈 Configuration file (--config)
  3. 🥉 Environment variables
  4. 4️⃣ Default values (lowest priority)

🔓 Running on Port 80

⚠️ Ports below 1024 require special permissions. The proxy provides helpful error messages and multiple solutions.

# ✅ Quick setup (recommended)
./scripts/setup_port80.sh
# 🔧 Or manually
sudo setcap 'cap_net_bind_service=+ep'$(which python3)
python-proxy --host 192.168.2.7 --port 80

🔀 Other options:

  • 🔴 Run with sudo (not recommended for production)
  • 🔀 Use iptables port forwarding
  • ⚙️ Use systemd socket activation

📚 See examples/port80_setup.md for complete guide.


🛠️ Development

📥 Install Development Dependencies

pip install -r requirements-dev.txt

🧪 Run Tests

# Run all tests
pytest
# Run with coverage
pytest --cov=python_proxy
# Run specific test file
pytest tests/test_config.py

🔍 Linting

# Run ruff linter
ruff check .# Auto-fix issues
ruff check --fix .

🎯 Use Cases

Use CaseDescriptionBenefits
🕷️ Web ScrapingModify headers, inject credentialsBypass restrictions
🔧 DevelopmentTest different API responsesNo backend changes
🔐 Security TestingAnalyze and modify trafficFind vulnerabilities
💉 Content InjectionAdd scripts, styles, or contentTesting & analytics
🧪 API TestingModify requests/responsesSimulate edge cases
📊 Traffic AnalysisLog and analyze HTTP trafficDebug & monitor

📜 License

Copyright (C) 2025 Sergey Porfirievparf@difive.com

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

📄 License: GPL v2 - See LICENSE file for details.


Made with ❤️ by Sergey Porfiriev

⭐ Star this repo if you find it useful! • 🐛 Report issues • 💡 Contribute

About

Transparent Python Proxy (~ nginx), allows modification of select pages BEFORE proxying or AFTER

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages