Refactored application creation
continuous-integration/drone/push Build is passing Details

main
Drew Bednar 2 months ago
parent 32190b7036
commit 37404b4821

@ -95,7 +95,7 @@ func main() {
srv := &http.Server{ srv := &http.Server{
Addr: fmt.Sprintf("%s:%s", *addr, *port), Addr: fmt.Sprintf("%s:%s", *addr, *port),
Handler: app, Handler: app.Routes(),
ErrorLog: slog.NewLogLogger(logger.Handler(), slog.LevelError), ErrorLog: slog.NewLogLogger(logger.Handler(), slog.LevelError),
TLSConfig: &tlsConfig, TLSConfig: &tlsConfig,
// Server wide timeouts. // Server wide timeouts.

@ -49,7 +49,7 @@ func TestPingIntegration(t *testing.T) {
t.Parallel() t.Parallel()
app := newTestApplication(t) app := newTestApplication(t)
ts := newTestServer(t, app) ts := newTestServer(t, app.Routes())
defer ts.Close() defer ts.Close()
code, _, body := ts.get(t, "/ping") code, _, body := ts.get(t, "/ping")

@ -1,45 +1,54 @@
package server package server
import ( import (
"database/sql"
"log/slog"
"net/http" "net/http"
"git.runcible.io/learning/ratchet/internal/model" "git.runcible.io/learning/ratchet/ui"
"github.com/alexedwards/scs/v2"
"github.com/go-playground/form/v4"
) )
func addRoutes(mux *http.ServeMux, func addBaseMiddleware(app *RatchetApp, next http.Handler, requireAuth bool) http.Handler {
logger *slog.Logger, var h http.Handler
tc *TemplateCache, if requireAuth {
db *sql.DB, h = RequireAuthenticationMiddleware(next, app.sessionManager)
fd *form.Decoder, }
sm *scs.SessionManager, h = AuthenticateMiddleware(next, app.sessionManager, app.userService)
userService *model.UserService, h = NoSurfMiddleware(h)
snippetService *model.SnippetService) http.Handler { h = app.sessionManager.LoadAndSave(h)
return h
}
func (a *RatchetApp) Routes() http.Handler {
// TODO implement middleware that disables directory listings
// This line was superceded by using the embedded filesystem
// fileServer := http.FileServer(http.Dir("./ui/static/"))
router := http.NewServeMux()
mux.Handle("GET /ping", PingHandler()) // Subtree pattern for static assets
// This line was superceded by using the embedded filesystem
// router.Handle("GET /static/", http.StripPrefix("/static/", fileServer))
router.Handle("GET /static/", http.FileServerFS(ui.Files))
router.Handle("GET /ping", PingHandler())
// /{$} is used to prevent subtree path patterns from acting like a wildcard // /{$} is used to prevent subtree path patterns from acting like a wildcard
// resulting in this route requiring an exact match on "/" only // resulting in this route requiring an exact match on "/" only
// You can only include one HTTP method in a route pattern if you choose // You can only include one HTTP method in a route pattern if you choose
// GET will match GET & HEAD http request methods // GET will match GET & HEAD http request methods
mux.Handle("GET /{$}", sm.LoadAndSave(NoSurfMiddleware(AuthenticateMiddleware(handleHome(logger, tc, sm, snippetService), sm, userService)))) // might be time to swith to github.com/justinas/alice dynamic chain router.Handle("GET /{$}", addBaseMiddleware(a, handleHome(a.logger, a.templateCache, a.sessionManager, a.snippetService), false)) // might be time to swith to github.com/justinas/alice dynamic chain
mux.Handle("GET /snippet/view/{id}", sm.LoadAndSave(NoSurfMiddleware(AuthenticateMiddleware(handleSnippetView(logger, tc, sm, snippetService), sm, userService)))) router.Handle("GET /snippet/view/{id}", addBaseMiddleware(a, handleSnippetView(a.logger, a.templateCache, a.sessionManager, a.snippetService), false))
mux.Handle("GET /snippet/create", sm.LoadAndSave(NoSurfMiddleware(AuthenticateMiddleware(RequireAuthenticationMiddleware(handleSnippetCreateGet(tc, sm), sm), sm, userService)))) router.Handle("GET /snippet/create", addBaseMiddleware(a, handleSnippetCreateGet(a.templateCache, a.sessionManager), true))
mux.Handle("POST /snippet/create", sm.LoadAndSave(NoSurfMiddleware(AuthenticateMiddleware(RequireAuthenticationMiddleware(handleSnippetCreatePost(logger, tc, fd, sm, snippetService), sm), sm, userService)))) router.Handle("POST /snippet/create", addBaseMiddleware(a, handleSnippetCreatePost(a.logger, a.templateCache, a.formDecoder, a.sessionManager, a.snippetService), true))
// mux.Handle("/something", handleSomething(logger, config)) // mux.Handle("/something", handleSomething(logger, config))
// mux.Handle("/healthz", handleHealthzPlease(logger)) // mux.Handle("/healthz", handleHealthzPlease(logger))
// mux.Handle("/", http.NotFoundHandler()) // mux.Handle("/", http.NotFoundHandler())
mux.Handle("GET /user/signup", sm.LoadAndSave(NoSurfMiddleware(AuthenticateMiddleware(handleUserSignupGet(tc, sm), sm, userService)))) router.Handle("GET /user/signup", addBaseMiddleware(a, handleUserSignupGet(a.templateCache, a.sessionManager), false))
mux.Handle("POST /user/signup", sm.LoadAndSave(NoSurfMiddleware(AuthenticateMiddleware(handleUserSignupPost(logger, tc, fd, sm, userService), sm, userService)))) router.Handle("POST /user/signup", addBaseMiddleware(a, handleUserSignupPost(a.logger, a.templateCache, a.formDecoder, a.sessionManager, a.userService), false))
mux.Handle("GET /user/login", sm.LoadAndSave(NoSurfMiddleware(AuthenticateMiddleware(handleUserLoginGet(tc, sm), sm, userService)))) router.Handle("GET /user/login", addBaseMiddleware(a, handleUserLoginGet(a.templateCache, a.sessionManager), false))
mux.Handle("POST /user/login", sm.LoadAndSave(NoSurfMiddleware(AuthenticateMiddleware(handleUserLoginPost(logger, tc, sm, fd, userService), sm, userService)))) router.Handle("POST /user/login", addBaseMiddleware(a, handleUserLoginPost(a.logger, a.templateCache, a.sessionManager, a.formDecoder, a.userService), false))
// Requires auth // Requires auth
mux.Handle("POST /user/logout", sm.LoadAndSave(NoSurfMiddleware(AuthenticateMiddleware(RequireAuthenticationMiddleware(handleUserLogoutPost(logger, sm), sm), sm, userService)))) router.Handle("POST /user/logout", addBaseMiddleware(a, handleUserLogoutPost(a.logger, a.sessionManager), true))
return RecoveryMiddleware(RequestLoggingMiddleware(CommonHeaderMiddleware(router), a.logger))
return mux
} }

@ -3,17 +3,13 @@ package server
import ( import (
"database/sql" "database/sql"
"log/slog" "log/slog"
"net/http"
"git.runcible.io/learning/ratchet/internal/model" "git.runcible.io/learning/ratchet/internal/model"
"git.runcible.io/learning/ratchet/ui"
"github.com/alexedwards/scs/v2" "github.com/alexedwards/scs/v2"
"github.com/go-playground/form/v4" "github.com/go-playground/form/v4"
) )
type RatchetApp struct { type RatchetApp struct {
http.Handler
logger *slog.Logger logger *slog.Logger
templateCache *TemplateCache templateCache *TemplateCache
//Services used by HTTP routes //Services used by HTTP routes
@ -33,21 +29,5 @@ func NewRatchetApp(logger *slog.Logger, tc *TemplateCache, db *sql.DB, sm *scs.S
rs.formDecoder = form.NewDecoder() rs.formDecoder = form.NewDecoder()
rs.templateCache = tc rs.templateCache = tc
rs.sessionManager = sm rs.sessionManager = sm
// TODO implement middleware that disables directory listings
// This line was superceded by using the embedded filesystem
// fileServer := http.FileServer(http.Dir("./ui/static/"))
router := http.NewServeMux()
// Subtree pattern for static assets
// This line was superceded by using the embedded filesystem
// router.Handle("GET /static/", http.StripPrefix("/static/", fileServer))
router.Handle("GET /static/", http.FileServerFS(ui.Files))
// Mux Router implements the Handler interface. AKA it has a ServeHTTP receiver.
// SEE we can really clean things up by moving this into routes.go and handlers.go
wrappedMux := addRoutes(router, rs.logger, rs.templateCache, db, rs.formDecoder, sm, rs.userService, rs.snippetService)
rs.Handler = CommonHeaderMiddleware(wrappedMux)
rs.Handler = RequestLoggingMiddleware(rs.Handler, logger)
rs.Handler = RecoveryMiddleware(rs.Handler)
return rs return rs
} }

Loading…
Cancel
Save