diff --git a/main.go b/main.go index e3e36a7..24ab8f1 100644 --- a/main.go +++ b/main.go @@ -52,14 +52,7 @@ func main() { code = e.Code } - err = ctx.Status(code).Render("errors/error", fiber.Map{ - "err": err, - }) - if err != nil { - return ctx.Status(fiber.StatusInternalServerError).SendString("Internal Server Error") - } - - return nil + return utils.RenderError(ctx, code) }, }) @@ -77,14 +70,23 @@ func main() { app.Get("/errors/429", func(c *fiber.Ctx) error { return c.Render("errors/429", nil) }) + app.Get("/errors/429/img", func(c *fiber.Ctx) error { + return c.Redirect("/static/img/error-429.png") + }) app.Get("/errors/404", func(c *fiber.Ctx) error { return c.Render("errors/404", nil) }) + app.Get("/errors/404/img", func(c *fiber.Ctx) error { + return c.Redirect("/static/img/error-404.png") + }) app.Get("/errors/error", func(c *fiber.Ctx) error { return c.Render("errors/error", fiber.Map{ "err": "Test error", }) }) + app.Get("/errors/error/img", func(c *fiber.Ctx) error { + return c.Redirect("/static/img/error-generic.png") + }) } else { app.Use("/static", filesystem.New(filesystem.Config{ MaxAge: 2592000, diff --git a/pages/embed.go b/pages/embed.go index d48844d..bf25e8b 100644 --- a/pages/embed.go +++ b/pages/embed.go @@ -23,10 +23,10 @@ func HandleEmbed(c *fiber.Ctx) error { post, err = ApiClient.FetchMedia(c.Params("postID")) } if err != nil && err.Error() == "ratelimited by imgur" { - return c.Status(429).Render("errors/429", nil) + return utils.RenderError(c, 429) } if err != nil && post.Id == "" && strings.Contains(err.Error(), "404") { - return c.Status(404).Render("errors/404", nil) + return utils.RenderError(c, 404) } if err != nil { return err diff --git a/pages/media.go b/pages/media.go index 34208db..1e9df14 100644 --- a/pages/media.go +++ b/pages/media.go @@ -11,22 +11,25 @@ import ( func HandleMedia(c *fiber.Ctx) error { c.Set("Cache-Control", "public,max-age=31557600") + c.Set("Content-Security-Policy", "default-src 'none'; style-src 'self'; img-src 'self'") if strings.HasPrefix(c.Path(), "/stack") { - return handleMedia(c, "https://i.stack.imgur.com/" + strings.ReplaceAll(c.Params("baseName"), "stack/", "") + "." + c.Params("extension")) + return handleMedia(c, "https://i.stack.imgur.com/"+strings.ReplaceAll(c.Params("baseName"), "stack/", "")+"."+c.Params("extension")) } else { - return handleMedia(c, "https://i.imgur.com/" + c.Params("baseName") + "." + c.Params("extension")) + return handleMedia(c, "https://i.imgur.com/"+c.Params("baseName")+"."+c.Params("extension")) } } func HandleUserCover(c *fiber.Ctx) error { c.Set("Cache-Control", "public,max-age=604800") - return handleMedia(c, "https://imgur.com/user/" + c.Params("userID") + "/cover?maxwidth=2560") -}; + c.Set("Content-Security-Policy", "default-src 'none'") + return handleMedia(c, "https://imgur.com/user/"+c.Params("userID")+"/cover?maxwidth=2560") +} func HandleUserAvatar(c *fiber.Ctx) error { c.Set("Cache-Control", "public,max-age=604800") - return handleMedia(c, "https://imgur.com/user/" + c.Params("userID") + "/avatar") -}; + c.Set("Content-Security-Policy", "default-src 'none'") + return handleMedia(c, "https://imgur.com/user/"+c.Params("userID")+"/avatar") +} func handleMedia(c *fiber.Ctx, url string) error { utils.SetHeaders(c) @@ -45,7 +48,7 @@ func handleMedia(c *fiber.Ctx, url string) error { if err != nil { return err } - + utils.SetReqHeaders(req) if c.Get("Range") != "" { @@ -57,23 +60,18 @@ func handleMedia(c *fiber.Ctx, url string) error { return err } - c.Status(res.StatusCode) - if res.StatusCode == 404 { - return c.Render("errors/404", fiber.Map{ - "path": c.Path(), - }) + if res.StatusCode == 404 || strings.Contains(res.Request.URL.String(), "error/404") { + return utils.RenderError(c, 404) } else if res.StatusCode == 429 { - return c.Render("errors/429", fiber.Map{ - "path": c.Path(), - }) + return utils.RenderError(c, 429) } - + c.Set("Accept-Ranges", "bytes") - c.Set("Content-Type", res.Header.Get("Content-Type")); + c.Set("Content-Type", res.Header.Get("Content-Type")) c.Set("Content-Length", res.Header.Get("Content-Length")) if res.Header.Get("Content-Range") != "" { c.Set("Content-Range", res.Header.Get("Content-Range")) } - + return c.SendStream(res.Body) -} \ No newline at end of file +} diff --git a/pages/post.go b/pages/post.go index 7a876e4..cfa8b47 100644 --- a/pages/post.go +++ b/pages/post.go @@ -26,14 +26,12 @@ func HandlePost(c *fiber.Ctx) error { post, err = ApiClient.FetchMedia(c.Params("postID")) } if err != nil && err.Error() == "ratelimited by imgur" { - return c.Status(429).Render("errors/429", fiber.Map{ - "path": c.Path(), - }) + return utils.RenderError(c, 429) } if err != nil && post.Id == "" && strings.Contains(err.Error(), "404") { - return c.Status(404).Render("errors/404", nil) + return utils.RenderError(c, 404) } - if err != nil { + if err != nil { return err } diff --git a/pages/privacy.go b/pages/privacy.go index 2d7851b..c2591e9 100644 --- a/pages/privacy.go +++ b/pages/privacy.go @@ -9,6 +9,7 @@ import ( func HandlePrivacy(c *fiber.Ctx) error { utils.SetHeaders(c) c.Set("X-Frame-Options", "DENY") + c.Set("Content-Security-Policy", "default-src 'none'; form-action 'self'; style-src 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content") return c.Render("privacy", fiber.Map{ "config": utils.Config, diff --git a/pages/tag.go b/pages/tag.go index de086ec..145ef49 100644 --- a/pages/tag.go +++ b/pages/tag.go @@ -25,21 +25,19 @@ func HandleTag(c *fiber.Ctx) error { tag, err := ApiClient.FetchTag(c.Params("tag"), c.Query("sort"), page) if err != nil && err.Error() == "ratelimited by imgur" { - return c.Status(429).Render("errors/429", fiber.Map{ - "path": c.Path(), - }) + return utils.RenderError(c, 429) } if err != nil { return err } if tag.Display == "" { - return c.Status(404).Render("errors/404", nil) + return utils.RenderError(c, 404) } return c.Render("tag", fiber.Map{ - "tag": tag, - "page": page, - "nextPage": pageNumber + 1, - "prevPage": pageNumber - 1, + "tag": tag, + "page": page, + "nextPage": pageNumber + 1, + "prevPage": pageNumber - 1, }) } diff --git a/pages/user.go b/pages/user.go index 42da651..3a07e57 100644 --- a/pages/user.go +++ b/pages/user.go @@ -25,23 +25,19 @@ func HandleUser(c *fiber.Ctx) error { user, err := ApiClient.FetchUser(c.Params("userID")) if err != nil && err.Error() == "ratelimited by imgur" { - return c.Status(429).Render("errors/429", fiber.Map{ - "path": c.Path(), - }) + return utils.RenderError(c, 429) } if err != nil { return err } if user.Username == "" { - return c.Status(404).Render("errors/404", nil) + return utils.RenderError(c, 404) } submissions, err := ApiClient.FetchSubmissions(c.Params("userID"), "newest", page) if err != nil && err.Error() == "ratelimited by imgur" { c.Status(429) - return c.Render("errors/429", fiber.Map{ - "path": c.Path(), - }) + return utils.RenderError(c, 429) } if err != nil { return err @@ -64,23 +60,19 @@ func HandleUserComments(c *fiber.Ctx) error { user, err := ApiClient.FetchUser(c.Params("userID")) if err != nil && err.Error() == "ratelimited by imgur" { - return c.Status(429).Render("errors/429", fiber.Map{ - "path": c.Path(), - }) + return utils.RenderError(c, 429) } if err != nil { return err } if user.Username == "" { - return c.Status(404).Render("errors/404", nil) + return utils.RenderError(c, 404) } comments, err := ApiClient.FetchUserComments(c.Params("userID")) if err != nil && err.Error() == "ratelimited by imgur" { c.Status(429) - return c.Render("errors/429", fiber.Map{ - "path": c.Path(), - }) + return utils.RenderError(c, 429) } if err != nil { return err @@ -110,23 +102,18 @@ func HandleUserFavorites(c *fiber.Ctx) error { user, err := ApiClient.FetchUser(c.Params("userID")) if err != nil && err.Error() == "ratelimited by imgur" { - return c.Status(429).Render("errors/429", fiber.Map{ - "path": c.Path(), - }) + return utils.RenderError(c, 429) } if err != nil { return err } if user.Username == "" { - return c.Status(404).Render("errors/404", nil) + return utils.RenderError(c, 404) } favorites, err := ApiClient.FetchUserFavorites(c.Params("userID"), "newest", page) if err != nil && err.Error() == "ratelimited by imgur" { - c.Status(429) - return c.Render("errors/429", fiber.Map{ - "path": c.Path(), - }) + return utils.RenderError(c, 429) } if err != nil { return err diff --git a/static/img/error-404.png b/static/img/error-404.png new file mode 100644 index 0000000..4cfa417 Binary files /dev/null and b/static/img/error-404.png differ diff --git a/static/img/error-429.png b/static/img/error-429.png new file mode 100644 index 0000000..c8eba31 Binary files /dev/null and b/static/img/error-429.png differ diff --git a/static/img/error-generic.png b/static/img/error-generic.png new file mode 100644 index 0000000..869ddb8 Binary files /dev/null and b/static/img/error-generic.png differ diff --git a/utils/error.go b/utils/error.go new file mode 100644 index 0000000..6e4c334 --- /dev/null +++ b/utils/error.go @@ -0,0 +1,25 @@ +package utils + +import ( + "strconv" + "strings" + + "codeberg.org/rimgo/rimgo/static" + "github.com/gofiber/fiber/v2" +) + +func RenderError(c *fiber.Ctx, code int) error { + if !strings.Contains(c.Get("Accept"), "html") { + codeStr := "generic" + if code != 0 { + codeStr = strconv.Itoa(code) + } + img, _ := static.GetFiles().ReadFile("img/error-" + codeStr + ".png") + c.Set("Content-Type", "image/png") + return c.Status(code).Send(img) + } else { + return c.Status(code).Render("errors/" + strconv.Itoa(code), fiber.Map{ + "path": c.Path(), + }) + } +} \ No newline at end of file