Skip to content

Commit

Permalink
feat(netemx): implement subset of the OONI API (ooni#1203)
Browse files Browse the repository at this point in the history
This diff implements the subset of the OONI API required for testing Web
Connectivity LTE using netemx.

Diff adapted from: ooni#1185.

Reference issue: ooni/probe#2461.

---------

Co-authored-by: kelmenhorst <k.elmenhorst@mailbox.org>
  • Loading branch information
2 people authored and Murphy-OrangeMud committed Feb 13, 2024
1 parent e41ba5c commit 7612267
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 0 deletions.
50 changes: 50 additions & 0 deletions internal/netemx/ooapi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package netemx

import (
"encoding/json"
"net/http"

"github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/runtimex"
)

// OOAPIHandler is an [http.Handler] implementing the OONI API.
type OOAPIHandler struct{}

var _ http.Handler = &OOAPIHandler{}

// ServeHTTP implements [http.Handler].
func (p *OOAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch {
case r.URL.Path == "/api/v1/test-helpers" && r.Method == http.MethodGet:
p.getApiV1TestHelpers(w, r)

default:
w.WriteHeader(http.StatusNotFound)
}
}

func (p *OOAPIHandler) getApiV1TestHelpers(w http.ResponseWriter, r *http.Request) {
resp := map[string][]model.OOAPIService{
"web-connectivity": {
{
Address: "https://2.th.ooni.org",
Type: "https",
},
{
Address: "https://3.th.ooni.org",
Type: "https",
},
{
Address: "https://0.th.ooni.org",
Type: "https",
},
{
Address: "https://1.th.ooni.org",
Type: "https",
},
},
}
w.Header().Add("Content-Type", "application/json")
w.Write(runtimex.Try1(json.Marshal(resp)))
}
55 changes: 55 additions & 0 deletions internal/netemx/ooapi_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package netemx

import (
"io"
"net/http"
"net/http/httptest"
"net/url"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/ooni/probe-cli/v3/internal/runtimex"
)

func TestOOAPIHandler(t *testing.T) {
handler := &OOAPIHandler{}
server := httptest.NewServer(handler)
defer server.Close()

t.Run("for /api/v1/test-helpers with method GET", func(t *testing.T) {
URL := runtimex.Try1(url.Parse(server.URL))
URL.Path = "/api/v1/test-helpers"
resp, err := http.Get(URL.String())
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Fatal("unexpected status code", resp.StatusCode)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}

expectedBody := `{"web-connectivity":[{"address":"https://2.th.ooni.org","type":"https"},{"address":"https://3.th.ooni.org","type":"https"},{"address":"https://0.th.ooni.org","type":"https"},{"address":"https://1.th.ooni.org","type":"https"}]}`

t.Log(string(body))
if diff := cmp.Diff([]byte(expectedBody), body); diff != "" {
t.Fatal(diff)
}
})

t.Run("for unsupported URL path", func(t *testing.T) {
URL := runtimex.Try1(url.Parse(server.URL))
URL.Path = "/antani"
resp, err := http.Get(URL.String())
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusNotFound {
t.Fatal("unexpected status code", resp.StatusCode)
}
})
}
6 changes: 6 additions & 0 deletions script/nocopyreadall.bash
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
set -euo pipefail
exitcode=0
for file in $(find . -type f -name \*.go); do
if [ "$file" = "./internal/netemx/ooapi_test.go" ]; then
# We're allowed to use ReadAll and Copy in this file because
# it's code that we only use for testing purposes.
continue
fi

if [ "$file" = "./internal/netxlite/iox.go" ]; then
# We're allowed to use ReadAll and Copy in this file to
# implement safer wrappers for these functions.
Expand Down

0 comments on commit 7612267

Please sign in to comment.