fix(reverseproxy): set is_proxied=True when X-Forwarded-Proto is present#3595
Open
austin-rt wants to merge 2 commits intojaneczku:masterfrom
Open
fix(reverseproxy): set is_proxied=True when X-Forwarded-Proto is present#3595austin-rt wants to merge 2 commits intojaneczku:masterfrom
austin-rt wants to merge 2 commits intojaneczku:masterfrom
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Default config_external_port to NULL instead of 8083 so it doesn't
mislead when a reverse proxy is in use
- Fall back to DEFAULT_PORT at runtime in kobo.py when port is NULL
- Handle blank port submission in admin.py (previously crashed with
int('') ValueError)
- Pass is_proxied to config and admin templates
- Show placeholder 8083 and proxy help text on config form
- Show "Not set — reverse proxy detected" on admin display
Co-authored-by: Cursor <cursoragent@cursor.com>
Author
|
Status: All changes verified via automated e2e testing against a fresh Docker install behind a Cloudflare Tunnel — Kobo sync URLs correctly use the public hostname, config saves cleanly with a blank port field, and reverse proxy detection works. Keeping this as a draft until I can confirm full end-to-end sync onto a physical Kobo device. Will mark ready for review once that's verified. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When Calibre-Web is served through a Cloudflare Tunnel (or any reverse proxy that sends
X-Forwarded-ProtowithoutX-Forwarded-Host), the Kobo sync URL is generated withlocalhost:8083instead of the public HTTPS URL.Root cause:
ReverseProxied.is_proxiedonly returnsTruewhenHTTP_X_FORWARDED_HOSTis present. Cloudflare Tunnel (and most standard reverse proxy configurations including nginx, Caddy, and Traefik in their default configs) sendsX-Forwarded-Protobut notX-Forwarded-Host, sois_proxiedstaysFalse. This causeskobo.py:get_download_url_for_book()to fall back to an explicithost:portURL, appending the internal container port (default 8083) — e.g.https://books.example.com:8083/kobo/.... This breaks Kobo wireless sync silently: books appear in the library but fail to download.My Setup
Changes
1.
cps/reverseproxy.py— Core fixAlso check
X-Forwarded-Protowhen determining scheme, and setself.proxied = Truewhenever any proxy header is detected — consistent with the existingX-Forwarded-Hostbehaviour.2.
cps/config_sql.py— Schema default changeChanged
config_external_portcolumn default from8083toNone. The old default was misleading behind a proxy — it caused the port to always be appended to URLs even when it shouldn't be.3.
cps/kobo.py— Runtime fallbackFall back to
DEFAULT_PORT(8083) at runtime whenconfig_external_portisNone, preserving existing behavior for non-proxied setups.4.
cps/admin.py— Blank port handling + proxy contextis_proxiedtoconfig_edit.htmlandadmin.htmltemplatesNULLinstead of crashing (int('')threwValueError)5.
cps/templates/config_edit.html— Port field UXrequired; value is blank whenNULL; placeholder shows80836.
cps/templates/admin.html— Config display8083if not proxied and not setNotes
ProxyFixin__init__.pyalready correctly handlesX-Forwarded-Protofor scheme detection, andTRUSTED_PROXY_COUNTis documented for Cloudflare Tunnel. This closes the gap inis_proxied, which is a separate check used bykobo.py.X-Forwarded-Protois the most universally forwarded proxy header — this fix broadensis_proxieddetection to cover Cloudflare Tunnel and the majority of standard proxy setups that don't explicitly setX-Forwarded-Host.Verified
Tested end-to-end on a fresh Docker install behind a Cloudflare Tunnel:
X-Forwarded-Proto8083https://...)localhost:8083)Note: Python isn't my primary language so apologies if the implementation isn't idiomatic — happy to iterate based on feedback.