aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--human.go19
-rw-r--r--human_test.go46
2 files changed, 61 insertions, 4 deletions
diff --git a/human.go b/human.go
index d78d31f..e2ac134 100644
--- a/human.go
+++ b/human.go
@@ -23,6 +23,25 @@ var (
// URL represents a standard [url.URL] following normalization rules of human.json.
type URL url.URL
+func NewURL(s string) (*URL, error) {
+ raw, err := url.Parse(s)
+ if err != nil {
+ return nil, err
+ }
+ u := URL(*raw)
+ return &u, nil
+}
+
+// Match returns true if url is within the scope.
+// See https://codeberg.org/robida/human.json#url-matching.
+func (u *URL) Match(url *URL) bool {
+ u.normalize()
+ url.normalize()
+ return u.Scheme == url.Scheme &&
+ u.Host == url.Host &&
+ (u.Path == url.Path || strings.HasPrefix(url.Path, u.Path+"/"))
+}
+
func (u *URL) normalize() {
if strings.Contains(u.Host, ":") {
sp := strings.Split(u.Host, ":")
diff --git a/human_test.go b/human_test.go
index 5109af4..cb0b86c 100644
--- a/human_test.go
+++ b/human_test.go
@@ -3,7 +3,6 @@ package human_test
import (
"encoding/json"
"fmt"
- "net/url"
"testing"
"time"
@@ -69,6 +68,46 @@ func TestURL_Json(t *testing.T) {
}
}
+func genericMatch(base *human.URL, test string) bool {
+ u, _ := human.NewURL(test)
+ return base.Match(u)
+}
+
+func TestURL_Match(t *testing.T) {
+ base, _ := human.NewURL(`https://example.org/~alice`)
+
+ if !genericMatch(base, `https://example.org/~alice`) {
+ t.Errorf("same must match")
+ }
+ if !genericMatch(base, `https://example.org/~alice/blog`) {
+ t.Errorf("sub must match")
+ }
+ if !genericMatch(base, `https://example.org/~alice/blog/my-post`) {
+ t.Errorf("any depth sub must match")
+ }
+
+ if genericMatch(base, `https://example.org/~bob`) {
+ t.Errorf("different path mustn't match")
+ }
+ if genericMatch(base, `https://example.org/`) {
+ t.Errorf("home musn't match")
+ }
+ if genericMatch(base, `https://example.org/~alice-two`) {
+ t.Errorf("different path musn't match")
+ }
+
+ if genericMatch(base, `https://foo.example.org/~alice`) {
+ t.Errorf("different host musn't match")
+ }
+ if genericMatch(base, `http://example.org/~alice`) {
+ t.Errorf("different scheme musn't match")
+ }
+
+ if !genericMatch(base, `https://example.org:443/~alice`) {
+ t.Errorf("std port must match")
+ }
+}
+
func TestVouch_Json(t *testing.T) {
var v human.Vouch
err := json.Unmarshal([]byte(`{"url": "https://bob.example.com","vouched_at": "2026-01-15"}`), &v)
@@ -82,11 +121,10 @@ func TestVouch_Json(t *testing.T) {
t.Errorf("invalid vouched_at: %v", v.VouchedAt)
}
- raw, _ := url.Parse(`https://bob.example.com:443/`)
+ u, _ := human.NewURL(`https://bob.example.com:443/`)
now := time.Now()
- cv := human.URL(*raw)
v = human.Vouch{
- URL: &cv,
+ URL: u,
VouchedAt: now,
}
b, err := json.Marshal(&v)