Skip to content

Commit 2c19194

Browse files
authored
fix: Extract domain from hostname for domain check (#15)
1 parent 2ebd7f0 commit 2c19194

File tree

7 files changed

+62
-37
lines changed

7 files changed

+62
-37
lines changed

README.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,19 @@ a handle.
2121

2222
## Configuration
2323

24-
| Environment Variable | Description | Example |
25-
| -------------------------- | -------------------------------------------------- | -------------------------------------- |
26-
| **`DID_PROVIDER`** | **Required** Name of a supported provider | `postgres` `memory` |
27-
| `REDIRECT_DID_TEMPLATE` | URL template for redirects when a DID is found | `https://bsky.app/profile/{did}` |
28-
| `REDIRECT_HANDLE_TEMPLATE` | URL template for redirects when a DID is not found | `https://example.com/?handle={handle}` |
24+
| Environment Variable | Description | Example |
25+
| -------------------------- | ---------------------------------------------------------- | -------------------------------------- |
26+
| **`DID_PROVIDER`** | **Required** Name of a supported provider | `postgres` `memory` |
27+
| `REDIRECT_DID_TEMPLATE` | URL template for redirects when a DID is found | `https://bsky.app/profile/{did}` |
28+
| `REDIRECT_HANDLE_TEMPLATE` | URL template for redirects when a DID is not found | `https://example.com/?handle={handle}` |
29+
| `CHECK_DOMAIN_PARAMETER` | Query parameter used by check domain endpoint (`/domainz`) | `handle` `hostname` `domain` |
2930

3031
### `memory` provider
3132

32-
| Environment Variable | Description | Example |
33-
| -------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------- |
34-
| **`MEMORY_DIDS`** | **Required** Comma separated list of handle@did pairs | `alice.example.com@did:plc:example001,bob.example.com@did:plc:example002` |
35-
| **`MEMORY_DOMAINS`** | **Required** Comma separate list of supported domains | `example.com,example.net` |
33+
| Environment Variable | Description | Example |
34+
| -------------------- | ----------------------------------------------------- | ------------------------------- |
35+
| **`MEMORY_DIDS`** | **Required** Comma separated list of handle@did pairs | `alice.example.com@did:plc:001` |
36+
| **`MEMORY_DOMAINS`** | **Required** Comma separate list of supported domains | `example.com,example.net` |
3637

3738
### `postgres` provider
3839

config.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,20 @@ package main
33
import (
44
"errors"
55
"log/slog"
6+
"os"
67
"reflect"
78

89
"github.com/caarlos0/env/v11"
910
"github.com/jackc/pgx/v5/pgxpool"
11+
"github.com/jackc/pgx/v5/tracelog"
12+
pgxslog "github.com/mcosta74/pgx-slog"
1013
)
1114

1215
type Config struct {
13-
Host string `env:"HOST" envDefault:"localhost"`
14-
Port string `env:"PORT" envDefault:"80"`
15-
LogLevel slog.Level `env:"LOG_LEVEL" envDefault:"error"`
16+
Host string `env:"HOST" envDefault:"localhost"`
17+
Port string `env:"PORT" envDefault:"80"`
18+
19+
Logger *slog.Logger `env:"LOG_LEVEL" envDefault:"error"`
1620

1721
RedirectDIDTemplate URLTemplate `env:"REDIRECT_DID_TEMPLATE" envDefault:"https://bsky.app/profile/{did}"`
1822
RedirectHandleTemplate URLTemplate `env:"REDIRECT_HANDLE_TEMPLATE" envDefault:"https://{handle.domain}?handle={handle}"`
@@ -25,20 +29,37 @@ type Config struct {
2529
MemoryDomains []string `env:"MEMORY_DOMAINS"`
2630

2731
Provider ProvidesDecentralizedIDs `env:"DID_PROVIDER,required"`
32+
33+
CheckDomainParameter string `env:"CHECK_DOMAIN_PARAMETER" envDefault:"handle"`
2834
}
2935

3036
func ConfigFromEnvironment() (Config, error) {
3137
config := Config{}
3238

3339
err := env.ParseWithOptions(&config, env.Options{
3440
FuncMap: map[reflect.Type]env.ParserFunc{
35-
reflect.TypeFor[slog.Level](): func(v string) (interface{}, error) {
41+
reflect.TypeFor[slog.Logger](): func(v string) (interface{}, error) {
3642
var level slog.Level
37-
return level, level.UnmarshalText([]byte(v))
43+
44+
err := level.UnmarshalText([]byte(v))
45+
46+
if err != nil {
47+
return nil, err
48+
}
49+
50+
return *slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
51+
Level: level,
52+
})), nil
3853
},
3954
reflect.TypeFor[pgxpool.Config](): func(v string) (interface{}, error) {
40-
config, err := pgxpool.ParseConfig(v)
41-
return *config, err
55+
databaseConfig, err := pgxpool.ParseConfig(v)
56+
57+
databaseConfig.ConnConfig.Tracer = &tracelog.TraceLog{
58+
Logger: pgxslog.NewLogger(config.Logger),
59+
LogLevel: tracelog.LogLevelDebug,
60+
}
61+
62+
return *databaseConfig, err
4263
},
4364
reflect.TypeFor[ProvidesDecentralizedIDs](): func(v string) (interface{}, error) {
4465
switch v {

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require (
66
github.com/caarlos0/env/v11 v11.3.1
77
github.com/gin-gonic/gin v1.10.0
88
github.com/jackc/pgx/v5 v5.7.2
9+
github.com/mcosta74/pgx-slog v0.4.1
910
github.com/samber/slog-gin v1.14.1
1011
github.com/stretchr/testify v1.10.0
1112
)

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
5454
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
5555
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
5656
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
57+
github.com/mcosta74/pgx-slog v0.4.1 h1:Rt25l/jE5tu1ioqPDrqY17Kv6REdsM0L9WCT+hFw1rw=
58+
github.com/mcosta74/pgx-slog v0.4.1/go.mod h1:BCpubkiENkWQ8MvZ4a9LJgWuBzC5UpWoJmQ1/SOlv+M=
5759
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
5860
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
5961
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=

main.go

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ package main
22

33
import (
44
"log"
5-
"log/slog"
65
"net"
7-
"os"
86

97
"github.com/gin-gonic/gin"
108
sloggin "github.com/samber/slog-gin"
@@ -17,25 +15,21 @@ func main() {
1715
log.Fatal(err)
1816
}
1917

20-
var logger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
21-
Level: config.LogLevel,
22-
}))
23-
2418
router := gin.New()
2519

26-
AddApplicationRoutes(router, logger, config)
20+
AddApplicationRoutes(router, config)
2721

2822
if err := router.Run(net.JoinHostPort(config.Host, config.Port)); err != nil {
2923
log.Fatal(err)
3024
}
3125
}
3226

33-
func AddApplicationRoutes(router *gin.Engine, logger *slog.Logger, config Config) {
34-
router.Use(sloggin.New(logger))
27+
func AddApplicationRoutes(router *gin.Engine, config Config) {
28+
router.Use(sloggin.New(config.Logger))
3529
router.Use(gin.Recovery())
3630

3731
router.GET("/healthz", CheckServerIsHealthy(config.Provider))
38-
router.GET("/domainz", CheckServerProvidesForDomain(config.Provider))
32+
router.GET("/domainz", CheckServerProvidesForDomain(config.Provider, config.CheckDomainParameter))
3933

4034
router.Use(ParseHandleFromHostname)
4135
router.Use(WithHandleResult(config.Provider))

main_test.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ func NewTestEnvironment() (*gin.Engine, *InMemoryProvider) {
2828
Provider: testProvider,
2929
RedirectDIDTemplate: "https://example.com/profile/{did}",
3030
RedirectHandleTemplate: "https://example.com/register?handle={handle}",
31+
Logger: slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
32+
Level: slog.LevelWarn,
33+
})),
34+
CheckDomainParameter: "domain",
3135
}
3236

3337
var testRouter = gin.New()
34-
var testLogger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
35-
Level: slog.LevelWarn,
36-
}))
3738

38-
AddApplicationRoutes(testRouter, testLogger, testConfig)
39+
AddApplicationRoutes(testRouter, testConfig)
3940

4041
return testRouter, testProvider
4142
}
@@ -68,7 +69,7 @@ func TestDomainEndpointReturnsOKForProvidedDomain(t *testing.T) {
6869
router, _ := NewTestEnvironment()
6970

7071
res := httptest.NewRecorder()
71-
req, _ := http.NewRequest("GET", "/domainz?domain=example.com", nil)
72+
req, _ := http.NewRequest("GET", "/domainz?domain=alice.example.com", nil)
7273
router.ServeHTTP(res, req)
7374

7475
assert.Equal(t, http.StatusOK, res.Code)
@@ -78,7 +79,7 @@ func TestDomainEndpointReturnsErrorForUnprovidedDomain(t *testing.T) {
7879
router, _ := NewTestEnvironment()
7980

8081
res := httptest.NewRecorder()
81-
req, _ := http.NewRequest("GET", "/domainz?domain=unprovided.test", nil)
82+
req, _ := http.NewRequest("GET", "/domainz?domain=alice.unprovided.test", nil)
8283
router.ServeHTTP(res, req)
8384

8485
assert.Equal(t, http.StatusNotFound, res.Code)

router.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,28 @@ func ParseHandleFromHostname(c *gin.Context) {
3737
c.Next()
3838
}
3939

40-
func CheckServerProvidesForDomain(provider ProvidesDecentralizedIDs) gin.HandlerFunc {
40+
func CheckServerProvidesForDomain(provider ProvidesDecentralizedIDs, handleParameter string) gin.HandlerFunc {
4141
return func(c *gin.Context) {
42-
domain := Domain(strings.ToLower(c.Query("domain")))
42+
handle, err := HostnameToHandle(strings.ToLower(c.Query(handleParameter)))
4343

44-
canProvide, err := provider.CanProvideForDomain(c, domain)
44+
if err != nil {
45+
_ = c.AbortWithError(http.StatusBadRequest, err)
46+
return
47+
}
48+
49+
canProvide, err := provider.CanProvideForDomain(c, handle.Domain)
4550

4651
if err != nil {
4752
_ = c.AbortWithError(http.StatusInternalServerError, err)
4853
return
4954
}
5055

5156
if !canProvide {
52-
c.String(http.StatusNotFound, "Decentralized IDs are not provided for %s by this server.", domain)
57+
c.String(http.StatusNotFound, "Decentralized IDs are not provided for %s by this server.", handle.Domain)
5358
return
5459
}
5560

56-
c.String(http.StatusOK, "Decentralized IDs are not provided for %s by this server.", domain)
61+
c.String(http.StatusOK, "Decentralized IDs are provided for %s by this server.", handle.Domain)
5762
}
5863
}
5964

0 commit comments

Comments
 (0)