Compare commits
No commits in common. "main" and "feat/routing" have entirely different histories.
main
...
feat/routi
14
go.mod
14
go.mod
@ -9,17 +9,17 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/dgraph-io/ristretto/v2 v2.3.0 // indirect
|
github.com/dgraph-io/ristretto/v2 v2.2.0 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/go-logr/logr v1.4.3 // indirect
|
github.com/go-logr/logr v1.4.3 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/google/flatbuffers v25.2.10+incompatible // indirect
|
github.com/google/flatbuffers v25.2.10+incompatible // indirect
|
||||||
github.com/klauspost/compress v1.18.0 // indirect
|
github.com/klauspost/compress v1.18.0 // indirect
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
go.opentelemetry.io/otel v1.37.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
go.opentelemetry.io/otel/metric v1.37.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||||
golang.org/x/net v0.43.0 // indirect
|
golang.org/x/net v0.41.0 // indirect
|
||||||
golang.org/x/sys v0.35.0 // indirect
|
golang.org/x/sys v0.34.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.8 // indirect
|
google.golang.org/protobuf v1.36.6 // indirect
|
||||||
)
|
)
|
||||||
|
15
go.sum
15
go.sum
@ -6,8 +6,6 @@ github.com/dgraph-io/badger/v4 v4.8.0 h1:JYph1ChBijCw8SLeybvPINizbDKWZ5n/GYbz2yh
|
|||||||
github.com/dgraph-io/badger/v4 v4.8.0/go.mod h1:U6on6e8k/RTbUWxqKR0MvugJuVmkxSNc79ap4917h4w=
|
github.com/dgraph-io/badger/v4 v4.8.0/go.mod h1:U6on6e8k/RTbUWxqKR0MvugJuVmkxSNc79ap4917h4w=
|
||||||
github.com/dgraph-io/ristretto/v2 v2.2.0 h1:bkY3XzJcXoMuELV8F+vS8kzNgicwQFAaGINAEJdWGOM=
|
github.com/dgraph-io/ristretto/v2 v2.2.0 h1:bkY3XzJcXoMuELV8F+vS8kzNgicwQFAaGINAEJdWGOM=
|
||||||
github.com/dgraph-io/ristretto/v2 v2.2.0/go.mod h1:RZrm63UmcBAaYWC1DotLYBmTvgkrs0+XhBd7Npn7/zI=
|
github.com/dgraph-io/ristretto/v2 v2.2.0/go.mod h1:RZrm63UmcBAaYWC1DotLYBmTvgkrs0+XhBd7Npn7/zI=
|
||||||
github.com/dgraph-io/ristretto/v2 v2.3.0 h1:qTQ38m7oIyd4GAed/QkUZyPFNMnvVWyazGXRwvOt5zk=
|
|
||||||
github.com/dgraph-io/ristretto/v2 v2.3.0/go.mod h1:gpoRV3VzrEY1a9dWAYV6T1U7YzfgttXdd/ZzL1s9OZM=
|
|
||||||
github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38=
|
github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38=
|
||||||
github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
@ -29,32 +27,19 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
|
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
|
||||||
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
|
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
|
||||||
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
|
||||||
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
|
||||||
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
|
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
|
||||||
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
|
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
|
||||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
|
||||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
|
||||||
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
|
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
|
||||||
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
||||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
|
||||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
|
||||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
|
||||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
|
||||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
|
||||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
|
||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||||
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
|
|
||||||
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
package routing
|
package joist
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HandlerFn func(w http.ResponseWriter, r *http.Request) error
|
type (
|
||||||
|
HandlerFn func(w http.ResponseWriter, r *http.Request) error
|
||||||
type Middlewares []func(http.ResponseWriter, *http.Request)
|
MiddlewareFn func(HandlerFn) HandlerFn
|
||||||
|
)
|
||||||
|
|
||||||
func (h HandlerFn) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (h HandlerFn) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
if err := h(w, r); err != nil {
|
if err := h(w, r); err != nil {
|
@ -1,4 +1,4 @@
|
|||||||
package storage
|
package joist
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -12,3 +12,11 @@ type Storer interface {
|
|||||||
GetForPrefix(ctx context.Context, prefix string) (map[string][]byte, error)
|
GetForPrefix(ctx context.Context, prefix string) (map[string][]byte, error)
|
||||||
Put(ctx context.Context, key string, val []byte, ttl time.Duration) error
|
Put(ctx context.Context, key string, val []byte, ttl time.Duration) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RouteCacher interface {
|
||||||
|
Add(name string, path string) error
|
||||||
|
AddRouteInfo(routeInfo RouteInfo) error
|
||||||
|
GetPath(name string) (string, error)
|
||||||
|
GetRouteInfo(name string) (RouteInfo, error)
|
||||||
|
All() (map[string]string, error)
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package storage
|
package badger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
@ -1,4 +1,4 @@
|
|||||||
package storage
|
package badger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
@ -1,26 +0,0 @@
|
|||||||
package routing
|
|
||||||
|
|
||||||
type RouteInfo struct {
|
|
||||||
Method string
|
|
||||||
Name string
|
|
||||||
Path string
|
|
||||||
Description string
|
|
||||||
Title string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRouteInfo(method, path, description, title string) (*RouteInfo, error) {
|
|
||||||
name, err := convertRouteToRouteName(path)
|
|
||||||
if err != nil {
|
|
||||||
return &RouteInfo{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &RouteInfo{
|
|
||||||
Method: method,
|
|
||||||
Name: name,
|
|
||||||
Path: path,
|
|
||||||
Description: description,
|
|
||||||
Title: title,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type routeInfoKey struct{}
|
|
@ -1,20 +0,0 @@
|
|||||||
package routing
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.markbailey.dev/cerbervs/joist/internal/errors"
|
|
||||||
chi "github.com/go-chi/chi/v5"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewRouter() *Router {
|
|
||||||
ttl := 8 * time.Hour
|
|
||||||
|
|
||||||
cache, err := NewRouteCacheService(WithTTL(ttl))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(errors.Wrap(err, errors.ErrRouterNotCreated))
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Router{Mux: chi.NewRouter(), cache: cache, cacheTTL: ttl}
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package routing
|
package joist
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -7,37 +7,37 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.markbailey.dev/cerbervs/joist/internal/badger"
|
||||||
jerr "git.markbailey.dev/cerbervs/joist/internal/errors"
|
jerr "git.markbailey.dev/cerbervs/joist/internal/errors"
|
||||||
"git.markbailey.dev/cerbervs/joist/internal/storage"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type RouteCache struct {
|
type routeCache struct {
|
||||||
rs map[string]string
|
rs map[string]string
|
||||||
ris map[string]*RouteInfo
|
ris map[string]*RouteInfo
|
||||||
s storage.Storer
|
s Storer
|
||||||
ttl time.Duration
|
ttl time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
type RouteCacheOpt func(*RouteCache)
|
type RouteCacheOpt func(*routeCache)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
rcOnce sync.Once
|
rcOnce sync.Once
|
||||||
cache *RouteCache
|
cache *routeCache
|
||||||
)
|
)
|
||||||
|
|
||||||
func WithTTL(ttl time.Duration) RouteCacheOpt {
|
func WithTTL(ttl time.Duration) RouteCacheOpt {
|
||||||
return func(r *RouteCache) {
|
return func(r *routeCache) {
|
||||||
r.ttl = ttl
|
r.ttl = ttl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithStore(store storage.Storer) RouteCacheOpt {
|
func WithStore(store Storer) RouteCacheOpt {
|
||||||
return func(r *RouteCache) {
|
return func(r *routeCache) {
|
||||||
r.s = store
|
r.s = store
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRouteCacheService(opts ...RouteCacheOpt) (*RouteCache, error) {
|
func NewRouteCacheService(opts ...RouteCacheOpt) (*routeCache, error) {
|
||||||
rcOnce.Do(func() {
|
rcOnce.Do(func() {
|
||||||
c, err := newRouteCache(opts...)
|
c, err := newRouteCache(opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -54,14 +54,14 @@ func NewRouteCacheService(opts ...RouteCacheOpt) (*RouteCache, error) {
|
|||||||
return cache, nil
|
return cache, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RouteCache) All() (map[string]string, error) {
|
func (r *routeCache) All() (map[string]string, error) {
|
||||||
if r.rs == nil {
|
if r.rs == nil {
|
||||||
return nil, jerr.ErrCacheUninitialized
|
return nil, jerr.ErrCacheUninitialized
|
||||||
}
|
}
|
||||||
return r.rs, nil
|
return r.rs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RouteCache) Add(name string, path string) error {
|
func (r *routeCache) Add(name string, path string) error {
|
||||||
ttl := r.ttl
|
ttl := r.ttl
|
||||||
if ttl == 0 {
|
if ttl == 0 {
|
||||||
ttl = 1 * time.Hour
|
ttl = 1 * time.Hour
|
||||||
@ -76,7 +76,7 @@ func (r *RouteCache) Add(name string, path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RouteCache) GetPath(name string) (string, error) {
|
func (r *routeCache) GetPath(name string) (string, error) {
|
||||||
if path, ok := r.rs[name]; ok {
|
if path, ok := r.rs[name]; ok {
|
||||||
return path, nil
|
return path, nil
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ func (r *RouteCache) GetPath(name string) (string, error) {
|
|||||||
return "", errors.New("route not found in cache")
|
return "", errors.New("route not found in cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RouteCache) AddRouteInfo(routeInfo RouteInfo) error {
|
func (r *routeCache) AddRouteInfo(routeInfo RouteInfo) error {
|
||||||
ttl := r.ttl
|
ttl := r.ttl
|
||||||
if ttl == 0 {
|
if ttl == 0 {
|
||||||
ttl = 1 * time.Hour
|
ttl = 1 * time.Hour
|
||||||
@ -113,7 +113,7 @@ func (r *RouteCache) AddRouteInfo(routeInfo RouteInfo) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RouteCache) GetRouteInfo(name string) (RouteInfo, error) {
|
func (r *routeCache) GetRouteInfo(name string) (RouteInfo, error) {
|
||||||
if ri, ok := r.ris[name]; ok {
|
if ri, ok := r.ris[name]; ok {
|
||||||
return *ri, nil
|
return *ri, nil
|
||||||
}
|
}
|
||||||
@ -131,13 +131,13 @@ func (r *RouteCache) GetRouteInfo(name string) (RouteInfo, error) {
|
|||||||
return RouteInfo{}, errors.New("route info not found in cache")
|
return RouteInfo{}, errors.New("route info not found in cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRouteCache(opts ...RouteCacheOpt) (*RouteCache, error) {
|
func newRouteCache(opts ...RouteCacheOpt) (*routeCache, error) {
|
||||||
s, err := storage.NewBadgerStore(storage.WithSubDir("route_cache"))
|
s, err := badger.NewBadgerStore(badger.WithSubDir("route_cache"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, jerr.Wrap(jerr.ErrFailedToCreateRouteCache, err)
|
return nil, jerr.Wrap(jerr.ErrFailedToCreateRouteCache, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cache := &RouteCache{
|
cache := &routeCache{
|
||||||
rs: make(map[string]string),
|
rs: make(map[string]string),
|
||||||
s: s,
|
s: s,
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package routing
|
package joist
|
||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
@ -1,29 +1,59 @@
|
|||||||
package routing
|
package joist
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
jerr "git.markbailey.dev/cerbervs/joist/internal/errors"
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RouteCacher interface {
|
type RouteInfo struct {
|
||||||
Add(string, string) error
|
Method string
|
||||||
AddRouteInfo(RouteInfo) error
|
Name string
|
||||||
GetPath(string) (string, error)
|
Path string
|
||||||
GetRouteInfo(string) (RouteInfo, error)
|
Description string
|
||||||
All() (map[string]string, error)
|
Title string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewRouteInfo(method, path, description, title string) (RouteInfo, error) {
|
||||||
|
name, err := convertRouteToRouteName(path)
|
||||||
|
if err != nil {
|
||||||
|
return RouteInfo{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return RouteInfo{
|
||||||
|
Method: method,
|
||||||
|
Name: name,
|
||||||
|
Path: path,
|
||||||
|
Description: description,
|
||||||
|
Title: title,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type routeInfoKey struct{}
|
||||||
|
|
||||||
type Router struct {
|
type Router struct {
|
||||||
*chi.Mux
|
chi.Mux
|
||||||
cache RouteCacher
|
cache RouteCacher
|
||||||
cacheTTL time.Duration
|
cacheTTL time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewRouter() Router {
|
||||||
|
ttl := 8 * time.Hour
|
||||||
|
|
||||||
|
cache, err := NewRouteCacheService(WithTTL(ttl))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(jerr.Wrap(err, jerr.ErrRouterNotCreated))
|
||||||
|
}
|
||||||
|
|
||||||
|
return Router{cache: cache, cacheTTL: ttl}
|
||||||
|
}
|
||||||
|
|
||||||
func (ro *Router) WithRouteInfo(ri RouteInfo, h HandlerFn) http.HandlerFunc {
|
func (ro *Router) WithRouteInfo(ri RouteInfo, h HandlerFn) http.HandlerFunc {
|
||||||
ro.cache.AddRouteInfo(ri)
|
ro.cache.AddRouteInfo(ri)
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user