From 5168a9476f0e83264ecafc85bc9145e8bdcbb8dc Mon Sep 17 00:00:00 2001 From: Gabriel Arakaki Giovanini Date: Sat, 5 Aug 2023 19:26:29 +0200 Subject: ref: Move net/http I was young and naive, fasthttp does not fit my needs and make development slower. I'll move to net/http since it has a wider support and will spare some time on implementation detail things (like CSRF). It will allow me to reduce a bit of the code since there may be lib for handling cookie encryption and auth in general. --- cmd/server/main.go | 10 +++---- go.mod | 6 +--- go.sum | 12 ++------ pkg/ext/fileserver.go | 33 --------------------- pkg/ext/middleware.go | 74 ++++++++++++++++++++++------------------------ pkg/ext/responses.go | 30 ++++--------------- pkg/ext/router.go | 45 ++++++++++++++-------------- pkg/view/auth.go | 77 ++++++++++++++++++++++++++---------------------- pkg/view/filesystem.go | 16 +++++----- pkg/view/media.go | 53 ++++++++++++++++----------------- pkg/view/settings.go | 57 ++++++++++++++++++----------------- pkg/worker/httpserver.go | 15 ++++------ templates/media.qtpl | 8 ++--- 13 files changed, 186 insertions(+), 250 deletions(-) delete mode 100644 pkg/ext/fileserver.go diff --git a/cmd/server/main.go b/cmd/server/main.go index 385c54f..39987e5 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -4,13 +4,13 @@ import ( "context" "encoding/hex" "errors" + "net/http" "os" "os/signal" - "github.com/fasthttp/router" + "github.com/gorilla/mux" "github.com/sirupsen/logrus" flag "github.com/spf13/pflag" - "github.com/valyala/fasthttp" "gorm.io/driver/mysql" "gorm.io/driver/postgres" "gorm.io/driver/sqlite" @@ -71,8 +71,8 @@ func main() { panic("failed to decode key database: " + err.Error()) } - r := router.New() - r.GET("/static/{filepath:*}", ext.FileServer(static.Static)) + r := mux.NewRouter() + r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.FS(static.Static)))) // repository var ( @@ -122,7 +122,7 @@ func main() { // worker var ( - serverWorker = worker.NewServerWorker(&fasthttp.Server{Handler: r.Handler, NoDefaultContentType: true}) + serverWorker = worker.NewServerWorker(&http.Server{Handler: r, Addr: "0.0.0.0:8080"}) fileWorker = worker.NewWorkerFromChanProcessor[string]( fileScanner, scheduler, diff --git a/go.mod b/go.mod index 8b4538d..91dd7fa 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,11 @@ go 1.19 require ( github.com/barasher/go-exiftool v1.10.0 - github.com/fasthttp/router v1.4.19 github.com/google/go-cmp v0.5.9 + github.com/gorilla/mux v1.8.0 github.com/h2non/bimg v1.1.9 github.com/sirupsen/logrus v1.9.2 github.com/spf13/pflag v1.0.5 - github.com/valyala/fasthttp v1.47.0 github.com/valyala/quicktemplate v1.7.0 golang.org/x/crypto v0.8.0 gorm.io/driver/mysql v1.5.1 @@ -20,16 +19,13 @@ require ( ) require ( - github.com/andybalholm/brotli v1.0.5 // indirect github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgx/v5 v5.3.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - github.com/klauspost/compress v1.16.5 // indirect github.com/mattn/go-sqlite3 v1.14.16 // indirect - github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect golang.org/x/mod v0.10.0 // indirect golang.org/x/sys v0.8.0 // indirect diff --git a/go.sum b/go.sum index c0456bc..03ce51a 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,10 @@ github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= -github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/barasher/go-exiftool v1.10.0 h1:f5JY5jc42M7tzR6tbL9508S2IXdIcG9QyieEXNMpIhs= github.com/barasher/go-exiftool v1.10.0/go.mod h1:F9s/a3uHSM8YniVfwF+sbQUtP8Gmh9nyzigNF+8vsWo= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/fasthttp/router v1.4.19 h1:RLE539IU/S4kfb4MP56zgP0TIBU9kEg0ID9GpWO0vqk= -github.com/fasthttp/router v1.4.19/go.mod h1:+Fh3YOd8x1+he6ZS+d2iUDBH9MGGZ1xQFUor0DE9rKE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= @@ -18,6 +14,8 @@ github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/h2non/bimg v1.1.9 h1:WH20Nxko9l/HFm4kZCA3Phbgu2cbHvYzxwxn9YROEGg= github.com/h2non/bimg v1.1.9/go.mod h1:R3+UiYwkK4rQl6KVFTOFJHitgLbZXBZNFh2cv3AEbp8= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -33,16 +31,12 @@ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= -github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk= -github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g= github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y= github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -54,8 +48,6 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= -github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c= -github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= github.com/valyala/quicktemplate v1.7.0 h1:LUPTJmlVcb46OOUY3IeD9DojFpAVbsG+5WFTcjMJzCM= github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= diff --git a/pkg/ext/fileserver.go b/pkg/ext/fileserver.go deleted file mode 100644 index 87c1ae8..0000000 --- a/pkg/ext/fileserver.go +++ /dev/null @@ -1,33 +0,0 @@ -package ext - -import ( - "io/fs" - "mime" - "path/filepath" - - "github.com/valyala/fasthttp" -) - -type FileSystem interface { - Open(name string) (fs.File, error) -} - -// This is a VERY simple file server. It does not take a lot into consideration -// and it should only be used to return small predictable files, like in the -// static folder. -func FileServer(rootFS FileSystem) fasthttp.RequestHandler { - return func(ctx *fasthttp.RequestCtx) { - path := ctx.UserValue("filepath").(string) - - f, err := rootFS.Open(path) - if err != nil { - InternalServerError(ctx, err) - return - } - defer f.Close() - - m := mime.TypeByExtension(filepath.Ext(path)) - ctx.SetContentType(m) - ctx.SetBodyStream(f, -1) - } -} diff --git a/pkg/ext/middleware.go b/pkg/ext/middleware.go index bcc6c5f..fe2d185 100644 --- a/pkg/ext/middleware.go +++ b/pkg/ext/middleware.go @@ -1,22 +1,22 @@ package ext import ( + "context" "encoding/base64" + "errors" + "net/http" "time" "github.com/sirupsen/logrus" - "github.com/valyala/fasthttp" "git.sr.ht/~gabrielgio/img/pkg/database/repository" "git.sr.ht/~gabrielgio/img/pkg/service" ) -func HTML(next fasthttp.RequestHandler) fasthttp.RequestHandler { - return func(ctx *fasthttp.RequestCtx) { - if len(ctx.Request.Header.ContentType()) > 0 { - ctx.Response.Header.SetContentType("text/html") - } - next(ctx) +func HTML(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/html") + next(w, r) } } @@ -30,17 +30,15 @@ func NewLogMiddleare(log *logrus.Entry) *LogMiddleware { } } -func (l *LogMiddleware) HTTP(next fasthttp.RequestHandler) fasthttp.RequestHandler { - return func(ctx *fasthttp.RequestCtx) { +func (l *LogMiddleware) HTTP(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { start := time.Now() - next(ctx) + next(w, r) elapsed := time.Since(start) l.entry. WithField("time", elapsed). - WithField("code", ctx.Response.StatusCode()). - WithField("path", string(ctx.Path())). - WithField("bytes", len(ctx.Response.Body())). - Info(string(ctx.Request.Header.Method())) + WithField("path", r.URL.Path). + Info(r.Method) } } @@ -56,23 +54,23 @@ func NewAuthMiddleware(key []byte, log *logrus.Entry) *AuthMiddleware { } } -func (a *AuthMiddleware) LoggedIn(next fasthttp.RequestHandler) fasthttp.RequestHandler { - return func(ctx *fasthttp.RequestCtx) { - path := string(ctx.Path()) +func (a *AuthMiddleware) LoggedIn(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + path := string(r.URL.Path) if path == "/login" || path == "/initial" { - next(ctx) + next(w, r) return } redirectLogin := "/login?redirect=" + path - authBase64 := ctx.Request.Header.Cookie("auth") - if authBase64 == nil { + authBase64, err := r.Cookie("auth") + if errors.Is(err, http.ErrNoCookie) { a.entry.Info("No auth provided") - ctx.Redirect(redirectLogin, 307) + http.Redirect(w, r, redirectLogin, http.StatusTemporaryRedirect) return } - auth, err := base64.StdEncoding.DecodeString(string(authBase64)) + auth, err := base64.StdEncoding.DecodeString(authBase64.Value) if err != nil { a.entry.Error(err) return @@ -81,20 +79,20 @@ func (a *AuthMiddleware) LoggedIn(next fasthttp.RequestHandler) fasthttp.Request token, err := service.ReadToken(auth, a.key) if err != nil { a.entry.Error(err) - ctx.Redirect(redirectLogin, 307) + http.Redirect(w, r, redirectLogin, http.StatusTemporaryRedirect) return } - ctx.SetUserValue("token", token) + r = r.WithContext(context.WithValue(r.Context(), "token", token)) a.entry. WithField("userID", token.UserID). WithField("username", token.Username). Info("user recognized") - next(ctx) + next(w, r) } } -func GetTokenFromCtx(ctx *fasthttp.RequestCtx) *service.Token { - tokenValue := ctx.UserValue("token") +func GetTokenFromCtx(w http.ResponseWriter, r *http.Request) *service.Token { + tokenValue := r.Context().Value("token") if token, ok := tokenValue.(*service.Token); ok { return token } @@ -111,31 +109,31 @@ func NewInitialSetupMiddleware(userRepository repository.UserRepository) *Initia } } -func (i *InitialSetupMiddleware) Check(next fasthttp.RequestHandler) fasthttp.RequestHandler { - return func(ctx *fasthttp.RequestCtx) { +func (i *InitialSetupMiddleware) Check(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { // if user has been set to context it is logged in already - _, ok := ctx.UserValue("token").(*service.Token) - if ok { - next(ctx) + token := GetTokenFromCtx(w, r) + if token == nil { + next(w, r) return } - path := string(ctx.Path()) + path := r.URL.Path if path == "/initial" { - next(ctx) + next(w, r) return } - exists, err := i.userRepository.Any(ctx) + exists, err := i.userRepository.Any(r.Context()) if err != nil { - InternalServerError(ctx, err) + InternalServerError(w, err) return } if exists { - next(ctx) + next(w, r) return } - ctx.Redirect("/initial", 307) + http.Redirect(w, r, "/initial", http.StatusTemporaryRedirect) } } diff --git a/pkg/ext/responses.go b/pkg/ext/responses.go index dbad5b2..ba58dd5 100644 --- a/pkg/ext/responses.go +++ b/pkg/ext/responses.go @@ -1,39 +1,21 @@ package ext import ( - "bytes" "fmt" - - "github.com/valyala/fasthttp" + "net/http" "git.sr.ht/~gabrielgio/img/templates" ) -var ( - ContentTypeHTML = []byte("text/html") -) - -func NotFoundHTML(ctx *fasthttp.RequestCtx) { - templates.WritePageTemplate(ctx, &templates.ErrorPage{ +func NotFound(w http.ResponseWriter, r *http.Request) { + templates.WritePageTemplate(w, &templates.ErrorPage{ Err: "Not Found", }) } -func NotFound(ctx *fasthttp.RequestCtx) { - ctx.Response.SetStatusCode(404) - ct := ctx.Response.Header.ContentType() - if bytes.Equal(ct, ContentTypeHTML) { - NotFoundHTML(ctx) - } -} - -func InternalServerError(ctx *fasthttp.RequestCtx, err error) { - ctx.Response.SetStatusCode(500) - templates.WritePageTemplate(ctx, &templates.ErrorPage{ +func InternalServerError(w http.ResponseWriter, err error) { + w.WriteHeader(http.StatusInternalServerError) + templates.WritePageTemplate(w, &templates.ErrorPage{ Err: fmt.Sprintf("Internal Server Error:\n%s", err.Error()), }) } - -func NoContent(ctx *fasthttp.RequestCtx) { - ctx.Response.SetStatusCode(204) -} diff --git a/pkg/ext/router.go b/pkg/ext/router.go index 74f0a95..8b9a310 100644 --- a/pkg/ext/router.go +++ b/pkg/ext/router.go @@ -1,51 +1,52 @@ package ext import ( - "github.com/fasthttp/router" - "github.com/valyala/fasthttp" + "net/http" + + "github.com/gorilla/mux" ) type ( Router struct { middlewares []Middleware - fastRouter *router.Router + router *mux.Router } - Middleware func(next fasthttp.RequestHandler) fasthttp.RequestHandler - ErrorRequestHandler func(ctx *fasthttp.RequestCtx) error + Middleware func(next http.HandlerFunc) http.HandlerFunc + ErrorRequestHandler func(w http.ResponseWriter, r *http.Request) error ) -func NewRouter(nestedRouter *router.Router) *Router { +func NewRouter(nestedRouter *mux.Router) *Router { return &Router{ - fastRouter: nestedRouter, + router: nestedRouter, } } -func (self *Router) AddMiddleware(middleware Middleware) { - self.middlewares = append(self.middlewares, middleware) +func (r *Router) AddMiddleware(middleware Middleware) { + r.middlewares = append(r.middlewares, middleware) } -func wrapError(next ErrorRequestHandler) fasthttp.RequestHandler { - return func(ctx *fasthttp.RequestCtx) { - if err := next(ctx); err != nil { - ctx.Response.SetStatusCode(500) - InternalServerError(ctx, err) +func wrapError(next ErrorRequestHandler) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if err := next(w, r); err != nil { + w.WriteHeader(http.StatusInternalServerError) + InternalServerError(w, err) } } } -func (self *Router) run(next ErrorRequestHandler) fasthttp.RequestHandler { - return func(ctx *fasthttp.RequestCtx) { +func (r *Router) run(next ErrorRequestHandler) http.HandlerFunc { + return func(w http.ResponseWriter, re *http.Request) { req := wrapError(next) - for _, r := range self.middlewares { + for _, r := range r.middlewares { req = r(req) } - req(ctx) + req(w, re) } } -func (self *Router) GET(path string, handler ErrorRequestHandler) { - self.fastRouter.GET(path, self.run(handler)) +func (r *Router) GET(path string, handler ErrorRequestHandler) { + r.router.HandleFunc(path, r.run(handler)).Methods("GET") } -func (self *Router) POST(path string, handler ErrorRequestHandler) { - self.fastRouter.POST(path, self.run(handler)) +func (r *Router) POST(path string, handler ErrorRequestHandler) { + r.router.HandleFunc(path, r.run(handler)).Methods("POSt") } diff --git a/pkg/view/auth.go b/pkg/view/auth.go index 631cfb3..2a4b95e 100644 --- a/pkg/view/auth.go +++ b/pkg/view/auth.go @@ -2,8 +2,7 @@ package view import ( "encoding/base64" - - "github.com/valyala/fasthttp" + "net/http" "git.sr.ht/~gabrielgio/img/pkg/ext" "git.sr.ht/~gabrielgio/img/pkg/service" @@ -20,71 +19,77 @@ func NewAuthView(userController *service.AuthController) *AuthView { } } -func (v *AuthView) LoginView(ctx *fasthttp.RequestCtx) error { - templates.WritePageTemplate(ctx, &templates.LoginPage{}) +func (v *AuthView) LoginView(w http.ResponseWriter, r *http.Request) error { + templates.WritePageTemplate(w, &templates.LoginPage{}) return nil } -func (v *AuthView) Logout(ctx *fasthttp.RequestCtx) error { - cook := fasthttp.Cookie{} - cook.SetKey("auth") - cook.SetValue("") - cook.SetMaxAge(-1) - cook.SetHTTPOnly(true) - cook.SetSameSite(fasthttp.CookieSameSiteDefaultMode) - ctx.Response.Header.SetCookie(&cook) +func (v *AuthView) Logout(w http.ResponseWriter, r *http.Request) error { + cook := http.Cookie{ + Name: "auth", + Value: "", + MaxAge: -1, + HttpOnly: true, + SameSite: http.SameSiteDefaultMode, + } + http.SetCookie(w, &cook) - ctx.Redirect("/", 307) + http.Redirect(w, r, "/", http.StatusTemporaryRedirect) return nil } -func (v *AuthView) Login(ctx *fasthttp.RequestCtx) error { - username := ctx.FormValue("username") - password := ctx.FormValue("password") +func (v *AuthView) Login(w http.ResponseWriter, r *http.Request) error { + var ( + username = []byte(r.FormValue("username")) + password = []byte(r.FormValue("password")) + ) - auth, err := v.userController.Login(ctx, username, password) + auth, err := v.userController.Login(r.Context(), username, password) if err != nil { return err } base64Auth := base64.StdEncoding.EncodeToString(auth) - cook := fasthttp.Cookie{} - cook.SetKey("auth") - cook.SetValue(base64Auth) - cook.SetHTTPOnly(true) - cook.SetSameSite(fasthttp.CookieSameSiteDefaultMode) - ctx.Response.Header.SetCookie(&cook) + cook := http.Cookie{ + Name: "auth", + Value: base64Auth, + HttpOnly: true, + SameSite: http.SameSiteDefaultMode, + } + http.SetCookie(w, &cook) - redirect := string(ctx.FormValue("redirect")) + redirect := r.FormValue("redirect") if redirect == "" { - ctx.Redirect("/", 307) + http.Redirect(w, r, "/", http.StatusTemporaryRedirect) } else { - ctx.Redirect(redirect, 307) + http.Redirect(w, r, redirect, http.StatusTemporaryRedirect) } return nil } -func Index(ctx *fasthttp.RequestCtx) { - ctx.Redirect("/login", 307) +func Index(w http.ResponseWriter, r *http.Request) { + http.Redirect(w, r, "/login", http.StatusTemporaryRedirect) } -func (v *AuthView) InitialRegisterView(ctx *fasthttp.RequestCtx) error { - templates.WritePageTemplate(ctx, &templates.RegisterPage{}) +func (v *AuthView) InitialRegisterView(w http.ResponseWriter, r *http.Request) error { + templates.WritePageTemplate(w, &templates.RegisterPage{}) return nil } -func (v *AuthView) InitialRegister(ctx *fasthttp.RequestCtx) error { - username := ctx.FormValue("username") - password := ctx.FormValue("password") - path := ctx.FormValue("path") +func (v *AuthView) InitialRegister(w http.ResponseWriter, r *http.Request) error { + var ( + username = []byte(r.FormValue("username")) + password = []byte(r.FormValue("password")) + path = []byte(r.FormValue("path")) + ) - err := v.userController.InitialRegister(ctx, username, password, path) + err := v.userController.InitialRegister(r.Context(), username, password, path) if err != nil { return err } - ctx.Redirect("/login", 307) + http.Redirect(w, r, "/login", http.StatusTemporaryRedirect) return nil } diff --git a/pkg/view/filesystem.go b/pkg/view/filesystem.go index 6a01117..d49ad4f 100644 --- a/pkg/view/filesystem.go +++ b/pkg/view/filesystem.go @@ -1,7 +1,7 @@ package view import ( - "github.com/valyala/fasthttp" + "net/http" "git.sr.ht/~gabrielgio/img/pkg/database/repository" "git.sr.ht/~gabrielgio/img/pkg/ext" @@ -31,21 +31,23 @@ func NewFileSystemView( } } -func (self *FileSystemView) Index(ctx *fasthttp.RequestCtx) error { - pathValue := string(ctx.FormValue("path")) - token := ext.GetTokenFromCtx(ctx) +func (self *FileSystemView) Index(w http.ResponseWriter, r *http.Request) error { + var ( + pathValue = r.FormValue("path") + token = ext.GetTokenFromCtx(w, r) + ) - page, err := self.fsService.GetPage(ctx, token.UserID, pathValue) + page, err := self.fsService.GetPage(r.Context(), token.UserID, pathValue) if err != nil { return err } - settings, err := self.settings.Load(ctx) + settings, err := self.settings.Load(r.Context()) if err != nil { return err } - templates.WritePageTemplate(ctx, &templates.FilePage{ + templates.WritePageTemplate(w, &templates.FilePage{ Page: page, ShowMode: settings.ShowMode, ShowOwner: settings.ShowOwner, diff --git a/pkg/view/media.go b/pkg/view/media.go index 6e34fd6..c7d84ec 100644 --- a/pkg/view/media.go +++ b/pkg/view/media.go @@ -1,10 +1,9 @@ package view import ( + "net/http" "strconv" - "github.com/valyala/fasthttp" - "git.sr.ht/~gabrielgio/img/pkg/database/repository" "git.sr.ht/~gabrielgio/img/pkg/ext" "git.sr.ht/~gabrielgio/img/templates" @@ -18,12 +17,12 @@ type ( } ) -func getPagination(ctx *fasthttp.RequestCtx) *repository.Pagination { +func getPagination(w http.ResponseWriter, r *http.Request) *repository.Pagination { var ( size int page int - sizeStr = string(ctx.FormValue("size")) - pageStr = string(ctx.FormValue("page")) + sizeStr = r.FormValue("size") + pageStr = r.FormValue("page") ) if sizeStr == "" { @@ -60,22 +59,22 @@ func NewMediaView( } } -func (self *MediaView) Index(ctx *fasthttp.RequestCtx) error { - p := getPagination(ctx) - token := ext.GetTokenFromCtx(ctx) +func (self *MediaView) Index(w http.ResponseWriter, r *http.Request) error { + p := getPagination(w, r) + token := ext.GetTokenFromCtx(w, r) - userPath, err := self.userRepository.GetPathFromUserID(ctx, token.UserID) + userPath, err := self.userRepository.GetPathFromUserID(r.Context(), token.UserID) if err != nil { return err } p.Path = userPath - medias, err := self.mediaRepository.List(ctx, p) + medias, err := self.mediaRepository.List(r.Context(), p) if err != nil { return err } - settings, err := self.settingsRepository.Load(ctx) + settings, err := self.settingsRepository.Load(r.Context()) if err != nil { return err } @@ -89,43 +88,43 @@ func (self *MediaView) Index(ctx *fasthttp.RequestCtx) error { Settings: settings, } - templates.WritePageTemplate(ctx, page) + templates.WritePageTemplate(w, page) return nil } -func (self *MediaView) GetImage(ctx *fasthttp.RequestCtx) error { - pathHash := string(ctx.FormValue("path_hash")) +func (self *MediaView) GetImage(w http.ResponseWriter, r *http.Request) error { + pathHash := r.FormValue("path_hash") - media, err := self.mediaRepository.Get(ctx, pathHash) + media, err := self.mediaRepository.Get(r.Context(), pathHash) if err != nil { return err } - ctx.Response.Header.SetContentType(media.MIMEType) - fasthttp.ServeFileUncompressed(ctx, media.Path) + w.Header().Set("Content-Type", media.MIMEType) + http.ServeFile(w, r, media.Path) return nil } -func (self *MediaView) GetThumbnail(ctx *fasthttp.RequestCtx) error { - pathHash := string(ctx.FormValue("path_hash")) +func (self *MediaView) GetThumbnail(w http.ResponseWriter, r *http.Request) error { + pathHash := r.FormValue("path_hash") - path, err := self.mediaRepository.GetThumbnailPath(ctx, pathHash) + path, err := self.mediaRepository.GetThumbnailPath(r.Context(), pathHash) if err != nil { - ctx.Redirect("/media/image?path_hash="+pathHash, 307) + http.Redirect(w, r, "/media/image?path_hash="+pathHash, http.StatusTemporaryRedirect) // nolint: nilerr return nil } - ctx.Request.Header.SetContentType("image/jpeg") - fasthttp.ServeFileUncompressed(ctx, path) + w.Header().Set("Content-Type", "image/jpeg") + http.ServeFile(w, r, path) return nil } func (self *MediaView) SetMyselfIn(r *ext.Router) { - r.GET("/media", self.Index) - r.POST("/media", self.Index) + r.GET("/media/", self.Index) + r.POST("/media/", self.Index) - r.GET("/media/image", self.GetImage) - r.GET("/media/thumbnail", self.GetThumbnail) + r.GET("/media/image/", self.GetImage) + r.GET("/media/thumbnail/", self.GetThumbnail) } diff --git a/pkg/view/settings.go b/pkg/view/settings.go index 5131362..bf2dca6 100644 --- a/pkg/view/settings.go +++ b/pkg/view/settings.go @@ -1,10 +1,9 @@ package view import ( + "net/http" "strconv" - "github.com/valyala/fasthttp" - "git.sr.ht/~gabrielgio/img/pkg/database/repository" "git.sr.ht/~gabrielgio/img/pkg/ext" "git.sr.ht/~gabrielgio/img/pkg/service" @@ -29,18 +28,18 @@ func NewSettingsView( } } -func (self *SettingsView) Index(ctx *fasthttp.RequestCtx) error { - s, err := self.settingsRepository.Load(ctx) +func (self *SettingsView) Index(w http.ResponseWriter, r *http.Request) error { + s, err := self.settingsRepository.Load(r.Context()) if err != nil { return err } - users, err := self.userController.List(ctx) + users, err := self.userController.List(r.Context()) if err != nil { return err } - templates.WritePageTemplate(ctx, &templates.SettingsPage{ + templates.WritePageTemplate(w, &templates.SettingsPage{ Settings: s, Users: users, }) @@ -48,22 +47,22 @@ func (self *SettingsView) Index(ctx *fasthttp.RequestCtx) error { return nil } -func (self *SettingsView) User(ctx *fasthttp.RequestCtx) error { - id := string(ctx.FormValue("userId")) +func (self *SettingsView) User(w http.ResponseWriter, r *http.Request) error { + id := r.FormValue("userId") idValue, err := ParseUint(id) if err != nil { return err } if idValue == nil { - templates.WritePageTemplate(ctx, &templates.UserPage{}) + templates.WritePageTemplate(w, &templates.UserPage{}) } else { - user, err := self.userController.Get(ctx, *idValue) + user, err := self.userController.Get(r.Context(), *idValue) if err != nil { return err } - templates.WritePageTemplate(ctx, &templates.UserPage{ + templates.WritePageTemplate(w, &templates.UserPage{ ID: idValue, Username: user.Username, Path: user.Path, @@ -74,13 +73,13 @@ func (self *SettingsView) User(ctx *fasthttp.RequestCtx) error { return nil } -func (self *SettingsView) UpsertUser(ctx *fasthttp.RequestCtx) error { +func (self *SettingsView) UpsertUser(w http.ResponseWriter, r *http.Request) error { var ( - username = string(ctx.FormValue("username")) - password = ctx.FormValue("password") - path = string(ctx.FormValue("path")) - isAdmin = string(ctx.FormValue("isAdmin")) == "on" - id = string(ctx.FormValue("userId")) + username = r.FormValue("username") + password = []byte(r.FormValue("password")) + path = r.FormValue("path") + isAdmin = r.FormValue("isAdmin") == "on" + id = r.FormValue("userId") ) idValue, err := ParseUint(id) @@ -88,18 +87,18 @@ func (self *SettingsView) UpsertUser(ctx *fasthttp.RequestCtx) error { return err } - err = self.userController.Upsert(ctx, idValue, username, "", password, isAdmin, path) + err = self.userController.Upsert(r.Context(), idValue, username, "", password, isAdmin, path) if err != nil { return err } - ctx.Redirect("/settings", 307) + http.Redirect(w, r, "/settings", http.StatusTemporaryRedirect) return nil } -func (self *SettingsView) Delete(ctx *fasthttp.RequestCtx) error { +func (self *SettingsView) Delete(w http.ResponseWriter, r *http.Request) error { var ( - id = string(ctx.FormValue("userId")) + id = r.FormValue("userId") ) idValue, err := ParseUint(id) @@ -108,24 +107,24 @@ func (self *SettingsView) Delete(ctx *fasthttp.RequestCtx) error { } if idValue != nil { - err = self.userController.Delete(ctx, *idValue) + err = self.userController.Delete(r.Context(), *idValue) if err != nil { return err } } - ctx.Redirect("/settings", 307) + http.Redirect(w, r, "/settings", http.StatusTemporaryRedirect) return nil } -func (self *SettingsView) Save(ctx *fasthttp.RequestCtx) error { +func (self *SettingsView) Save(w http.ResponseWriter, r *http.Request) error { var ( - showMode = string(ctx.FormValue("showMode")) == "on" - showOwner = string(ctx.FormValue("showOwner")) == "on" - preloadVideoMetadata = string(ctx.FormValue("preloadVideoMetadata")) == "on" + showMode = r.FormValue("showMode") == "on" + showOwner = r.FormValue("showOwner") == "on" + preloadVideoMetadata = r.FormValue("preloadVideoMetadata") == "on" ) - err := self.settingsRepository.Save(ctx, &repository.Settings{ + err := self.settingsRepository.Save(r.Context(), &repository.Settings{ ShowMode: showMode, ShowOwner: showOwner, PreloadVideoMetadata: preloadVideoMetadata, @@ -134,7 +133,7 @@ func (self *SettingsView) Save(ctx *fasthttp.RequestCtx) error { return err } - return self.Index(ctx) + return self.Index(w, r) } func (self *SettingsView) SetMyselfIn(r *ext.Router) { diff --git a/pkg/worker/httpserver.go b/pkg/worker/httpserver.go index 181cf73..dc8f255 100644 --- a/pkg/worker/httpserver.go +++ b/pkg/worker/httpserver.go @@ -2,29 +2,24 @@ package worker import ( "context" - - "github.com/valyala/fasthttp" + "net/http" ) type ServerWorker struct { - server *fasthttp.Server + server *http.Server } func (self *ServerWorker) Start(ctx context.Context) error { go func() { // nolint: errcheck - self.server.ListenAndServe("0.0.0.0:8080") + self.server.ListenAndServe() }() <-ctx.Done() - return self.Shutdown() -} - -func (self *ServerWorker) Shutdown() error { - return self.server.Shutdown() + return self.server.Shutdown(ctx) } -func NewServerWorker(server *fasthttp.Server) *ServerWorker { +func NewServerWorker(server *http.Server) *ServerWorker { return &ServerWorker{ server: server, } diff --git a/templates/media.qtpl b/templates/media.qtpl index 6217899..ae58e61 100644 --- a/templates/media.qtpl +++ b/templates/media.qtpl @@ -22,19 +22,19 @@ func (m *MediaPage) PreloadAttr() string { {% for _, media := range p.Medias %}
{% if media.IsVideo() %} -
{% endfor %}
- next + next
{% endfunc %} -- cgit v1.2.3