Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Effective request URL for HTTP::Server #10246

Open
straight-shoota opened this issue Jan 13, 2021 · 3 comments
Open

[RFC] Effective request URL for HTTP::Server #10246

straight-shoota opened this issue Jan 13, 2021 · 3 comments

Comments

@straight-shoota
Copy link
Member

straight-shoota commented Jan 13, 2021

Often web application does not need to be aware of by which address it is accessed. Internal links can just use relative URLs, so it doesn't matter how it is served to the client because the browser is just told to use the same authority it used for the original request.
But sometimes an app still needs to generate absolute URLs to internal resources. Examples for this are canonical URLs or presenting links for sharing.

A trivial solution is to set the hostname and protocol as a configuration value. This works well for simple environments. But it does not work when the application serves different host names or protocols (such as http and https). And it should not the app's responsibility to care about this. That's the job of network configuration, DNS, reverse proxies etc.

An often superior solution is to reconstruct the effective request URL (what the user entered into their browser) from the available data on a per-request basis. The path and query part of the URL is contained in every request as the resource property. But the scheme and authority are typically more complex to reconstruct.

For a directly exposed application the relevant information is in the Host header (and #remote_address as default). The protocol is currently not passed from HTTP::Server so it can only be guessed from the port. But this can be improved (see #5784).

For an application running behind a reverse proxy / load balancer, the information is typically transferred via headers such as X-Forwarded-Host, X-Forwarded-Proto and X-Forwarded-Port and others. Given there's no standardization on this, there are many different configurations to consider and allow for customization of accepted headers.

The most complex part is probably differntiation between whether an application is directly exposed to incoming connections (and handles TLS termination) or if it sits behind a reverse proxy. The reason is that you wouldn't want to blindly trust any forwarded host header (shame on you, Rails! rails/rails#29893). Whether an app is running behind a reverse proxy is as good as impossible to detect at runtime, so it needs configuration. An example for such configuration would be USE_X_FORWARDED_HOST for Django.

Such a "small" feature involves a high level of complexity. This could mean it's too much for stdlib and we should keep it simple. On the other hand, it's a relatively common necessity for web applications and users frequently trip over incomplete solutions. Having an default implementation available would be a great feature.

Related: #7096

@oprypin
Copy link
Member

oprypin commented Feb 8, 2021

This is definitely too much for stdlib, it should be left to web frameworks.

It's dubious to guess the host (+ yes, this invites security issues) and literally impossible to guess the protocol.

And even having done all that, a user is still better off just joining a pre-configured prefix "https://example.com" directly with the request path.

@oprypin
Copy link
Member

oprypin commented Feb 8, 2021

I should also note, even guessing the original /path is just guessing. A reverse proxy could've rewritten all of it, though the most typical one is stripping a prefix for the purpose of mounting an app onto that prefix path.

@jhass
Copy link
Member

jhass commented Sep 9, 2022

There's RFC7239, but a sensible implementation should still read the various non-standardized (X-) headers around this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants