-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(webconnectivityqa): reproduce ooni/probe#2628 issue (#1479)
This PR improves webconnectivityqa to reproduce the ooni/probe#2628 issue. We model the v0.4 behavior as the correct behavior. We need to extend webconnectivitylte to correctly handle this case.
- Loading branch information
1 parent
db5878c
commit 69a6c89
Showing
7 changed files
with
269 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package netemx | ||
|
||
import ( | ||
"net" | ||
"net/http" | ||
|
||
"github.com/ooni/netem" | ||
) | ||
|
||
// HTTPBinHandlerFactory constructs an [HTTPBinHandler]. | ||
func HTTPBinHandlerFactory() HTTPHandlerFactory { | ||
return HTTPHandlerFactoryFunc(func(env NetStackServerFactoryEnv, stack *netem.UNetStack) http.Handler { | ||
return HTTPBinHandler() | ||
}) | ||
} | ||
|
||
// HTTPBinHandler returns the [http.Handler] implementing an httpbin.com-like service. | ||
// | ||
// We currently implement the following API endpoints: | ||
// | ||
// /broken-redirect-http | ||
// When accessed by the OONI Probe client redirects with 302 to http:// and | ||
// otherwise redirects to the https://www.example.com/ URL. | ||
// | ||
// /broken-redirect-https | ||
// When accessed by the OONI Probe client redirects with 302 to https:// and | ||
// otherwise redirects to the https://www.example.com/ URL. | ||
// | ||
// Any other request URL causes a 404 respose. | ||
func HTTPBinHandler() http.Handler { | ||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
// missing address => 500 | ||
address, _, err := net.SplitHostPort(r.RemoteAddr) | ||
if err != nil { | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
// compute variables used by the switch below | ||
cleartextRedirect := r.URL.Path == "/broken-redirect-http" | ||
client := address == DefaultClientAddress | ||
secureRedirect := r.URL.Path == "/broken-redirect-https" | ||
|
||
switch { | ||
// broken HTTP redirect for clients | ||
case cleartextRedirect && client: | ||
w.Header().Set("Location", "http://") | ||
w.WriteHeader(http.StatusFound) | ||
|
||
// working HTTP redirect for anyone else | ||
case cleartextRedirect && !client: | ||
w.Header().Set("Location", "http://www.example.com/") | ||
w.WriteHeader(http.StatusFound) | ||
|
||
// broken HTTPS redirect for clients | ||
case secureRedirect && client: | ||
w.Header().Set("Location", "https://") | ||
w.WriteHeader(http.StatusFound) | ||
|
||
// working HTTPS redirect for anyone else | ||
case secureRedirect && !client: | ||
w.Header().Set("Location", "https://www.example.com/") | ||
w.WriteHeader(http.StatusFound) | ||
|
||
// otherwise | ||
default: | ||
w.WriteHeader(http.StatusNotFound) | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package netemx | ||
|
||
import ( | ||
"net" | ||
"net/http" | ||
"net/http/httptest" | ||
"net/url" | ||
"testing" | ||
) | ||
|
||
func TestHTTPBinHandler(t *testing.T) { | ||
t.Run("missing client address", func(t *testing.T) { | ||
req := &http.Request{ | ||
URL: &url.URL{Scheme: "http://", Path: "/"}, | ||
Body: http.NoBody, | ||
Close: false, | ||
Host: "httpbin.com", | ||
} | ||
rr := httptest.NewRecorder() | ||
handler := HTTPBinHandler() | ||
handler.ServeHTTP(rr, req) | ||
result := rr.Result() | ||
if result.StatusCode != http.StatusInternalServerError { | ||
t.Fatal("unexpected status code", result.StatusCode) | ||
} | ||
}) | ||
|
||
t.Run("/broken-redirect-http with client address", func(t *testing.T) { | ||
req := &http.Request{ | ||
URL: &url.URL{Scheme: "http://", Path: "/broken-redirect-http"}, | ||
Body: http.NoBody, | ||
Close: false, | ||
Host: "httpbin.com", | ||
RemoteAddr: net.JoinHostPort(DefaultClientAddress, "54321"), | ||
} | ||
rr := httptest.NewRecorder() | ||
handler := HTTPBinHandler() | ||
handler.ServeHTTP(rr, req) | ||
result := rr.Result() | ||
if result.StatusCode != http.StatusFound { | ||
t.Fatal("unexpected status code", result.StatusCode) | ||
} | ||
if loc := result.Header.Get("Location"); loc != "http://" { | ||
t.Fatal("unexpected location", loc) | ||
} | ||
}) | ||
|
||
t.Run("/broken-redirect-http with another address", func(t *testing.T) { | ||
req := &http.Request{ | ||
URL: &url.URL{Scheme: "http://", Path: "/broken-redirect-http"}, | ||
Body: http.NoBody, | ||
Close: false, | ||
Host: "httpbin.com", | ||
RemoteAddr: net.JoinHostPort("8.8.8.8", "54321"), | ||
} | ||
rr := httptest.NewRecorder() | ||
handler := HTTPBinHandler() | ||
handler.ServeHTTP(rr, req) | ||
result := rr.Result() | ||
if result.StatusCode != http.StatusFound { | ||
t.Fatal("unexpected status code", result.StatusCode) | ||
} | ||
if loc := result.Header.Get("Location"); loc != "http://www.example.com/" { | ||
t.Fatal("unexpected location", loc) | ||
} | ||
}) | ||
|
||
t.Run("/broken-redirect-https with client address", func(t *testing.T) { | ||
req := &http.Request{ | ||
URL: &url.URL{Scheme: "http://", Path: "/broken-redirect-https"}, | ||
Body: http.NoBody, | ||
Close: false, | ||
Host: "httpbin.com", | ||
RemoteAddr: net.JoinHostPort(DefaultClientAddress, "54321"), | ||
} | ||
rr := httptest.NewRecorder() | ||
handler := HTTPBinHandler() | ||
handler.ServeHTTP(rr, req) | ||
result := rr.Result() | ||
if result.StatusCode != http.StatusFound { | ||
t.Fatal("unexpected status code", result.StatusCode) | ||
} | ||
if loc := result.Header.Get("Location"); loc != "https://" { | ||
t.Fatal("unexpected location", loc) | ||
} | ||
}) | ||
|
||
t.Run("/broken-redirect-https with another address", func(t *testing.T) { | ||
req := &http.Request{ | ||
URL: &url.URL{Scheme: "http://", Path: "/broken-redirect-https"}, | ||
Body: http.NoBody, | ||
Close: false, | ||
Host: "httpbin.com", | ||
RemoteAddr: net.JoinHostPort("8.8.8.8", "54321"), | ||
} | ||
rr := httptest.NewRecorder() | ||
handler := HTTPBinHandler() | ||
handler.ServeHTTP(rr, req) | ||
result := rr.Result() | ||
if result.StatusCode != http.StatusFound { | ||
t.Fatal("unexpected status code", result.StatusCode) | ||
} | ||
if loc := result.Header.Get("Location"); loc != "https://www.example.com/" { | ||
t.Fatal("unexpected location", loc) | ||
} | ||
}) | ||
|
||
t.Run("/nonexistent URL", func(t *testing.T) { | ||
req := &http.Request{ | ||
URL: &url.URL{Scheme: "https://", Path: "/nonexistent"}, | ||
Body: http.NoBody, | ||
Close: false, | ||
Host: "httpbin.com", | ||
RemoteAddr: net.JoinHostPort("8.8.8.8", "54321"), | ||
} | ||
rr := httptest.NewRecorder() | ||
handler := HTTPBinHandler() | ||
handler.ServeHTTP(rr, req) | ||
result := rr.Result() | ||
if result.StatusCode != http.StatusNotFound { | ||
t.Fatal("unexpected status code", result.StatusCode) | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters