2023-09-20 15:13:10 -03:00
|
|
|
package handler_test
|
2023-09-20 01:26:38 -03:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"encoding/json"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"reflect"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
2023-09-20 15:13:10 -03:00
|
|
|
"git.maronato.dev/maronato/finger/handler"
|
2023-09-20 01:26:38 -03:00
|
|
|
"git.maronato.dev/maronato/finger/internal/config"
|
|
|
|
"git.maronato.dev/maronato/finger/internal/log"
|
2023-09-20 15:13:10 -03:00
|
|
|
"git.maronato.dev/maronato/finger/webfingers"
|
2023-09-20 01:26:38 -03:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestWebfingerHandler(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2023-09-20 15:13:10 -03:00
|
|
|
fingers := webfingers.WebFingers{
|
2023-09-20 01:26:38 -03:00
|
|
|
"acct:user@example.com": {
|
|
|
|
Subject: "acct:user@example.com",
|
2023-09-20 15:13:10 -03:00
|
|
|
Links: []webfingers.Link{
|
2023-09-20 01:26:38 -03:00
|
|
|
{
|
|
|
|
Rel: "http://webfinger.net/rel/profile-page",
|
|
|
|
Href: "https://example.com/user",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Properties: map[string]string{
|
|
|
|
"http://webfinger.net/rel/name": "John Doe",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"acct:other@example.com": {
|
|
|
|
Subject: "acct:other@example.com",
|
|
|
|
Properties: map[string]string{
|
|
|
|
"http://webfinger.net/rel/name": "Jane Doe",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"https://example.com/user": {
|
|
|
|
Subject: "https://example.com/user",
|
|
|
|
Properties: map[string]string{
|
|
|
|
"http://webfinger.net/rel/name": "John Baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
resource string
|
|
|
|
wantCode int
|
|
|
|
alternateMethod string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "valid resource",
|
|
|
|
resource: "acct:user@example.com",
|
|
|
|
wantCode: http.StatusOK,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "other valid resource",
|
|
|
|
resource: "acct:other@example.com",
|
|
|
|
wantCode: http.StatusOK,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "url resource",
|
|
|
|
resource: "https://example.com/user",
|
|
|
|
wantCode: http.StatusOK,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "resource missing acct:",
|
|
|
|
resource: "user@example.com",
|
|
|
|
wantCode: http.StatusNotFound,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "resource missing",
|
|
|
|
resource: "",
|
|
|
|
wantCode: http.StatusBadRequest,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "invalid method",
|
|
|
|
resource: "acct:user@example.com",
|
|
|
|
wantCode: http.StatusMethodNotAllowed,
|
|
|
|
alternateMethod: http.MethodPost,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
tc := tt
|
|
|
|
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
cfg := config.NewConfig()
|
|
|
|
l := log.NewLogger(&strings.Builder{}, cfg)
|
|
|
|
|
|
|
|
ctx = log.WithLogger(ctx, l)
|
|
|
|
|
|
|
|
// Create a new request
|
|
|
|
r, _ := http.NewRequestWithContext(ctx, tc.alternateMethod, "/.well-known/webfinger?resource="+tc.resource, http.NoBody)
|
|
|
|
|
|
|
|
// Create a new response
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
|
|
|
// Create a new handler
|
2023-09-20 15:13:10 -03:00
|
|
|
h := handler.WebfingerHandler(fingers)
|
2023-09-20 01:26:38 -03:00
|
|
|
|
|
|
|
// Serve the request
|
|
|
|
h.ServeHTTP(w, r)
|
|
|
|
|
|
|
|
// Check the status code
|
|
|
|
if w.Code != tc.wantCode {
|
|
|
|
t.Errorf("expected status code %d, got %d", tc.wantCode, w.Code)
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the status code is 200, check the response body
|
|
|
|
if tc.wantCode == http.StatusOK {
|
|
|
|
// Check the content type
|
|
|
|
if w.Header().Get("Content-Type") != "application/jrd+json" {
|
|
|
|
t.Errorf("expected content type %s, got %s", "application/jrd+json", w.Header().Get("Content-Type"))
|
|
|
|
}
|
|
|
|
|
2023-09-20 15:13:10 -03:00
|
|
|
fingerWant := fingers[tc.resource]
|
|
|
|
fingerGot := &webfingers.WebFinger{}
|
2023-09-20 01:26:38 -03:00
|
|
|
|
|
|
|
// Decode the response body
|
|
|
|
if err := json.NewDecoder(w.Body).Decode(fingerGot); err != nil {
|
|
|
|
t.Errorf("error decoding json: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort links
|
|
|
|
|
|
|
|
sort.Slice(fingerGot.Links, func(i, j int) bool {
|
|
|
|
return fingerGot.Links[i].Rel < fingerGot.Links[j].Rel
|
|
|
|
})
|
|
|
|
|
|
|
|
sort.Slice(fingerWant.Links, func(i, j int) bool {
|
|
|
|
return fingerWant.Links[i].Rel < fingerWant.Links[j].Rel
|
|
|
|
})
|
|
|
|
|
|
|
|
// Check the response body
|
|
|
|
if !reflect.DeepEqual(fingerGot, fingerWant) {
|
|
|
|
t.Errorf("expected body %v, got %v", fingerWant, fingerGot)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2023-09-20 15:13:10 -03:00
|
|
|
|
|
|
|
func BenchmarkWebfingerHandler(b *testing.B) {
|
|
|
|
fingers, err := webfingers.NewWebFingers(
|
|
|
|
webfingers.Resources{
|
|
|
|
"user@example.com": {
|
|
|
|
"prop1": "value1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
h := handler.WebfingerHandler(fingers)
|
|
|
|
r := httptest.NewRequest(http.MethodGet, "/.well-known/webfinger?resource=acct:user@example.com", http.NoBody)
|
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
|
|
|
h.ServeHTTP(w, r)
|
|
|
|
|
|
|
|
if w.Code != http.StatusOK {
|
|
|
|
b.Errorf("expected status code %d, got %d", http.StatusOK, w.Code)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|