Skip to content

Commit

Permalink
refactor: switch to stdlib router
Browse files Browse the repository at this point in the history
  • Loading branch information
vgarvardt committed Mar 24, 2024
1 parent f0d1a6e commit fd03652
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 57 deletions.
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ go 1.22

require (
github.com/asdine/storm/v3 v3.2.1
github.com/cappuccinotm/slogx v1.3.0
github.com/cappuccinotm/slogx v1.4.0
github.com/felixge/httpsnoop v1.0.4
github.com/go-chi/chi/v5 v5.0.12
github.com/go-pkgz/routegroup v1.1.1
github.com/gorilla/feeds v1.1.2
github.com/leekchan/gtf v0.0.0-20190214083521-5fba33c5b00b
github.com/sethvargo/go-envconfig v1.0.1
Expand All @@ -24,8 +25,8 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.2 // indirect
go.etcd.io/bbolt v1.3.4 // indirect
golang.org/x/net v0.21.0 // indirect
go.etcd.io/bbolt v1.3.9 // indirect
golang.org/x/net v0.22.0 // indirect
golang.org/x/sys v0.18.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
13 changes: 8 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@ github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863 h1:BRrxwOZBolJN4gIwv
github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863/go.mod h1:D0JMgToj/WdxCgd30Kc1UcA9E+WdZoJqeVOuYW7iTBM=
github.com/asdine/storm/v3 v3.2.1 h1:I5AqhkPK6nBZ/qJXySdI7ot5BlXSZ7qvDY1zAn5ZJac=
github.com/asdine/storm/v3 v3.2.1/go.mod h1:LEpXwGt4pIqrE/XcTvCnZHT5MgZCV6Ub9q7yQzOFWr0=
github.com/cappuccinotm/slogx v1.3.0 h1:1kkmKLLqfByZDuS+SXZZHfl6Skez/ASKAzHN+OI37w0=
github.com/cappuccinotm/slogx v1.3.0/go.mod h1:Q9lmOfumtErQpVTT5/3nKH++YRJMrYNvGe7Xkqnjr2Q=
github.com/cappuccinotm/slogx v1.4.0 h1:hqruNf/7KAWP+hTY6bL9vklaIpaSMYIWsLFGtEHNOoo=
github.com/cappuccinotm/slogx v1.4.0/go.mod h1:Q9lmOfumtErQpVTT5/3nKH++YRJMrYNvGe7Xkqnjr2Q=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-pkgz/routegroup v1.1.1 h1:Dm5IBiEmUbQT+3rliBimhX0SifnZp/uRF/WOu3XPmms=
github.com/go-pkgz/routegroup v1.1.1/go.mod h1:kDDPDRLRiRY1vnENrZJw1jQAzQX7fvsbsHGRQFNQfKc=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand Down Expand Up @@ -53,15 +55,16 @@ github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaU
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/yuin/goldmark v1.7.0 h1:EfOIvIMZIzHdB/R/zVrikYLPPwJlfMcNczJFMs1m6sA=
github.com/yuin/goldmark v1.7.0/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down
1 change: 0 additions & 1 deletion pkg/server/handler/posts.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ func (h *Posts) Tag(w http.ResponseWriter, r *http.Request) {
// Post is the HTTP handler for the post page
func (h *Posts) Post(w http.ResponseWriter, r *http.Request) {
post, err := h.storage.FindByPath(r.URL.Path)

if err != nil {
status := map[bool]int{
true: http.StatusNotFound,
Expand Down
6 changes: 4 additions & 2 deletions pkg/server/middleware/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ func NewLogger(logger *slog.Logger) *Logger {
// Handler is the request handler that creates logger instance for each request with corresponding request ID.
func (m *Logger) Handler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requestID := middleware.GetReqID(r.Context())
ctx := r.Context()

Check warning on line 25 in pkg/server/middleware/logger.go

View check run for this annotation

Codecov / codecov/patch

pkg/server/middleware/logger.go#L25

Added line #L25 was not covered by tests

requestID := middleware.GetReqID(ctx)

Check warning on line 27 in pkg/server/middleware/logger.go

View check run for this annotation

Codecov / codecov/patch

pkg/server/middleware/logger.go#L27

Added line #L27 was not covered by tests
requestLogger := m.logger.With(slog.String("request-id", requestID))

newCtx := rqctx.SetID(r.Context(), requestID)
newCtx := rqctx.SetID(ctx, requestID)

Check warning on line 30 in pkg/server/middleware/logger.go

View check run for this annotation

Codecov / codecov/patch

pkg/server/middleware/logger.go#L30

Added line #L30 was not covered by tests
newCtx = rqctx.SetLogger(newCtx, requestLogger)
next.ServeHTTP(w, r.WithContext(newCtx))
})
Expand Down
6 changes: 4 additions & 2 deletions pkg/server/middleware/request_logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ func NewRequestLogger() *RequestLogger {
// Handler is the request handler that logs request data
func (m *RequestLogger) Handler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
rqctx.GetLogger(r.Context()).Debug("Started request", slog.String("method", r.Method), slog.String("path", r.URL.Path))
logger := rqctx.GetLogger(r.Context())

Check warning on line 27 in pkg/server/middleware/request_logger.go

View check run for this annotation

Codecov / codecov/patch

pkg/server/middleware/request_logger.go#L27

Added line #L27 was not covered by tests

logger.Debug("Started request", slog.String("method", r.Method), slog.String("path", r.URL.Path))

Check warning on line 29 in pkg/server/middleware/request_logger.go

View check run for this annotation

Codecov / codecov/patch

pkg/server/middleware/request_logger.go#L29

Added line #L29 was not covered by tests

metrics := httpsnoop.CaptureMetrics(next, w, r)

logEntry := rqctx.GetLogger(r.Context()).With(
logEntry := logger.With(

Check warning on line 33 in pkg/server/middleware/request_logger.go

View check run for this annotation

Codecov / codecov/patch

pkg/server/middleware/request_logger.go#L33

Added line #L33 was not covered by tests
slog.String("method", r.Method),
slog.String("path", r.URL.Path),
slog.String("host", r.Host),
Expand Down
4 changes: 1 addition & 3 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ func Run(ctx context.Context, cfg *Config, version string) error {
postsHandler := handler.NewPosts(storageInstance, htmlRenderer)
feedHandler := handler.NewFeed(storageInstance, feedRenderer)

r := web.NewRouter(postsHandler, feedHandler, logger)

web.ServeStatic(r, cfg.HTTPConfig, cfg.UIConfig.Theme)
r := web.NewRouter(postsHandler, feedHandler, cfg.HTTPConfig, cfg.UIConfig.Theme, logger)

Check warning on line 65 in pkg/server/server.go

View check run for this annotation

Codecov / codecov/patch

pkg/server/server.go#L65

Added line #L65 was not covered by tests

return web.ListenAndServe(ctx, r, cfg.SSLConfig, cfg.HTTPConfig, logger)
}
53 changes: 26 additions & 27 deletions pkg/server/web/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,56 +10,55 @@ import (
"time"

"github.com/cappuccinotm/slogx"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/go-pkgz/routegroup"
"golang.org/x/crypto/acme/autocert"
"golang.org/x/sync/errgroup"

"github.com/vgarvardt/rklotz/pkg/server/handler"
m "github.com/vgarvardt/rklotz/pkg/server/middleware"
)

const staticPath = "/static"

// NewRouter initialises and builds new HTTP router
func NewRouter(pH *handler.Posts, fH *handler.Feed, logger *slog.Logger) chi.Router {
r := chi.NewRouter()

r.Use(middleware.RequestID)
r.Use(middleware.RealIP)
r.Use(m.NewLogger(logger).Handler)
r.Use(m.NewRequestLogger().Handler)
r.Use(m.Recovery)

r.Get("/", pH.Front)
r.Get("/tag/{tag}", pH.Tag)
r.NotFound(pH.Post)

r.Route("/feed", func(r chi.Router) {
r.Get("/atom", fH.Atom)
r.Get("/rss", fH.Rss)
func NewRouter(ph *handler.Posts, fh *handler.Feed, cfgHTTP HTTPConfig, theme string, logger *slog.Logger) http.Handler {
mux := routegroup.New(http.NewServeMux())

Check warning on line 26 in pkg/server/web/serve.go

View check run for this annotation

Codecov / codecov/patch

pkg/server/web/serve.go#L25-L26

Added lines #L25 - L26 were not covered by tests

mux.Use(
middleware.RequestID,
middleware.RealIP,
m.NewLogger(logger).Handler,
m.NewRequestLogger().Handler,
m.Recovery,
)

Check warning on line 34 in pkg/server/web/serve.go

View check run for this annotation

Codecov / codecov/patch

pkg/server/web/serve.go#L28-L34

Added lines #L28 - L34 were not covered by tests

mux.HandleFunc("GET /{$}", ph.Front)
mux.HandleFunc("GET /tag/{tag}", ph.Tag)
mux.HandleFunc("/", ph.Post)

Check warning on line 38 in pkg/server/web/serve.go

View check run for this annotation

Codecov / codecov/patch

pkg/server/web/serve.go#L36-L38

Added lines #L36 - L38 were not covered by tests

mux.Mount("/feed").Route(func(b *routegroup.Bundle) {
b.HandleFunc("GET /atom", fh.Atom)
b.HandleFunc("GET /rss", fh.Rss)

Check warning on line 42 in pkg/server/web/serve.go

View check run for this annotation

Codecov / codecov/patch

pkg/server/web/serve.go#L40-L42

Added lines #L40 - L42 were not covered by tests
})

return r
}

// ServeStatic registers static handler for the router
func ServeStatic(r chi.Router, cfgHTTP HTTPConfig, theme string) {
staticRoot := http.Dir(cfgHTTP.StaticPath)
staticPath := "/static"
staticHandler := http.StripPrefix(staticPath, http.FileServer(staticRoot))

faviconPath := filepath.Join(cfgHTTP.StaticPath, theme, "favicon.ico")

r.Get(staticPath+"/*", func(w http.ResponseWriter, r *http.Request) {
mux.HandleFunc("GET "+staticPath+"/", func(w http.ResponseWriter, r *http.Request) {

Check warning on line 49 in pkg/server/web/serve.go

View check run for this annotation

Codecov / codecov/patch

pkg/server/web/serve.go#L49

Added line #L49 was not covered by tests
staticHandler.ServeHTTP(w, r)
})

r.Get("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {
mux.HandleFunc("GET /favicon.ico", func(w http.ResponseWriter, r *http.Request) {

Check warning on line 53 in pkg/server/web/serve.go

View check run for this annotation

Codecov / codecov/patch

pkg/server/web/serve.go#L53

Added line #L53 was not covered by tests
http.ServeFile(w, r, faviconPath)
})

return mux

Check warning on line 57 in pkg/server/web/serve.go

View check run for this annotation

Codecov / codecov/patch

pkg/server/web/serve.go#L57

Added line #L57 was not covered by tests
}

// ListenAndServe launches web server that listens to HTTP(S) requests
func ListenAndServe(ctx context.Context, router chi.Router, cfgSSL SSLConfig, cfgHTTP HTTPConfig, logger *slog.Logger) error {
func ListenAndServe(ctx context.Context, router http.Handler, cfgSSL SSLConfig, cfgHTTP HTTPConfig, logger *slog.Logger) error {

Check warning on line 61 in pkg/server/web/serve.go

View check run for this annotation

Codecov / codecov/patch

pkg/server/web/serve.go#L61

Added line #L61 was not covered by tests
if !cfgSSL.Enabled {
server := &http.Server{
ReadTimeout: 10 * time.Second,
Expand Down
27 changes: 13 additions & 14 deletions pkg/storage/storage_boltdb.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package storage

import (
"errors"
"io/fs"
"os"
"path/filepath"

Expand Down Expand Up @@ -69,7 +71,7 @@ func (s *BoltDBStorage) Save(post *model.Post) error {
for i := range post.Tags {
var tag model.Tag
err := s.tags.One("Tag", post.Tags[i], &tag)
if err == storm.ErrNotFound {
if errors.Is(err, storm.ErrNotFound) {
tag = model.Tag{Tag: post.Tags[i], Paths: []string{}}
} else if nil != err {
return err
Expand All @@ -94,9 +96,9 @@ func (s *BoltDBStorage) Finalize() error {
// FindByPath searches for a post by path
func (s *BoltDBStorage) FindByPath(path string) (*model.Post, error) {
var post model.Post
err := s.db.One("Path", path, &post)

if err == storm.ErrNotFound {
err := s.db.One("Path", path, &post)
if errors.Is(err, storm.ErrNotFound) {
return nil, ErrorNotFound
}

Expand All @@ -116,7 +118,7 @@ func (s *BoltDBStorage) ListTag(tag string, page int) ([]*model.Post, error) {
var tagObject model.Tag

err := s.tags.One("Tag", tag, &tagObject)
if err == storm.ErrNotFound {
if errors.Is(err, storm.ErrNotFound) {
return nil, ErrorNotFound
}

Expand Down Expand Up @@ -163,16 +165,13 @@ func (s *BoltDBStorage) TagMeta(tag string) *model.Meta {

func (s *BoltDBStorage) remove() error {
_, err := os.Stat(s.path)
if err != nil {
if !os.IsNotExist(err) {
return err
}
} else {
err = os.Remove(s.path)
if err != nil {
return err
}
if err == nil {
return os.Remove(s.path)
}

return nil
if errors.Is(err, fs.ErrNotExist) {
return nil
}

return err

Check warning on line 176 in pkg/storage/storage_boltdb.go

View check run for this annotation

Codecov / codecov/patch

pkg/storage/storage_boltdb.go#L176

Added line #L176 was not covered by tests
}

0 comments on commit fd03652

Please sign in to comment.