Kokizzu Kokizzu - 4 months ago 38
HTTP Question

Correct way of getting Client's IP Addresses from http.Request (Golang)

What's the correct way to get all client's IP Addresses from

http.Request
? In
PHP
there are a lot of variables that I should check. Is it the same on Go?

One that I found is:

req.RemoteAddr


And is the request case sensitive? for example
x-forwarded-for
is the same as
X-Forwarded-For
and
X-FORWARDED-FOR
? (from
req.Header.Get("X-FORWARDED-FOR")
)

Answer

Looking at http.Request you can find the following member variables:

// HTTP defines that header names are case-insensitive.
// The request parser implements this by canonicalizing the
// name, making the first character and any characters
// following a hyphen uppercase and the rest lowercase.
//
// For client requests certain headers are automatically
// added and may override values in Header.
//
// See the documentation for the Request.Write method.
Header Header

// RemoteAddr allows HTTP servers and other software to record
// the network address that sent the request, usually for
// logging. This field is not filled in by ReadRequest and
// has no defined format. The HTTP server in this package
// sets RemoteAddr to an "IP:port" address before invoking a
// handler.
// This field is ignored by the HTTP client.
RemoteAddr string

You can use RemoteAddr to get the remote client's IP address and port (the format is "IP:port"), which is the address of the original requestor or the last proxy.

This is all that you have for sure. Then you can investigate the headers, which are case-insensitive (per documentation above), meaning all of your examples

req.Header.Get("X-Forwarded-For")
req.Header.Get("x-forwarded-for")
req.Header.Get("X-FORWARDED-FOR")

will work. This is also probably the field you want to take a look at, but it depends on the HTTP software used on the remote side. Client can put anything into there if it wishes to. Also, note the expected format of this field is the comma+space separated list of IP addresses. You will need to parse it a little bit to get a single IP of your choice (probably the first one in the list), for example:

// Assuming format is as expected
ips := strings.Split("10.0.0.1, 10.0.0.2, 10.0.0.3", ", ")
for _, ip := range ips {
    fmt.Println(ip)
}

will produce:

10.0.0.1
10.0.0.2
10.0.0.3
Comments