mirror of
https://git.mills.io/saltyim/saltyim.git
synced 2024-06-16 03:48:24 +00:00
b11d14a274
Co-authored-by: xuu <me@sour.is> Reviewed-on: https://git.mills.io/saltyim/saltyim/pulls/109
162 lines
4.5 KiB
Go
162 lines
4.5 KiB
Go
package internal
|
|
|
|
import (
|
|
"io/fs"
|
|
"net/http"
|
|
|
|
"github.com/julienschmidt/httprouter"
|
|
)
|
|
|
|
// Middleware ...
|
|
type Middleware func(httprouter.Handle) httprouter.Handle
|
|
|
|
// Router ...
|
|
type Router struct {
|
|
httprouter.Router
|
|
|
|
path string
|
|
middlewares []Middleware
|
|
}
|
|
|
|
// NewRouter ...
|
|
func NewRouter() *Router {
|
|
return &Router{
|
|
Router: httprouter.Router{
|
|
RedirectTrailingSlash: true,
|
|
RedirectFixedPath: true,
|
|
HandleMethodNotAllowed: false,
|
|
HandleOPTIONS: true,
|
|
|
|
GlobalOPTIONS: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
|
w.Header().Set("Access-Control-Allow-Headers", "*")
|
|
w.Header().Set("Access-Control-Expose-Headers", "*")
|
|
w.Header().Set("Accept-Encoding", "br, gzip, deflate")
|
|
w.Header().Set("X-Salty-Accept-Encoding", "br, gzip, deflate")
|
|
}),
|
|
},
|
|
}
|
|
}
|
|
|
|
func (r *Router) joinPath(path string) string {
|
|
if (r.path + path)[0] != '/' {
|
|
panic("path should start with '/' in path '" + path + "'.")
|
|
}
|
|
|
|
return r.path + path
|
|
}
|
|
|
|
// Group returns new *Router with given path and middlewares.
|
|
// It should be used for handles which have same path prefix or common middlewares.
|
|
func (r *Router) Group(path string, m ...Middleware) *Router {
|
|
if path[len(path)-1] == '/' {
|
|
path = path[:len(path)-1]
|
|
}
|
|
return &Router{
|
|
Router: r.Router,
|
|
middlewares: append(m, r.middlewares...),
|
|
path: r.joinPath(path),
|
|
}
|
|
}
|
|
|
|
// Use appends new middleware to current Router.
|
|
func (r *Router) Use(m ...Middleware) *Router {
|
|
r.middlewares = append(m, r.middlewares...)
|
|
return r
|
|
}
|
|
|
|
// Handle registers a new request handle combined with middlewares.
|
|
func (r *Router) Handle(method, path string, handle httprouter.Handle) {
|
|
for _, v := range r.middlewares {
|
|
handle = v(handle)
|
|
}
|
|
r.Router.Handle(method, r.joinPath(path), handle)
|
|
}
|
|
|
|
// GET is a shortcut for Router.Handle("GET", path, handle)
|
|
func (r *Router) GET(path string, handle httprouter.Handle) {
|
|
r.Handle("GET", path, handle)
|
|
}
|
|
|
|
// HEAD is a shortcut for Router.Handle("HEAD", path, handle)
|
|
func (r *Router) HEAD(path string, handle httprouter.Handle) {
|
|
r.Handle("HEAD", path, handle)
|
|
}
|
|
|
|
// OPTIONS is a shortcut for Router.Handle("OPTIONS", path, handle)
|
|
func (r *Router) OPTIONS(path string, handle httprouter.Handle) {
|
|
r.Handle("OPTIONS", path, handle)
|
|
}
|
|
|
|
// POST is a shortcut for Router.Handle("POST", path, handle)
|
|
func (r *Router) POST(path string, handle httprouter.Handle) {
|
|
r.Handle("POST", path, handle)
|
|
}
|
|
|
|
// PUT is a shortcut for Router.Handle("PUT", path, handle)
|
|
func (r *Router) PUT(path string, handle httprouter.Handle) {
|
|
r.Handle("PUT", path, handle)
|
|
}
|
|
|
|
// PATCH is a shortcut for Router.Handle("PATCH", path, handle)
|
|
func (r *Router) PATCH(path string, handle httprouter.Handle) {
|
|
r.Handle("PATCH", path, handle)
|
|
}
|
|
|
|
// DELETE is a shortcut for Router.Handle("DELETE", path, handle)
|
|
func (r *Router) DELETE(path string, handle httprouter.Handle) {
|
|
r.Handle("DELETE", path, handle)
|
|
}
|
|
|
|
// Handler is an adapter for http.Handler.
|
|
func (r *Router) Handler(method, path string, handler http.Handler) {
|
|
handle := func(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
|
|
handler.ServeHTTP(w, req)
|
|
}
|
|
r.Handle(method, path, handle)
|
|
}
|
|
|
|
// HandlerFunc is an adapter for http.HandlerFunc.
|
|
func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) {
|
|
r.Handler(method, path, handler)
|
|
}
|
|
|
|
// Static serves files from given root directory.
|
|
func (r *Router) Static(path, root string) {
|
|
if len(path) < 10 || path[len(path)-10:] != "/*filepath" {
|
|
panic("path should end with '/*filepath' in path '" + path + "'.")
|
|
}
|
|
|
|
base := r.joinPath(path[:len(path)-9])
|
|
fileServer := http.StripPrefix(base, http.FileServer(http.Dir(root)))
|
|
|
|
r.Handler("GET", path, fileServer)
|
|
}
|
|
|
|
// File serves the named file.
|
|
func (r *Router) File(path, name string) {
|
|
r.HandlerFunc("GET", path, func(w http.ResponseWriter, req *http.Request) {
|
|
http.ServeFile(w, req, name)
|
|
})
|
|
}
|
|
|
|
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|
r.Router.ServeHTTP(w, req)
|
|
}
|
|
|
|
// ServeFilesWithCacheControl ...
|
|
func (r *Router) ServeFilesWithCacheControl(path string, root fs.FS) {
|
|
if len(path) < 10 || path[len(path)-10:] != "/*filepath" {
|
|
panic("path must end with /*filepath in path '" + path + "'")
|
|
}
|
|
|
|
fileServer := http.FileServer(http.FS(root))
|
|
|
|
r.GET(path, func(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
|
w.Header().Set("Vary", "Accept-Encoding")
|
|
w.Header().Set("Cache-Control", "public, max-age=7776000")
|
|
req.URL.Path = ps.ByName("filepath")
|
|
fileServer.ServeHTTP(w, req)
|
|
})
|
|
}
|