diff options
| author | Gabriel Arakaki Giovanini <mail@gabrielgio.me> | 2023-08-05 19:26:29 +0200 | 
|---|---|---|
| committer | Gabriel Arakaki Giovanini <mail@gabrielgio.me> | 2023-08-05 19:26:29 +0200 | 
| commit | 5168a9476f0e83264ecafc85bc9145e8bdcbb8dc (patch) | |
| tree | 5cd04e84f8aa427d274e16dd8cf507ff48468e07 | |
| parent | 24c121a9ef229870f54de487de01c15a15ebbff1 (diff) | |
| download | lens-5168a9476f0e83264ecafc85bc9145e8bdcbb8dc.tar.gz lens-5168a9476f0e83264ecafc85bc9145e8bdcbb8dc.tar.bz2 lens-5168a9476f0e83264ecafc85bc9145e8bdcbb8dc.zip  | |
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.
| -rw-r--r-- | cmd/server/main.go | 10 | ||||
| -rw-r--r-- | go.mod | 6 | ||||
| -rw-r--r-- | go.sum | 12 | ||||
| -rw-r--r-- | pkg/ext/fileserver.go | 33 | ||||
| -rw-r--r-- | pkg/ext/middleware.go | 74 | ||||
| -rw-r--r-- | pkg/ext/responses.go | 30 | ||||
| -rw-r--r-- | pkg/ext/router.go | 45 | ||||
| -rw-r--r-- | pkg/view/auth.go | 77 | ||||
| -rw-r--r-- | pkg/view/filesystem.go | 16 | ||||
| -rw-r--r-- | pkg/view/media.go | 53 | ||||
| -rw-r--r-- | pkg/view/settings.go | 57 | ||||
| -rw-r--r-- | pkg/worker/httpserver.go | 15 | ||||
| -rw-r--r-- | templates/media.qtpl | 8 | 
13 files changed, 186 insertions, 250 deletions
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, @@ -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 @@ -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 %}      <div class="card-image">         {% if media.IsVideo() %} -       <video class="image is-fit" controls muted="true" poster="/media/thumbnail?path_hash={%s media.PathHash %}" preload="{%s p.PreloadAttr() %}"> -           <source src="/media/image?path_hash={%s media.PathHash %}" type="{%s media.MIMEType %}"> +       <video class="image is-fit" controls muted="true" poster="/media/thumbnail/?path_hash={%s media.PathHash %}" preload="{%s p.PreloadAttr() %}"> +           <source src="/media/image/?path_hash={%s media.PathHash %}" type="{%s media.MIMEType %}">         </video>         {% else %}          <figure class="image is-fit"> -            <img src="/media/thumbnail?path_hash={%s media.PathHash %}"> +            <img src="/media/thumbnail/?path_hash={%s media.PathHash %}">          </figure>          {% endif %}      </div>  {% endfor %}  </div>  <div class="row"> -    <a href="/media?page={%d p.Next.Page %}" class="button is-pulled-right">next</a> +    <a href="/media/?page={%d p.Next.Page %}" class="button is-pulled-right">next</a>  </div>  {% endfunc %}  | 
