mirror of
https://github.com/TecharoHQ/anubis.git
synced 2026-04-17 05:44:57 +00:00
feat(checker): port other checkers over
Signed-off-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
32
lib/checker/headerexists/checker.go
Normal file
32
lib/checker/headerexists/checker.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package headerexists
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/TecharoHQ/anubis/internal"
|
||||
"github.com/TecharoHQ/anubis/lib/checker"
|
||||
)
|
||||
|
||||
func New(key string) checker.Interface {
|
||||
return headerExistsChecker{
|
||||
header: strings.TrimSpace(http.CanonicalHeaderKey(key)),
|
||||
hash: internal.FastHash(key),
|
||||
}
|
||||
}
|
||||
|
||||
type headerExistsChecker struct {
|
||||
header, hash string
|
||||
}
|
||||
|
||||
func (hec headerExistsChecker) Check(r *http.Request) (bool, error) {
|
||||
if r.Header.Get(hec.header) != "" {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (hec headerExistsChecker) Hash() string {
|
||||
return hec.hash
|
||||
}
|
||||
57
lib/checker/headerexists/checker_test.go
Normal file
57
lib/checker/headerexists/checker_test.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package headerexists
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestChecker(t *testing.T) {
|
||||
fac := Factory{}
|
||||
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
header string
|
||||
reqHeader string
|
||||
ok bool
|
||||
}{
|
||||
{
|
||||
name: "match",
|
||||
header: "Authorization",
|
||||
reqHeader: "Authorization",
|
||||
ok: true,
|
||||
},
|
||||
{
|
||||
name: "not_match",
|
||||
header: "Authorization",
|
||||
reqHeader: "Authentication",
|
||||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
hec, err := fac.Build(t.Context(), json.RawMessage(fmt.Sprintf("%q", tt.header)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Log(hec.Hash())
|
||||
|
||||
r, err := http.NewRequest(http.MethodGet, "/", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make request: %v", err)
|
||||
}
|
||||
|
||||
r.Header.Set(tt.reqHeader, "hunter2")
|
||||
|
||||
ok, err := hec.Check(r)
|
||||
|
||||
if tt.ok != ok {
|
||||
t.Errorf("ok: %v, wanted: %v", ok, tt.ok)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("err: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
40
lib/checker/headerexists/factory.go
Normal file
40
lib/checker/headerexists/factory.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package headerexists
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/TecharoHQ/anubis/lib/checker"
|
||||
)
|
||||
|
||||
type Factory struct{}
|
||||
|
||||
func (f Factory) Build(ctx context.Context, data json.RawMessage) (checker.Interface, error) {
|
||||
var headerName string
|
||||
|
||||
if err := json.Unmarshal([]byte(data), &headerName); err != nil {
|
||||
return nil, fmt.Errorf("%w: want string", checker.ErrUnparseableConfig)
|
||||
}
|
||||
|
||||
if err := f.Valid(ctx, data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return New(http.CanonicalHeaderKey(headerName)), nil
|
||||
}
|
||||
|
||||
func (Factory) Valid(ctx context.Context, data json.RawMessage) error {
|
||||
var headerName string
|
||||
|
||||
if err := json.Unmarshal([]byte(data), &headerName); err != nil {
|
||||
return fmt.Errorf("%w: want string", checker.ErrUnparseableConfig)
|
||||
}
|
||||
|
||||
if headerName == "" {
|
||||
return fmt.Errorf("%w: string must not be empty", checker.ErrInvalidConfig)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
60
lib/checker/headerexists/factory_test.go
Normal file
60
lib/checker/headerexists/factory_test.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package headerexists
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFactoryGood(t *testing.T) {
|
||||
files, err := os.ReadDir("./testdata/good")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fac := Factory{}
|
||||
|
||||
for _, fname := range files {
|
||||
t.Run(fname.Name(), func(t *testing.T) {
|
||||
data, err := os.ReadFile(filepath.Join("testdata", "good", fname.Name()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := fac.Valid(t.Context(), json.RawMessage(data)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFactoryBad(t *testing.T) {
|
||||
files, err := os.ReadDir("./testdata/bad")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fac := Factory{}
|
||||
|
||||
for _, fname := range files {
|
||||
t.Run(fname.Name(), func(t *testing.T) {
|
||||
data, err := os.ReadFile(filepath.Join("testdata", "bad", fname.Name()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Run("Build", func(t *testing.T) {
|
||||
if _, err := fac.Build(t.Context(), json.RawMessage(data)); err == nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
if err := fac.Valid(t.Context(), json.RawMessage(data)); err == nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
1
lib/checker/headerexists/testdata/bad/empty.json
vendored
Normal file
1
lib/checker/headerexists/testdata/bad/empty.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
""
|
||||
1
lib/checker/headerexists/testdata/bad/object.json
vendored
Normal file
1
lib/checker/headerexists/testdata/bad/object.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
1
lib/checker/headerexists/testdata/good/authorization.json
vendored
Normal file
1
lib/checker/headerexists/testdata/good/authorization.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"Authorization"
|
||||
Reference in New Issue
Block a user