Clean API request paths

This commit is contained in:
Daniel 2021-03-10 11:44:29 +01:00
parent d4ae90e1ba
commit 4a05c26339

View file

@ -4,6 +4,8 @@ import (
"context"
"errors"
"net/http"
"path"
"strings"
"sync"
"time"
@ -53,7 +55,7 @@ func Serve() {
return server.ListenAndServe()
})
// return on shutdown error
if err == http.ErrServerClosed {
if errors.Is(err, http.ErrServerClosed) {
return
}
// log error and restart
@ -94,6 +96,17 @@ func (mh *mainHandler) handle(w http.ResponseWriter, r *http.Request) error {
tracer.Submit()
}()
// Clean URL.
cleanedRequestPath := cleanRequestPath(r.URL.Path)
// If the cleaned URL differs from the original one, redirect to there.
if r.URL.Path != cleanedRequestPath {
redirURL := *r.URL
redirURL.Path = cleanedRequestPath
http.Redirect(lrw, r, redirURL.String(), http.StatusMovedPermanently)
return nil
}
// Get handler for request.
// Gorilla does not support handling this on our own very well.
// See github.com/gorilla/mux.ServeHTTP for reference.
@ -145,3 +158,25 @@ func (mh *mainHandler) handle(w http.ResponseWriter, r *http.Request) error {
return nil
}
// cleanRequestPath cleans and returns a request URL.
func cleanRequestPath(requestPath string) string {
// If the request URL is empty, return a request for "root".
if requestPath == "" || requestPath == "/" {
return "/"
}
// If the request URL does not start with a slash, prepend it.
if !strings.HasPrefix(requestPath, "/") {
requestPath = "/" + requestPath
}
// Clean path to remove any relative parts.
cleanedRequestPath := path.Clean(requestPath)
// Because path.Clean removes a trailing slash, we need to add it back here
// if the original URL had one.
if strings.HasSuffix(requestPath, "/") {
cleanedRequestPath += "/"
}
return cleanedRequestPath
}