parent
							
								
									c6fdfc9cd5
								
							
						
					
					
						commit
						e21a425f88
					
				
							
								
								
									
										2
									
								
								AUTHORS
								
								
								
								
							
							
						
						
									
										2
									
								
								AUTHORS
								
								
								
								
							|  | @ -13,6 +13,8 @@ Frederick F. Kautz IV <fkautz@alumni.cmu.edu> | ||||||
| Josh Hawn <josh.hawn@docker.com> | Josh Hawn <josh.hawn@docker.com> | ||||||
| Nghia Tran <tcnghia@gmail.com> | Nghia Tran <tcnghia@gmail.com> | ||||||
| Olivier Gambier <olivier@docker.com> | Olivier Gambier <olivier@docker.com> | ||||||
|  | Richard <richard.scothern@gmail.com> | ||||||
|  | Shreyas Karnik <karnik.shreyas@gmail.com> | ||||||
| Stephen J Day <stephen.day@docker.com> | Stephen J Day <stephen.day@docker.com> | ||||||
| Tianon Gravi <admwiggin@gmail.com> | Tianon Gravi <admwiggin@gmail.com> | ||||||
| xiekeyang <xiekeyang@huawei.com> | xiekeyang <xiekeyang@huawei.com> | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ package context | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
|  | 	"net" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"sync" | 	"sync" | ||||||
|  | @ -17,26 +18,27 @@ var ( | ||||||
| 	ErrNoRequestContext = errors.New("no http request in context") | 	ErrNoRequestContext = errors.New("no http request in context") | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // http.Request.RemoteAddr is not the originating IP if the request
 | // RemoteAddr extracts the remote address of the request, taking into
 | ||||||
| // came through a reverse proxy.
 | // account proxy headers.
 | ||||||
| // X-Forwarded-For and X-Real-IP provide this information with decreased
 |  | ||||||
| // support, so check in that order.  There may be multiple 'X-Forwarded-For'
 |  | ||||||
| // headers, but go maps don't retain order so just pick one.
 |  | ||||||
| func RemoteAddr(r *http.Request) string { | func RemoteAddr(r *http.Request) string { | ||||||
| 	remoteAddr := r.RemoteAddr | 	if prior := r.Header.Get("X-Forwarded-For"); prior != "" { | ||||||
| 
 | 		proxies := strings.Split(prior, ",") | ||||||
| 	if prior, ok := r.Header["X-Forwarded-For"]; ok { |  | ||||||
| 		proxies := strings.Split(prior[0], ",") |  | ||||||
| 		if len(proxies) > 0 { | 		if len(proxies) > 0 { | ||||||
| 			remoteAddr = strings.Trim(proxies[0], " ") | 			remoteAddr := strings.Trim(proxies[0], " ") | ||||||
|  | 			if net.ParseIP(remoteAddr) != nil { | ||||||
|  | 				return remoteAddr | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} else if realip, ok := r.Header["X-Real-Ip"]; ok { | 	} | ||||||
| 		if len(realip) > 0 { | 	// X-Real-Ip is less supported, but worth checking in the
 | ||||||
| 			remoteAddr = realip[0] | 	// absence of X-Forwarded-For
 | ||||||
|  | 	if realIP := r.Header.Get("X-Real-Ip"); realIP != "" { | ||||||
|  | 		if net.ParseIP(realIP) != nil { | ||||||
|  | 			return realIP | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return remoteAddr | 	return r.RemoteAddr | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // WithRequest places the request on the context. The context of the request
 | // WithRequest places the request on the context. The context of the request
 | ||||||
|  | @ -44,7 +46,6 @@ func RemoteAddr(r *http.Request) string { | ||||||
| // is available at "http.request". Other common attributes are available under
 | // is available at "http.request". Other common attributes are available under
 | ||||||
| // the prefix "http.request.". If a request is already present on the context,
 | // the prefix "http.request.". If a request is already present on the context,
 | ||||||
| // this method will panic.
 | // this method will panic.
 | ||||||
| 
 |  | ||||||
| func WithRequest(ctx context.Context, r *http.Request) context.Context { | func WithRequest(ctx context.Context, r *http.Request) context.Context { | ||||||
| 	if ctx.Value("http.request") != nil { | 	if ctx.Value("http.request") != nil { | ||||||
| 		// NOTE(stevvooe): This needs to be considered a programming error. It
 | 		// NOTE(stevvooe): This needs to be considered a programming error. It
 | ||||||
|  |  | ||||||
|  | @ -214,16 +214,15 @@ func TestWithVars(t *testing.T) { | ||||||
| // at the transport layer to 127.0.0.1:<port> .  However, as the X-Forwarded-For header
 | // at the transport layer to 127.0.0.1:<port> .  However, as the X-Forwarded-For header
 | ||||||
| // just contains the IP address, it is different enough for testing.
 | // just contains the IP address, it is different enough for testing.
 | ||||||
| func TestRemoteAddr(t *testing.T) { | func TestRemoteAddr(t *testing.T) { | ||||||
| 	expectedRemote := "127.0.0.1" | 	var expectedRemote string | ||||||
| 	var actualRemote string |  | ||||||
| 	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | 	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		defer r.Body.Close() | 		defer r.Body.Close() | ||||||
| 
 | 
 | ||||||
| 		if r.RemoteAddr == expectedRemote { | 		if r.RemoteAddr == expectedRemote { | ||||||
| 			t.Errorf("Unexpected matching remote addresses") | 			t.Errorf("Unexpected matching remote addresses") | ||||||
| 		} | 		} | ||||||
| 		actualRemote = RemoteAddr(r) |  | ||||||
| 
 | 
 | ||||||
|  | 		actualRemote := RemoteAddr(r) | ||||||
| 		if expectedRemote != actualRemote { | 		if expectedRemote != actualRemote { | ||||||
| 			t.Errorf("Mismatching remote hosts: %v != %v", expectedRemote, actualRemote) | 			t.Errorf("Mismatching remote hosts: %v != %v", expectedRemote, actualRemote) | ||||||
| 		} | 		} | ||||||
|  | @ -241,14 +240,35 @@ func TestRemoteAddr(t *testing.T) { | ||||||
| 	frontend := httptest.NewServer(proxy) | 	frontend := httptest.NewServer(proxy) | ||||||
| 	defer frontend.Close() | 	defer frontend.Close() | ||||||
| 
 | 
 | ||||||
| 	getReq, err := http.NewRequest("GET", frontend.URL, nil) | 	// X-Forwarded-For set by proxy
 | ||||||
|  | 	expectedRemote = "127.0.0.1" | ||||||
|  | 	proxyReq, err := http.NewRequest("GET", frontend.URL, nil) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	_, err = http.DefaultClient.Do(proxyReq) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// RemoteAddr in X-Real-Ip
 | ||||||
|  | 	getReq, err := http.NewRequest("GET", backend.URL, nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	expectedRemote = "1.2.3.4" | ||||||
|  | 	getReq.Header["X-Real-ip"] = []string{expectedRemote} | ||||||
| 	_, err = http.DefaultClient.Do(getReq) | 	_, err = http.DefaultClient.Do(getReq) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// Valid X-Real-Ip and invalid X-Forwarded-For
 | ||||||
|  | 	getReq.Header["X-forwarded-for"] = []string{"1.2.3"} | ||||||
|  | 	_, err = http.DefaultClient.Do(getReq) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -43,7 +43,6 @@ func NewBridge(ub URLBuilder, source SourceRecord, actor ActorRecord, request Re | ||||||
| 
 | 
 | ||||||
| // NewRequestRecord builds a RequestRecord for use in NewBridge from an
 | // NewRequestRecord builds a RequestRecord for use in NewBridge from an
 | ||||||
| // http.Request, associating it with a request id.
 | // http.Request, associating it with a request id.
 | ||||||
| 
 |  | ||||||
| func NewRequestRecord(id string, r *http.Request) RequestRecord { | func NewRequestRecord(id string, r *http.Request) RequestRecord { | ||||||
| 	return RequestRecord{ | 	return RequestRecord{ | ||||||
| 		ID:        id, | 		ID:        id, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue