Hello, I just wanted to know the rational for making the HTTP::Request uri private.
And consequently what is the best way to check the scheme from the handler context?
One can obviously URI.parse the @resource and check the scheme but it seems redundant since that is what the uri private method does.
I would have made a pull request for adding a scheme method, but it feels so obvious that I feel there might be a strong reason not to have it.
It feels more and more weird to see such issues in the main language repository. Related: https://github.com/crystal-lang/crystal/issues/5215
Not to derail the original issue, but I think HTTP::Server is basic enough to be in the stdlib, I see RUST where the most basic things will send you searching which is the best HTTP Client or Server libs out there, and then splitting comes in, wasting community resources, etc..
On topic:
Request#uri usually doesn't include a scheme because it parses the URI from Request#resource which is typically a relative URL containing only the (full) path. It can be an absolute path but that's not typically used (except for PROXY requests).
Everything provided by parsing the typically relative request URI can be accessed by Request#path and Request#query_params.
@mig-hub I'd like to hear about your use case, do you actually have requests with absolute URIs?
@straight-shoota Oh yes that makes perfect sense, sorry I got confused. My use case is very basic, I wanted to implement an SSL enforcer on some paths for a project.
Does it make sense to make a pull request for a HTTP::Request#scheme like Ruby Rack Request? or would you rather not have this in stdlib?
Feels related to #5784 (and its related issues & PRs)
I'm not sure if something like Request#scheme (or Request#tls?) makes much sense. It should be simple to detect, when reading the request if the IO is a SSLSocket, it's served over TSL. But that only means that the Crystal app directly terminates the TSL session. In production environments it is often recommended to put a reverse proxy like nginx in front which usually also handles TLS. It would be pretty much meaningless if the app communicates with the proxy over TLS (could be incorrect in both ways). You would rather be interested in whether the proxy connects to the client via TLS. The X-Forwarded-Proto is typically used for this.
As @jhass pointed out, having direct access to the connection of a request could help your purpose. Even when the TLS termination is transparently handled, you would know by the local port whether that's an encrypted interface or not.
@straight-shoota yes my question was more when there is a load balancer. Seeing the rack implementation, I was not sure how standard X-Forwarded-Proto is, since they have other possible headers on the rack version.
X-Forwarded-Proto is pretty common. But there are others too. In the end, it completely depends on how the application is deployed. And that's also an issue for providing a generic API for that.
Furthermore, if the application is accessible without a reverse proxy overriding the protocol header, the client could forge it. When using such security-related headers, it needs to be ensured that the application is only available through a trusted reverse proxy, or the individual request needs to be validated to come from a trusted host.
This is all very much specific to the individual application, or rather it's deployment. I don't think there could be a generic solution.