@@ -131,34 +131,51 @@ class NextPage(BaseModel, Generic[PageParameters]):
131131 parameters : PageParameters | None = None
132132
133133
134- def iter_originating_hosts (request : web .Request ) -> Iterator [str ]:
134+ def iter_origins (request : web .Request ) -> Iterator [str ]:
135135 #
136136 # SEE https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host
137137 # SEE https://doc.traefik.io/traefik/getting-started/faq/#what-are-the-forwarded-headers-when-proxying-http-requests
138138 seen = set ()
139139
140- forwarded = request .headers .get ("X-Forwarded-Host" )
141- if forwarded :
140+ fwd_protos = [
141+ p .strip ()
142+ for p in request .headers .get ("X-Forwarded-Proto" ).split ("," )
143+ if p .strip ()
144+ ]
145+ fwd_hosts = [
146+ h .strip ()
147+ for h in request .headers .get ("X-Forwarded-Host" ).split ("," )
148+ if h .strip ()
149+ ]
150+ fwd_ports = [
151+ pt .strip ()
152+ for pt in request .headers .get ("X-Forwarded-Port" ).split ("," )
153+ if pt .strip ()
154+ ]
155+
156+ fwd_origins = [
157+ f"{ proto } ://{ host } :{ port } "
158+ for proto , host , port in zip (fwd_protos , fwd_hosts , fwd_ports , strict = False )
159+ ]
160+ if fwd_origins :
142161 # X-Forwarded-Host can contain a comma-separated list of hosts
143162 # (when the request passes through multiple proxies)
144- for host in forwarded .split ("," ):
145- stripped_host = host .strip ().partition (":" )[0 ]
146- if stripped_host and stripped_host not in seen :
147- seen .add (stripped_host )
148- yield host
163+ for origin in fwd_origins :
164+ if origin and origin not in seen :
165+ seen .add (origin )
166+ yield origin
149167
150168 # Fallback to request.host
151- if request .host :
152- host = request .host .partition (":" )[0 ]
153- if host not in seen :
154- yield host
169+ if request .url :
170+ origin = f"{ request .url .scheme } ://{ request .url .host } "
171+ if request .url .port :
172+ origin += f":{ request .url .port } "
173+ yield origin
155174
156175
157176def get_api_base_url (request : web .Request ) -> str :
158- originating_host = next (iter_originating_hosts (request ))
177+ api_host = next (iter_origins (request ))
159178 api_host = (
160- f"api.{ originating_host } "
161- if not is_ip_address (originating_host )
162- else originating_host
179+ f"api.{ api_host } " if not is_ip_address (api_host ) else api_host # in tests
163180 )
164181 return f"{ request .url .with_host (api_host ).with_port (None ).with_path ('' )} "
0 commit comments