Generic HTTP Forward Proxy (/proxy/forward)
Overview
/proxy/forward is a transparent HTTP relay endpoint. It forwards any HTTP request — any method, any body, any headers — to a destination URL using MediaFlow's outbound IP, then returns the upstream response verbatim.
Primary use cases:
- Debrid IP binding — Route debrid API calls (RealDebrid, AllDebrid, TorBox, etc.) through MediaFlow so the debrid service records MediaFlow's IP as the TCP source, not the addon server's IP. Combine with the
{mediaflow_ip}placeholder to keep theip=parameter consistent. - Extractor POST requests — Send JSON or form POST to a video host's extraction endpoint from MediaFlow's IP (resolves issue #271).
- Any IP-bound API call — Any HTTP API that must appear to come from the same IP that later fetches the stream.
Endpoint
ANY /proxy/forward
?d=<destination_url>
&api_password=<password> # required (or encrypted token)
[&h_<header-name>=<value>] # set outbound request header (repeatable)
[&r_<header-name>=<value>] # override response header (repeatable)
Methods
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS
Parameters
| Parameter | Required | Description |
|---|---|---|
d |
Yes | Destination URL. Must be http:// or https://. |
api_password |
Yes* | API password (*if API_PASSWORD is configured). |
h_<name> |
No | Set a request header sent to the destination. E.g. h_Authorization=Bearer tok. |
r_<name> |
No | Override a response header returned to the caller. |
Request body
The incoming request body is forwarded to the destination as-is. No base64, no envelope.
Response
The upstream HTTP status, headers (minus hop-by-hop), and body are returned verbatim.
{mediaflow_ip} placeholder
Embed the literal string {mediaflow_ip} anywhere in the destination URL or request body. MediaFlow substitutes it with its own public IP before forwarding.
This keeps the ip= parameter that debrid services use for CDN URL binding consistent with the TCP source of the API call.
Example — RealDebrid ip= binding:
GET /proxy/forward
?d=https://api.real-debrid.com/rest/1.0/torrents/instantAvailability/{hash}%3Fip%3D{mediaflow_ip}
&api_password=secret
&h_Authorization=Bearer <rd_token>
MediaFlow replaces {mediaflow_ip} with e.g. 1.2.3.4 before calling RealDebrid.
Public IP endpoint
GET /proxy/ip?api_password=<password>
Returns {"ip": "<public-ip>"} — MediaFlow's outbound IP. Useful when you need to retrieve MediaFlow's IP before making a separate request (e.g. appending ip= to a CDN URL).
Configure a static value with the PUBLIC_IP environment variable to skip the auto-detection request.
Safety controls
| Control | Default | Description |
|---|---|---|
| SSRF guard | Always on | Requests to loopback (127.x, ::1) and RFC-1918 private addresses are blocked with 403. |
| Allowlist | Empty (allow all) | Set FORWARD_ALLOWED_HOSTS to restrict forwarding to specific hostnames. |
| Denylist | Empty | Set FORWARD_DENIED_HOSTS to block additional hostnames. |
| Request body limit | 50 MB | Set FORWARD_MAX_REQUEST_BODY_BYTES. Blocks at the limit with 413. |
| Response body limit | 10 MB | Set FORWARD_MAX_RESPONSE_BODY_BYTES. Returns 502 if exceeded. |
| Auth required | Always | api_password or a valid encrypted token is mandatory. |
IP-disclosure header stripping
The following headers are stripped from the outbound request before forwarding so the caller's IP is never leaked:
X-Forwarded-For, X-Real-IP, X-Client-IP, True-Client-IP, Forwarded, CF-Connecting-IP, X-Original-Forwarded-For, X-Cluster-Client-IP
Examples
GET — API call through MediaFlow's IP
curl "http://localhost:8888/proxy/forward\
?d=https://api.real-debrid.com/rest/1.0/user\
&api_password=secret\
&h_Authorization=Bearer%20YOUR_RD_TOKEN"
POST JSON — extractor endpoint
curl -X POST \
"http://localhost:8888/proxy/forward\
?d=https://example.com/api/videos/abc123/playback\
&api_password=secret\
&h_Referer=https%3A%2F%2Fexample.com%2F\
&h_Content-Type=application%2Fjson" \
-d '{"fingerprint":{"userAgent":"Mozilla/5.0"}}'
POST form — debrid API
curl -X POST \
"http://localhost:8888/proxy/forward\
?d=https://api.real-debrid.com/rest/1.0/torrents/addMagnet\
&api_password=secret\
&h_Authorization=Bearer%20YOUR_RD_TOKEN\
&h_Content-Type=application%2Fx-www-form-urlencoded" \
--data-urlencode "magnet=magnet:?xt=urn:btih:..."
DELETE — remove a torrent
curl -X DELETE \
"http://localhost:8888/proxy/forward\
?d=https://api.real-debrid.com/rest/1.0/torrents/delete/TORRENT_ID\
&api_password=secret\
&h_Authorization=Bearer%20YOUR_RD_TOKEN"
Get MediaFlow's public IP
curl "http://localhost:8888/proxy/ip?api_password=secret"
# {"ip":"1.2.3.4"}
Configuration
New settings added to support /proxy/forward. All are optional.
| Environment variable | Default | Description |
|---|---|---|
PUBLIC_IP |
(auto-detected) | Static public IP returned by /proxy/ip and substituted for {mediaflow_ip}. Skip auto-detection on startup. |
FORWARD_ALLOWED_HOSTS |
[] |
Comma-separated allowlist of hostnames. Empty = allow any host. |
FORWARD_DENIED_HOSTS |
[] |
Comma-separated denylist of hostnames (in addition to the built-in private-IP guard). |
FORWARD_MAX_REQUEST_BODY_BYTES |
52428800 (50 MB) |
Maximum incoming request body size. Allows NZB/torrent file uploads. |
FORWARD_MAX_RESPONSE_BODY_BYTES |
10485760 (10 MB) |
Maximum upstream response body size. |
Comparison with /proxy/stream
| Feature | /proxy/stream |
/proxy/forward |
|---|---|---|
| Methods | GET, HEAD |
Any (GET, POST, PUT, PATCH, DELETE, …) |
| Request body | No | Yes (forwarded verbatim) |
| Range / partial content | Yes | No |
| HLS / DASH rewriting | Yes | No |
IP binding ({mediaflow_ip}) |
No | Yes |
| Response size limit | No | Yes (10 MB default) |
| Intended use | Video streaming | API calls, extractor POSTs |