tower-web icon indicating copy to clipboard operation
tower-web copied to clipboard

There should be a way to get a peer's IP address

Open miquels opened this issue 7 years ago • 6 comments

There should be a way to get the peer's IP address, e.g. tcpstream.peer_addr(). A peer_addr() or client_addr() method should be added to the request struct.

If this issue should be filed with hyper instead let me know.

miquels avatar Aug 20 '18 08:08 miquels

As a work-around, if you're behind a reverse proxy, you can have the proxy server add an x-forwarded-for or x-real-ip header

jwilm avatar Aug 20 '18 16:08 jwilm

There are a few ways that the client IP address can be exposed:

  1. Storing it in the http Extensions map.
  2. Defining a new Request type that has additional fields.
  3. Adding IP address to http::Request
  4. Storing it in the x-real-ip (or other) header.

You have thoughts @seanmonstar?

carllerche avatar Aug 22 '18 03:08 carllerche

Storing it in the http Extensions map.

Probably best option, but the sad part is that it means everyone pays to store the value even though only some need access to it...

Defining a new Request type that has additional fields.

Definitely the least attractive option (why have http::Request if we have to newtype over it?).

Adding IP address to http::Request

The reason for it not being there in the first place is because it doesn't always make sense; it's mixing HTTP with TCP/IP. Some transports have no concept of an IP address (like UDS).

Storing it in the x-real-ip (or other) header.

I think users should probably look for that header, since in most cases, the client isn't directly connected to their server, but there's usually several steps of load balancers in the way. But I don't think a framework should be inserting this header if it didn't already exist.

seanmonstar avatar Aug 22 '18 19:08 seanmonstar

a framework

And I'd expect a framework to provide an abstraction over these (x-real-ip || ... || TCP address).

no concept of an IP address (like UDS).

Great point! This feels something that Go takes advantage of and makes sense. Seems like this will always have to be an Option.

shepmaster avatar Aug 22 '18 19:08 shepmaster

@seanmonstar I agree with your summary.

Though, a thought occurs. I wonder if additional data could be passed via the generic in Request<T>.

Then, there would need to be an additional trait bound: BufStream + SomethingElse to access the addr. Middleware would have to be able to preserve that extra data too somehow.

carllerche avatar Aug 24 '18 16:08 carllerche

Storing it in the http Extensions map.

Probably best option, but the sad part is that it means everyone pays to store the value even though only some need access to it...

How about doing that only when asked for, say by adding a method to the Builder like pub fn save_client_ip_address(self, val: bool) -> Self ?

miquels avatar Aug 28 '18 08:08 miquels