diff options
| author | 2026-05-02 23:49:00 +0700 | |
|---|---|---|
| committer | 2026-05-02 23:49:00 +0700 | |
| commit | d8de4ede8c6a0cc02b9c8c30d68155b1f838254c (patch) | |
| tree | 449701dcf7ac0aafc7f21116b77203d0cc51fc98 /internal/router/router.go | |
| parent | 4c05d4c66827d6e5a131c657ee08293bcde497d1 (diff) | |
| parent | cca3ff72b5e29b31122c0a0496be741e7bc0162b (diff) | |
| download | web-0.14.0.tar.gz web-0.14.0.zip | |
v0.14.0 (#27)v0.14.0
* [feat: migrate to
uz.saya.casa](https://github.com/SayaAndy/saya-today-web/commit/d3a63ca8a84bf4583bac8f5fd09bd52774bc4158)
* [feat: overhaul the design of blog
catalog](https://github.com/SayaAndy/saya-today-web/commit/99294b260661a8d3f6992404de7881945eab837b)
* [feat: replace font-andika with M PLUS and Gentium
Plus](https://github.com/SayaAndy/saya-today-web/commit/b1355436e96f2dfa777e843b53896d0bb71628e3)
* [feat: use yandexcloud.kz for photos &
static](https://github.com/SayaAndy/saya-today-web/commit/3898baa47faf268864ecac3699f7e98c6cac01a4)
* [feat: move from b2 to s3 for blog pages &
facts](https://github.com/SayaAndy/saya-today-web/commit/3efa6ed24713658af855c0ca9504f3e089342182)
* [feat: support s3 for blog
pages](https://github.com/SayaAndy/saya-today-web/commit/66b2a96fcca113105043be3cb9c49f8ee7fe240c)
* [feat: use accent colors for glightbox
tooltip](https://github.com/SayaAndy/saya-today-web/commit/81a9147c5406e3b2f2441373b935d7c5de2780da)
* [fix: set sidecar onclick attribute correctly in
update](https://github.com/SayaAndy/saya-today-web/commit/941bd3b3f3e26ca62757a34a20bc9b323be02a74)
* [fix: set cache-control for non-cacheable
pages](https://github.com/SayaAndy/saya-today-web/commit/78d6b00cd973e4254ea13cbb17bb35a30fef51b9)
* [feat: update font-awesome 6.7.2 to
7.2.0](https://github.com/SayaAndy/saya-today-web/commit/5e64aa9db2796e8aa6267d2ed9179ea01dc6561b)
* [fix: remove leading slash in path with going
up](https://github.com/SayaAndy/saya-today-web/commit/13428b467f752d9b53b39a3c8122998f1896ed1e)
* [feat: implement rate
limiting](https://github.com/SayaAndy/saya-today-web/commit/ca1f36376865cb2a20923aa62fdff3ee217abde3)
* [feat: integrate unix sockets into stage &
prod](https://github.com/SayaAndy/saya-today-web/commit/507bcbac6b1bf9f1a731afbe82bec10700f4028c)
* [feat: compact & move new fonts into
yandexcloud.kz](https://github.com/SayaAndy/saya-today-web/pull/27/commits/cca3ff72b5e29b31122c0a0496be741e7bc0162b)
* [feat: update all github actions, golang dependencies, golang to 1.26,
alpine to
3.23](https://github.com/SayaAndy/saya-today-web/commit/a3aa1dd07abfbbb27a7dfeeb536a6fcc51709256)
* [refactor: simpler frontmatter parser (replace regexp with bytes
pkg)](https://github.com/SayaAndy/saya-today-web/commit/42bf9d8e7f459f9021fb6fb389d3b51fed5edc35)
* [feat: allow some api methods + disallow user pages for
bots](https://github.com/SayaAndy/saya-today-web/commit/e3c80a07514a052adafd5c0f51daf69b664530e0)
Diffstat (limited to 'internal/router/router.go')
| -rw-r--r-- | internal/router/router.go | 93 |
1 files changed, 68 insertions, 25 deletions
diff --git a/internal/router/router.go b/internal/router/router.go index 3242759..65e35a4 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -7,13 +7,16 @@ import ( "fmt" "html/template" "log/slog" + "net" "net/url" + "os" "slices" + "strconv" "strings" "time" "github.com/SayaAndy/saya-today-web/config" - "github.com/SayaAndy/saya-today-web/internal/b2" + "github.com/SayaAndy/saya-today-web/internal/blog" "github.com/SayaAndy/saya-today-web/internal/blogtrigger" "github.com/SayaAndy/saya-today-web/internal/factgiver" "github.com/SayaAndy/saya-today-web/internal/glightbox" @@ -78,6 +81,7 @@ type Route interface { TemplatesToInject() []string SitemapInfo(supplements *Supplements) []SitemapInfo ContentType() string + RateLimiter() *fiber.Handler Render(c *fiber.Ctx, supplements *Supplements, lang string, templateMap fiber.Map) (statusCode int, err error) AddMeta(c *fiber.Ctx, supplements *Supplements, lang string, templateMap fiber.Map) (meta []MetaField, err error) AddLinkedData(c *fiber.Ctx, supplements *Supplements, lang string, templateMap fiber.Map) (ld map[string]any, err error) @@ -90,7 +94,7 @@ type Route interface { type Supplements struct { DB *sql.DB - B2Client *b2.B2Client + BlogClient blog.Client Localization map[string]*locale.LocaleConfig AvailableLanguages []config.AvailableLanguageConfig ClientCache *ClientCache @@ -101,6 +105,8 @@ type Supplements struct { TemplateManager *templatemanager.TemplateManager MarkdownRenderer goldmark.Markdown Meta config.MetaConfig + PhotoStorage config.PhotoStorageConfig + StaticStorage config.PhotoTypeConfig } type Router struct { @@ -109,6 +115,7 @@ type Router struct { templatedRoutes map[string]map[string]Route templatedPathMatcher *PathMatcher canonicalEndpoint string + endpoint config.EndpointConfig } func NewRouter(cfg *config.Config) (*Router, error) { @@ -140,7 +147,7 @@ func NewRouter(cfg *config.Config) (*Router, error) { } slog.Debug("successfully applied migrations") - supplements.B2Client, err = b2.NewB2Client(&cfg.BlogPages.Storage.Config) + supplements.BlogClient, err = blog.NewClientMap[cfg.BlogPages.Storage.Type](&cfg.BlogPages.Storage) if err != nil { return nil, fmt.Errorf("fail to initialize b2 client: %w", err) } @@ -156,7 +163,7 @@ func NewRouter(cfg *config.Config) (*Router, error) { supplements.MarkdownRenderer = goldmark.New( goldmark.WithExtensions( - glightbox.NewGLightboxExtension(), + glightbox.NewGLightboxExtension(cfg.PhotoStorage), tailwind.NewTailwindExtension(), ), goldmark.WithParserOptions( @@ -198,8 +205,8 @@ func NewRouter(cfg *config.Config) (*Router, error) { return nil, fmt.Errorf("fail to initialize mailer: %w", err) } - supplements.BlogTrigger, err = blogtrigger.NewBlogTriggerScheduler(supplements.B2Client, cfg.AvailableLanguages, cfg.Mail.Trigger.OnNewPost, - func(bp []*b2.BlogPage) error { + supplements.BlogTrigger, err = blogtrigger.NewBlogTriggerScheduler(supplements.BlogClient, cfg.AvailableLanguages, cfg.Mail.Trigger.OnNewPost, + func(bp []*blog.Page) error { for _, post := range bp { if err := supplements.Mailer.NewPost(post); err != nil { return err @@ -217,6 +224,8 @@ func NewRouter(cfg *config.Config) (*Router, error) { } supplements.Meta = cfg.Meta + supplements.PhotoStorage = cfg.PhotoStorage + supplements.StaticStorage = cfg.StaticStorage enablePrintRoutes := false if cfg.LogLevel <= slog.LevelDebug { @@ -229,7 +238,7 @@ func NewRouter(cfg *config.Config) (*Router, error) { }) app.Use(cors.New(cors.Config{ - AllowOrigins: "https://f003.backblazeb2.com", + AllowOrigins: strings.Join(cfg.AllowOrigins, ","), AllowMethods: "GET,POST,OPTIONS", AllowHeaders: "Origin, Content-Type, Accept", })) @@ -251,7 +260,7 @@ func NewRouter(cfg *config.Config) (*Router, error) { templatedRoutes := make(map[string]map[string]Route) templatedPathMatcher := NewPathMatcher() - return &Router{supplements, app, templatedRoutes, templatedPathMatcher, cfg.CanonicalEndpoint}, nil + return &Router{supplements, app, templatedRoutes, templatedPathMatcher, cfg.CanonicalEndpoint, cfg.Endpoint}, nil } func (r *Router) InitRoutes() (err error) { @@ -263,6 +272,10 @@ func (r *Router) InitRoutes() (err error) { return fmt.Errorf("failed to add '%s %s' route into template manager: %w", method, match, err) } + if rateLimiter := route.RateLimiter(); rateLimiter != nil { + r.app.Use(match, *rateLimiter) + } + if route.IsTemplated() { if _, ok := r.templatedRoutes[method]; !ok { r.templatedRoutes[method] = make(map[string]Route) @@ -296,14 +309,18 @@ func (r *Router) InitRoutes() (err error) { cacheKey = fmt.Sprintf("%s.full-page.%s", method, trimmedPath) case ByUrlAndQuery: cacheKey = fmt.Sprintf("%s.full-page.%s.%s", method, trimmedPath, queryString) + case Disabled: + c.Set("Cache-Control", "no-store, no-cache, must-revalidate") } defaultMap := fiber.Map{ - "L": r.supplements.Localization[lang], - "Lang": lang, - "Path": trimmedPath, - "QueryString": queryString, - "CanonicalEndpoint": r.canonicalEndpoint, + "L": r.supplements.Localization[lang], + "Lang": lang, + "Path": trimmedPath, + "QueryString": queryString, + "CanonicalEndpoint": r.canonicalEndpoint, + "StaticStorageBaseUrl": r.supplements.StaticStorage.BaseUrl, + "ThumbnailBaseUrl": r.supplements.PhotoStorage.Thumbnail320p.BaseUrl, } statusCode, err := currentRoute.Render(c, r.supplements, lang, defaultMap) @@ -356,6 +373,7 @@ func (r *Router) InitRoutes() (err error) { c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8) return c.Status(fiber.ErrBadRequest.Code).SendString(fmt.Sprintf("unknown segment '%s'", part)) } + c.Set("Cache-Control", "no-store, no-cache, must-revalidate") err := r.generalPageSegment(c, part) return err }) @@ -371,10 +389,30 @@ func (r *Router) InitRoutes() (err error) { return nil } -func (r *Router) Listen(endpoint string) error { - if err := r.app.Listen(endpoint); err != nil { - return fmt.Errorf("error while running fiber server: %w", err) +func (r *Router) Listen() error { + switch r.endpoint.Type { + case "unix": + unixConfig := r.endpoint.Config.(*config.UnixConfig) + endpoint, _ := strings.CutPrefix(unixConfig.Path, "unix://") + ln, err := net.Listen("unix", endpoint) + if err != nil { + return fmt.Errorf("error while initializing unix listener: %w", err) + } + chmod, _ := strconv.ParseUint(unixConfig.Chmod[1:], 8, 32) + os.Chmod(unixConfig.Path, os.FileMode(chmod)) + if err := r.app.Listener(ln); err != nil { + return fmt.Errorf("error while running fiber server: %w", err) + } + case "http": + httpConfig := r.endpoint.Config.(*config.HttpConfig) + fmt.Print(httpConfig) + if err := r.app.Listen(httpConfig.ListenOn); err != nil { + return fmt.Errorf("error while running fiber server: %w", err) + } + default: + return fmt.Errorf("error with initializing fiber server: invalid endpoint type (supported are unix and http)") } + return nil } @@ -398,6 +436,7 @@ func (r *Router) Close() (err error) { } slog.Debug("closing page cache") r.supplements.PageCache.Close() + return errors.Join(allErrors...) } @@ -423,10 +462,12 @@ func (r *Router) generalPage(c *fiber.Ctx, route Route, lang string) error { } valueMap := fiber.Map{ - "L": r.supplements.Localization[lang], - "Lang": lang, - "QueryString": queryString, - "CanonicalEndpoint": r.canonicalEndpoint, + "L": r.supplements.Localization[lang], + "Lang": lang, + "QueryString": queryString, + "CanonicalEndpoint": r.canonicalEndpoint, + "StaticStorageBaseUrl": r.supplements.StaticStorage.BaseUrl, + "ThumbnailBaseUrl": r.supplements.PhotoStorage.Thumbnail320p.BaseUrl, } var err error @@ -503,11 +544,13 @@ func (r *Router) generalPageSegment(c *fiber.Ctx, part string) error { var statusCode int defaultMap := fiber.Map{ - "L": r.supplements.Localization[lang], - "Lang": lang, - "Path": strings.Trim(path, "/"), - "QueryString": queryString, - "CanonicalEndpoint": r.canonicalEndpoint, + "L": r.supplements.Localization[lang], + "Lang": lang, + "Path": strings.Trim(path, "/"), + "QueryString": queryString, + "CanonicalEndpoint": r.canonicalEndpoint, + "StaticStorageBaseUrl": r.supplements.StaticStorage.BaseUrl, + "ThumbnailBaseUrl": r.supplements.PhotoStorage.Thumbnail320p.BaseUrl, } switch part { |