Reverse proxy & feedback #3120
antoniosarosi
started this conversation in
Show and tell
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
I've been working on a little reverse proxy project over the last couple weeks, nothing serious, just for fun. Here are some issues I found specific to
hyper
and this kind of projects:HTTP/1.1 Upgraded connections
There is an example of how connection upgrades work with
hyper
here, but it doesn't apply to reverse proxies, since they don't handle the upgraded connection themselves. Instead, they have to set up a tunnel and forward data from the client to the upstream server and viceversa. There is also an example of how to set up a tunnel here, this is used with theCONNECT
header by a forward proxy. The problem with a reverse proxy is that it cannot immediately upgrade the connection, it has to send the request to the upstream server and wait for theHTTP 101
response, then upgrade the connection and send that response back to the client.The examples use
hyper::upgrade::on
to upgrade on either a request or response. The issue is that upgrading on a request as a server requires giving up ownership on that request, because you need to spawn a Tokio task since thehyper::upgrade::on
future will not resolve until you send anHTTP 101
response back to the client. From this example:As a reverse proxy, you have to forward the incoming request to the upstream server and also upgrade on it, which you can't do easily because for both actions you need ownership on the request. So this is more or less what I ended up doing:
I found out while reading through the source code that
hyper::upgrade::on
basically calls this function:So I figured out I can do that manually and then await the
OnUpgrade
futures like this:It works, but I'm not sure if it's okay to remove that extension from the request and response.
No access to the underlying socket
I implemented the
Forwarded
HTTP header, for which I need to know my listening address and the client address. In previous versions (I'm using1.0.0-rc2
) there was a methodremote_addr()
on the request or an extension type, but it's not available anymore. I found this response to an issue from 2018, so that's what I did, I just made my own struct that implementsService
:This is not a really a problem but it adds boilerplate, because if I could get the socket addresses from the request I wouldn't have to implement
Service
, I could useservice_fn
and a function.Body types
Other than that everything was great, I just missed some documentation on body types as some examples (http_proxy, web_api, echo) tend to use
BoxBody
but they don't explain why. I'm assuming it's becauseBoxBody
can represent both an incoming body and a complete body, so it's useful for echoing requests or sending a custom 404 response under the same return type. I'll update this discussion if I find more issues while implementing new features.Beta Was this translation helpful? Give feedback.
All reactions