|
|
@@ -157,7 +157,7 @@ func TestRequestBuilder_WithCookie(t *testing.T) {
|
|
|
defer server.Close()
|
|
|
|
|
|
builder := NewRequestBuilder()
|
|
|
- resp, err := builder.WithCookie(tt.cookie).ExecuteRequest(server.URL)
|
|
|
+ resp, err := builder.WithCookie(tt.cookie, server.URL).ExecuteRequest(server.URL)
|
|
|
if err != nil {
|
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
|
}
|
|
|
@@ -166,6 +166,145 @@ func TestRequestBuilder_WithCookie(t *testing.T) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+func TestRequestBuilder_WithCookieOnlySentToSameSite(t *testing.T) {
|
|
|
+ // The proxy receives the requests sent to any host, so no DNS is needed.
|
|
|
+ receivedCookies := make(chan string, 1)
|
|
|
+ proxyServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
+ select {
|
|
|
+ case receivedCookies <- r.Header.Get("Cookie"):
|
|
|
+ default:
|
|
|
+ }
|
|
|
+ w.WriteHeader(http.StatusOK)
|
|
|
+ }))
|
|
|
+ defer proxyServer.Close()
|
|
|
+
|
|
|
+ proxyURL, err := url.Parse(proxyServer.URL)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatalf("Unable to parse proxy URL: %v", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // The same builder is used for all requests, like when scraping the entries of a feed.
|
|
|
+ builder := NewRequestBuilder().
|
|
|
+ WithCustomApplicationProxyURL(proxyURL).
|
|
|
+ UseCustomApplicationProxyURL(true).
|
|
|
+ WithCookie("session=secret", "https://feeds.example.org/rss.xml")
|
|
|
+
|
|
|
+ tests := []struct {
|
|
|
+ requestURL string
|
|
|
+ expected string
|
|
|
+ }{
|
|
|
+ {"http://feeds.example.org/rss.xml", "session=secret"},
|
|
|
+ {"http://www.example.org/article.html", "session=secret"},
|
|
|
+ {"http://example.org/favicon.ico", "session=secret"},
|
|
|
+ {"http://example.net/article.html", ""},
|
|
|
+ {"http://feeds.example.org.example.net/rss.xml", ""},
|
|
|
+ {"http://cdn.example.com/icon.png", ""},
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, tt := range tests {
|
|
|
+ resp, err := builder.ExecuteRequest(tt.requestURL)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatalf("Expected no error for %q, got %v", tt.requestURL, err)
|
|
|
+ }
|
|
|
+ resp.Body.Close()
|
|
|
+
|
|
|
+ select {
|
|
|
+ case cookie := <-receivedCookies:
|
|
|
+ if cookie != tt.expected {
|
|
|
+ t.Errorf("Expected Cookie for %q to be %q, got %q", tt.requestURL, tt.expected, cookie)
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ t.Fatalf("Expected request to %q to be sent through the proxy", tt.requestURL)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestRequestBuilder_WithCookieNotForwardedOnRedirectToAnotherSite(t *testing.T) {
|
|
|
+ type receivedRequest struct {
|
|
|
+ host string
|
|
|
+ cookie string
|
|
|
+ }
|
|
|
+
|
|
|
+ receivedRequests := make(chan receivedRequest, 2)
|
|
|
+ proxyServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
+ select {
|
|
|
+ case receivedRequests <- receivedRequest{r.Host, r.Header.Get("Cookie")}:
|
|
|
+ default:
|
|
|
+ }
|
|
|
+
|
|
|
+ if r.Host == "www.example.org" {
|
|
|
+ http.Redirect(w, r, "http://example.net/article.html", http.StatusFound)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ w.WriteHeader(http.StatusOK)
|
|
|
+ }))
|
|
|
+ defer proxyServer.Close()
|
|
|
+
|
|
|
+ proxyURL, err := url.Parse(proxyServer.URL)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatalf("Unable to parse proxy URL: %v", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ builder := NewRequestBuilder().
|
|
|
+ WithCustomApplicationProxyURL(proxyURL).
|
|
|
+ UseCustomApplicationProxyURL(true).
|
|
|
+ WithCookie("session=secret", "https://feeds.example.org/rss.xml")
|
|
|
+
|
|
|
+ resp, err := builder.ExecuteRequest("http://www.example.org/article.html")
|
|
|
+ if err != nil {
|
|
|
+ t.Fatalf("Expected no error, got %v", err)
|
|
|
+ }
|
|
|
+ resp.Body.Close()
|
|
|
+
|
|
|
+ if len(receivedRequests) != 2 {
|
|
|
+ t.Fatalf("Expected the redirect to be followed, got %d requests", len(receivedRequests))
|
|
|
+ }
|
|
|
+
|
|
|
+ if request := <-receivedRequests; request.cookie != "session=secret" {
|
|
|
+ t.Errorf("Expected Cookie for %q to be %q, got %q", request.host, "session=secret", request.cookie)
|
|
|
+ }
|
|
|
+
|
|
|
+ if request := <-receivedRequests; request.host != "example.net" || request.cookie != "" {
|
|
|
+ t.Errorf("Expected no Cookie to be forwarded to example.net, got %q for %q", request.cookie, request.host)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestIsSameSite(t *testing.T) {
|
|
|
+ tests := []struct {
|
|
|
+ host string
|
|
|
+ siteHost string
|
|
|
+ expected bool
|
|
|
+ }{
|
|
|
+ {"example.org", "example.org", true},
|
|
|
+ {"www.example.org", "example.org", true},
|
|
|
+ {"example.org", "www.example.org", true},
|
|
|
+ {"www.example.org", "feeds.example.org", true},
|
|
|
+ {"WWW.Example.ORG", "feeds.example.org", true},
|
|
|
+ {"news.example.co.uk", "www.example.co.uk", true},
|
|
|
+ {"xn--bcher-kva.example", "www.bücher.example", true},
|
|
|
+ {"example.net", "example.org", false},
|
|
|
+ {"notexample.org", "example.org", false},
|
|
|
+ {"example.org.example.net", "example.org", false},
|
|
|
+ {"attacker.co.uk", "example.co.uk", false},
|
|
|
+ {"attacker.CO.UK", "www.example.CO.UK", false},
|
|
|
+ {"bob.github.io", "alice.github.io", false},
|
|
|
+ {"127.0.0.1", "127.0.0.1", true},
|
|
|
+ {"10.0.0.1", "192.168.0.1", false},
|
|
|
+ {"::1", "::1", true},
|
|
|
+ {"localhost", "localhost", true},
|
|
|
+ {"intranet", "localhost", false},
|
|
|
+ {"", "example.org", false},
|
|
|
+ {"example.org", "", false},
|
|
|
+ {"", "", false},
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, tt := range tests {
|
|
|
+ if got := isSameSite(tt.host, tt.siteHost); got != tt.expected {
|
|
|
+ t.Errorf("isSameSite(%q, %q) = %v, expected %v", tt.host, tt.siteHost, got, tt.expected)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func TestRequestBuilder_WithUsernameAndPassword(t *testing.T) {
|
|
|
tests := []struct {
|
|
|
name string
|
|
|
@@ -407,7 +546,7 @@ func TestRequestBuilder_ChainedMethods(t *testing.T) {
|
|
|
builder := NewRequestBuilder()
|
|
|
resp, err := builder.
|
|
|
WithUserAgent("TestAgent/1.0", "DefaultAgent/1.0").
|
|
|
- WithCookie("test=value").
|
|
|
+ WithCookie("test=value", server.URL).
|
|
|
WithETag("etag123").
|
|
|
WithTimeout(10 * time.Second).
|
|
|
ExecuteRequest(server.URL)
|