From d7e6597831777d50201e0a079f25d30bbd21c8b9 Mon Sep 17 00:00:00 2001 From: Edward Tsang Date: Wed, 25 Jul 2018 15:16:04 -0700 Subject: [PATCH 1/2] use http.CanonicalHeaderKey because it handles all normalization of headers, fix one test, also added forwarded but TBD --- Gopkg.lock | 9 +++++++++ Gopkg.toml | 30 ++++++++++++++++++++++++++++++ realip.go | 16 +++++++++++++--- realip_test.go | 12 ++++++++---- 4 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 Gopkg.lock create mode 100644 Gopkg.toml diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 0000000..bef2d00 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,9 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "ab4fef131ee828e96ba67d31a7d690bd5f2f42040c6766b1b12fe856f87e0ff7" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 0000000..24f0f17 --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,30 @@ +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[prune] + go-tests = true + unused-packages = true diff --git a/realip.go b/realip.go index e2803a2..f05e52c 100644 --- a/realip.go +++ b/realip.go @@ -7,6 +7,15 @@ import ( "strings" ) +// Should use canonical format of the header key s +// https://golang.org/pkg/net/http/#CanonicalHeaderKey +var xForwardedFor = http.CanonicalHeaderKey("X-Forwarded-For") +var xRealIP = http.CanonicalHeaderKey("X-Real-IP") +// RFC7239 defines a new "Forwarded: " header designed to replace the +// existing use of X-Forwarded-* headers. +// e.g. Forwarded: for=192.0.2.60;proto=https;by=203.0.113.43 +var forwarded = http.CanonicalHeaderKey("Forwarded") + var cidrs []*net.IPNet func init() { @@ -49,11 +58,12 @@ func isPrivateAddress(address string) (bool, error) { return false, nil } -// FromRequest return client's real public IP address from http request headers. +// FromRequest returns client's real public IP address from http request headers. func FromRequest(r *http.Request) string { // Fetch header value - xRealIP := r.Header.Get("X-Real-Ip") - xForwardedFor := r.Header.Get("X-Forwarded-For") + xRealIP := r.Header.Get(xRealIP) + xForwardedFor := r.Header.Get(xForwardedFor) + // forwarded := r.Header.Get(forwarded) // If both empty, return IP from remote address if xRealIP == "" && xForwardedFor == "" { diff --git a/realip_test.go b/realip_test.go index e80efe0..42bda65 100644 --- a/realip_test.go +++ b/realip_test.go @@ -1,6 +1,7 @@ package realip import ( + "fmt" "net/http" "testing" ) @@ -51,10 +52,9 @@ func TestRealIP(t *testing.T) { newRequest := func(remoteAddr, xRealIP string, xForwardedFor ...string) *http.Request { h := http.Header{} h.Set("X-Real-IP", xRealIP) - for _, address := range xForwardedFor { - h.Set("X-Forwarded-For", address) - } - + for _, address := range xForwardedFor { + h.Set("X-Forwarded-For", address) + } return &http.Request{ RemoteAddr: remoteAddr, Header: h, @@ -80,6 +80,10 @@ func TestRealIP(t *testing.T) { request: newRequest("", "", localAddr, publicAddr1, publicAddr2), expected: publicAddr2, }, { + name: "Has multiple address for X-Forwarded-For", + request: newRequest("", "", localAddr, fmt.Sprintf("%s,%s", publicAddr1, publicAddr2)), + expected: publicAddr1, + }, { name: "Has X-Real-IP", request: newRequest("", publicAddr1), expected: publicAddr1, From 989b951490cbf84d1a9909d981f882120d73eef5 Mon Sep 17 00:00:00 2001 From: Edward Tsang Date: Wed, 25 Jul 2018 17:44:05 -0700 Subject: [PATCH 2/2] gofmt --- realip.go | 3 ++- realip_test.go | 20 +++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/realip.go b/realip.go index f05e52c..cd32af1 100644 --- a/realip.go +++ b/realip.go @@ -11,6 +11,7 @@ import ( // https://golang.org/pkg/net/http/#CanonicalHeaderKey var xForwardedFor = http.CanonicalHeaderKey("X-Forwarded-For") var xRealIP = http.CanonicalHeaderKey("X-Real-IP") + // RFC7239 defines a new "Forwarded: " header designed to replace the // existing use of X-Forwarded-* headers. // e.g. Forwarded: for=192.0.2.60;proto=https;by=203.0.113.43 @@ -63,7 +64,7 @@ func FromRequest(r *http.Request) string { // Fetch header value xRealIP := r.Header.Get(xRealIP) xForwardedFor := r.Header.Get(xForwardedFor) - // forwarded := r.Header.Get(forwarded) + // forwarded := r.Header.Get(forwarded) // If both empty, return IP from remote address if xRealIP == "" && xForwardedFor == "" { diff --git a/realip_test.go b/realip_test.go index 42bda65..fce22c7 100644 --- a/realip_test.go +++ b/realip_test.go @@ -1,7 +1,7 @@ package realip import ( - "fmt" + "fmt" "net/http" "testing" ) @@ -51,10 +51,12 @@ func TestRealIP(t *testing.T) { newRequest := func(remoteAddr, xRealIP string, xForwardedFor ...string) *http.Request { h := http.Header{} - h.Set("X-Real-IP", xRealIP) - for _, address := range xForwardedFor { - h.Set("X-Forwarded-For", address) - } + if xRealIP != "" { + h.Set("X-Real-IP", xRealIP) + } + for _, address := range xForwardedFor { + h.Set("X-Forwarded-For", address) + } return &http.Request{ RemoteAddr: remoteAddr, Header: h, @@ -80,10 +82,10 @@ func TestRealIP(t *testing.T) { request: newRequest("", "", localAddr, publicAddr1, publicAddr2), expected: publicAddr2, }, { - name: "Has multiple address for X-Forwarded-For", - request: newRequest("", "", localAddr, fmt.Sprintf("%s,%s", publicAddr1, publicAddr2)), - expected: publicAddr1, - }, { + name: "Has multiple address for X-Forwarded-For", + request: newRequest("", "", localAddr, fmt.Sprintf("%s,%s", publicAddr1, publicAddr2)), + expected: publicAddr1, + }, { name: "Has X-Real-IP", request: newRequest("", publicAddr1), expected: publicAddr1,