sliproad/router/router.go
Gabriel Simmer 1ba1a14807
New file regex.
The old regex was hard to parse and maintain, and was broken for some
edge cases. Simplified it greatly and seems to work fine!
2020-04-11 22:43:03 +01:00

99 lines
2.4 KiB
Go

package router
import (
"fmt"
"github.com/gorilla/mux"
"io"
"log"
"net/http"
"os"
"strconv"
)
type Handler func(context *Context, w http.ResponseWriter, r *http.Request) *HTTPError
type HTTPError struct {
Message string
StatusCode int
}
// Context contains any information to be shared with middlewares.
type Context struct {}
func Handle(handlers ...Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
context := &Context{}
for _, handler := range handlers {
err := handler(context, w, r)
if err != nil {
log.Printf("%v", err)
w.Write([]byte(http.StatusText(err.StatusCode)))
return
}
}
})
}
// Actual router, define endpoints here.
func Init() *mux.Router {
r := mux.NewRouter()
// "Static" paths
r.PathPrefix("/javascript/").Handler(http.StripPrefix("/javascript/", http.FileServer(http.Dir("assets/web/javascript"))))
r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(http.Dir("assets/web/css"))))
r.PathPrefix("/icons/").Handler(http.StripPrefix("/icons/", http.FileServer(http.Dir("assets/web/icons"))))
// Paths that require specific handlers
r.Handle("/", Handle(
rootHandler(),
)).Methods("GET")
r.Handle("/api/providers", Handle(
ListProviders(),
)).Methods("GET")
r.Handle(`/api/files/{provider:[a-zA-Z0-9]+\/*}`, Handle(
HandleProvider(),
)).Methods("GET", "POST")
r.Handle(`/api/files/{provider:[a-zA-Z0-9]+}/{file:.+}`, Handle(
HandleProvider(),
)).Methods("GET", "POST")
return r
}
// Handles serving index page.
func rootHandler() Handler {
return func(context *Context, w http.ResponseWriter, r *http.Request) *HTTPError {
f, err := os.Open("assets/web/index.html")
if err != nil {
return &HTTPError{
Message: fmt.Sprintf("error serving index page from assets/web"),
StatusCode: http.StatusInternalServerError,
}
}
defer f.Close()
stats, err := f.Stat()
if err != nil {
return &HTTPError{
Message: fmt.Sprintf("error serving index page from assets/web"),
StatusCode: http.StatusInternalServerError,
}
} else {
w.Header().Add("Content-Length", strconv.FormatInt(stats.Size(), 10))
}
_, err = io.Copy(w, f)
if err != nil {
return &HTTPError{
Message: fmt.Sprintf("error serving index page from assets/web"),
StatusCode: http.StatusInternalServerError,
}
}
return nil
}
}