157 lines
6.3 KiB
HTML
157 lines
6.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Reverse Proxy - pyserve</title>
|
|
<link rel="stylesheet" href="../style.css">
|
|
</head>
|
|
<body>
|
|
<div id="container">
|
|
<div id="header">
|
|
<h1>pyserve</h1>
|
|
<div class="tagline">python application orchestrator</div>
|
|
</div>
|
|
|
|
<div class="breadcrumb">
|
|
<a href="../index.html">pyserve</a> » <a href="/guides/">Guides</a> » Reverse Proxy
|
|
</div>
|
|
|
|
<div id="content">
|
|
<h2>Reverse Proxy</h2>
|
|
|
|
<p>pyserve can act as a reverse proxy, forwarding requests to backend services.</p>
|
|
|
|
<h3>Basic Proxy Configuration</h3>
|
|
<p>Use the <code>proxy_pass</code> directive in routing:</p>
|
|
|
|
<pre><span class="directive">extensions:</span>
|
|
- <span class="directive">type:</span> <span class="value">routing</span>
|
|
<span class="directive">config:</span>
|
|
<span class="directive">regex_locations:</span>
|
|
<span class="value">"~^/api/"</span>:
|
|
<span class="directive">proxy_pass:</span> <span class="value">"http://localhost:9001"</span></pre>
|
|
|
|
<p>All requests to <code>/api/*</code> will be forwarded to <code>http://localhost:9001/api/*</code>.</p>
|
|
|
|
<h3>Proxy Headers</h3>
|
|
<p>pyserve automatically adds standard proxy headers:</p>
|
|
|
|
<table class="dirindex">
|
|
<tr>
|
|
<td><code>X-Forwarded-For</code></td>
|
|
<td>Client's IP address</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>X-Forwarded-Proto</code></td>
|
|
<td>Original protocol (http/https)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>X-Forwarded-Host</code></td>
|
|
<td>Original Host header</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>X-Real-IP</code></td>
|
|
<td>Client's real IP address</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<h3>Custom Headers</h3>
|
|
<p>Add custom headers to proxied requests:</p>
|
|
|
|
<pre><span class="value">"~^/api/"</span>:
|
|
<span class="directive">proxy_pass:</span> <span class="value">"http://localhost:9001"</span>
|
|
<span class="directive">headers:</span>
|
|
- <span class="value">"X-Custom-Header: my-value"</span>
|
|
- <span class="value">"Authorization: Bearer token123"</span></pre>
|
|
|
|
<h3>Dynamic Headers with Captures</h3>
|
|
<p>Use regex capture groups to build dynamic headers:</p>
|
|
|
|
<pre><span class="value">"~^/api/v(?P<version>\\d+)/(?P<service>\\w+)"</span>:
|
|
<span class="directive">proxy_pass:</span> <span class="value">"http://localhost:9001"</span>
|
|
<span class="directive">headers:</span>
|
|
- <span class="value">"X-API-Version: {version}"</span>
|
|
- <span class="value">"X-Service: {service}"</span>
|
|
- <span class="value">"X-Client-IP: $remote_addr"</span></pre>
|
|
|
|
<p>Special variables:</p>
|
|
<ul class="indent">
|
|
<li><code>{capture_name}</code> — Named capture group from regex</li>
|
|
<li><code>$remote_addr</code> — Client's IP address</li>
|
|
</ul>
|
|
|
|
<h3>Proxy Timeout</h3>
|
|
<p>Configure timeout for proxy requests:</p>
|
|
|
|
<pre><span class="comment"># Global default timeout</span>
|
|
<span class="directive">server:</span>
|
|
<span class="directive">proxy_timeout:</span> <span class="value">30.0</span>
|
|
|
|
<span class="comment"># Per-route timeout</span>
|
|
<span class="directive">extensions:</span>
|
|
- <span class="directive">type:</span> <span class="value">routing</span>
|
|
<span class="directive">config:</span>
|
|
<span class="directive">regex_locations:</span>
|
|
<span class="value">"~^/api/slow"</span>:
|
|
<span class="directive">proxy_pass:</span> <span class="value">"http://localhost:9001"</span>
|
|
<span class="directive">timeout:</span> <span class="value">120</span> <span class="comment"># 2 minutes for slow endpoints</span></pre>
|
|
|
|
<h3>URL Rewriting</h3>
|
|
<p>The proxy preserves the original request path by default:</p>
|
|
|
|
<pre><span class="comment"># Request: GET /api/users/123</span>
|
|
<span class="comment"># Proxied: GET http://backend:9001/api/users/123</span>
|
|
<span class="value">"~^/api/"</span>:
|
|
<span class="directive">proxy_pass:</span> <span class="value">"http://backend:9001"</span></pre>
|
|
|
|
<p>To proxy to a specific path:</p>
|
|
|
|
<pre><span class="comment"># Request: GET /api/users/123</span>
|
|
<span class="comment"># Proxied: GET http://backend:9001/v2/users/123 (path preserved)</span>
|
|
<span class="value">"~^/api/"</span>:
|
|
<span class="directive">proxy_pass:</span> <span class="value">"http://backend:9001/v2"</span></pre>
|
|
|
|
<h3>Load Balancing Example</h3>
|
|
<p>Route different services to different backends:</p>
|
|
|
|
<pre><span class="directive">extensions:</span>
|
|
- <span class="directive">type:</span> <span class="value">routing</span>
|
|
<span class="directive">config:</span>
|
|
<span class="directive">regex_locations:</span>
|
|
<span class="value">"~^/api/users"</span>:
|
|
<span class="directive">proxy_pass:</span> <span class="value">"http://user-service:8001"</span>
|
|
|
|
<span class="value">"~^/api/orders"</span>:
|
|
<span class="directive">proxy_pass:</span> <span class="value">"http://order-service:8002"</span>
|
|
|
|
<span class="value">"~^/api/products"</span>:
|
|
<span class="directive">proxy_pass:</span> <span class="value">"http://product-service:8003"</span></pre>
|
|
|
|
<h3>Error Handling</h3>
|
|
<p>pyserve returns appropriate error codes for proxy failures:</p>
|
|
|
|
<table class="dirindex">
|
|
<tr>
|
|
<td><code>502 Bad Gateway</code></td>
|
|
<td>Backend connection failed or returned invalid response</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>504 Gateway Timeout</code></td>
|
|
<td>Backend did not respond within timeout</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<div class="note">
|
|
<strong>Note:</strong> pyserve uses <code>httpx</code> for async HTTP requests
|
|
to backend services, supporting HTTP/1.1 and HTTP/2.
|
|
</div>
|
|
</div>
|
|
|
|
<div id="footer">
|
|
<p>pyserve © 2024-2025 | MIT License</p>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|