1
0
mirror of https://github.com/lus/pasty.git synced 2023-08-10 21:13:09 +03:00
pasty/internal/web/web.go

104 lines
2.9 KiB
Go
Raw Normal View History

package web
import (
2020-08-23 17:22:20 +03:00
"encoding/json"
2021-04-15 20:26:17 +03:00
"path/filepath"
"strings"
routing "github.com/fasthttp/router"
2021-04-15 21:15:42 +03:00
"github.com/lus/pasty/internal/config"
2021-04-15 20:26:17 +03:00
"github.com/lus/pasty/internal/static"
v1 "github.com/lus/pasty/internal/web/controllers/v1"
2020-08-24 00:07:07 +03:00
"github.com/ulule/limiter/v3"
limitFasthttp "github.com/ulule/limiter/v3/drivers/middleware/fasthttp"
"github.com/ulule/limiter/v3/drivers/store/memory"
"github.com/valyala/fasthttp"
)
2020-08-23 17:44:06 +03:00
// Serve serves the web resources
func Serve() error {
// Create the router
router := routing.New()
2020-08-23 15:13:17 +03:00
// Define the 404 handler
router.NotFound = func(ctx *fasthttp.RequestCtx) {
ctx.SetStatusCode(fasthttp.StatusNotFound)
ctx.SetBodyString("not found")
}
// Route the frontend requests
frontend := frontendHandler()
router.GET("/{path:*}", func(ctx *fasthttp.RequestCtx) {
path := string(ctx.Path())
2020-08-24 19:32:14 +03:00
if !strings.HasPrefix(path, "/api") && (strings.Count(path, "/") == 1 || strings.HasPrefix(path, "/assets")) {
if strings.HasPrefix(path, "/assets/js/") {
ctx.SetContentType("text/javascript")
}
2020-08-23 15:13:17 +03:00
frontend(ctx)
return
}
router.NotFound(ctx)
})
2020-08-24 00:07:07 +03:00
// Set up the rate limiter
2021-04-15 21:15:42 +03:00
rate, err := limiter.NewRateFromFormatted(config.Current.RateLimit)
2020-08-24 00:07:07 +03:00
if err != nil {
return err
}
rateLimiter := limiter.New(memory.NewStore(), rate)
rateLimiterMiddleware := limitFasthttp.NewMiddleware(rateLimiter)
// Route the API endpoints
apiRoute := router.Group("/api")
{
v1Route := apiRoute.Group("/v1")
{
2020-08-23 17:40:06 +03:00
v1Route.GET("/info", func(ctx *fasthttp.RequestCtx) {
jsonData, _ := json.Marshal(map[string]interface{}{
"version": static.Version,
"deletionTokens": config.Current.DeletionTokens,
2020-08-23 17:40:06 +03:00
})
ctx.SetBody(jsonData)
})
2020-08-24 00:07:07 +03:00
v1.InitializePastesController(v1Route.Group("/pastes"), rateLimiterMiddleware)
}
}
2020-08-23 17:22:20 +03:00
// Route the hastebin documents route if hastebin support is enabled
2021-04-15 21:15:42 +03:00
if config.Current.HastebinSupport {
2020-08-24 00:07:07 +03:00
router.POST("/documents", rateLimiterMiddleware.Handle(v1.HastebinSupportHandler))
2020-08-23 17:22:20 +03:00
}
2020-08-23 17:44:06 +03:00
// Serve the web resources
2020-08-23 15:13:17 +03:00
return (&fasthttp.Server{
2020-08-23 21:29:18 +03:00
Handler: func(ctx *fasthttp.RequestCtx) {
// Add the CORS headers
ctx.Response.Header.Set("Access-Control-Allow-Methods", "GET,POST,DELETE,OPTIONS")
ctx.Response.Header.Set("Access-Control-Allow-Origin", "*")
// Call the router handler
router.Handler(ctx)
},
Logger: new(nilLogger),
2021-04-15 21:15:42 +03:00
}).ListenAndServe(config.Current.WebAddress)
2020-08-23 15:13:17 +03:00
}
// frontendHandler handles the frontend routing
func frontendHandler() fasthttp.RequestHandler {
// Create the file server
fs := &fasthttp.FS{
Root: "./web",
IndexNames: []string{"index.html"},
CacheDuration: 0,
}
fs.PathNotFound = func(ctx *fasthttp.RequestCtx) {
2020-08-24 19:32:14 +03:00
if strings.HasPrefix(string(ctx.Path()), "/assets") {
ctx.SetStatusCode(fasthttp.StatusNotFound)
ctx.SetBodyString("not found")
return
}
2020-08-23 15:13:17 +03:00
ctx.SendFile(filepath.Join(fs.Root, "index.html"))
}
return fs.NewRequestHandler()
}