package pages import ( "io" "mime" "net/http" "strings" "codeberg.org/rimgo/rimgo/utils" ) func HandleMedia(w http.ResponseWriter, r *http.Request) error { w.Header().Set("Cache-Control", "public,max-age=31557600") w.Header().Set("Content-Security-Policy", "default-src 'none'; style-src 'self'; img-src 'self'") splitName := strings.SplitN(r.PathValue("component"), ".", 2) baseName, extension := splitName[0], splitName[1] if strings.HasPrefix(r.URL.Path, "/stack") { return handleMedia(w, r, "https://i.stack.imgur.com/"+strings.ReplaceAll(baseName, "stack/", "")+"."+extension) } else { return handleMedia(w, r, "https://i.imgur.com/"+baseName+"."+extension) } } func HandleUserCover(w http.ResponseWriter, r *http.Request) error { w.Header().Set("Cache-Control", "public,max-age=604800") w.Header().Set("Content-Security-Policy", "default-src 'none'") return handleMedia(w, r, "https://imgur.com/user/"+r.PathValue("userID")+"/cover?maxwidth=2560") } func HandleUserAvatar(w http.ResponseWriter, r *http.Request) error { w.Header().Set("Cache-Control", "public,max-age=604800") w.Header().Set("Content-Security-Policy", "default-src 'none'") return handleMedia(w, r, "https://imgur.com/user/"+r.PathValue("userID")+"/avatar") } func handleMedia(w http.ResponseWriter, r *http.Request, url string) error { utils.SetHeaders(w) path := r.URL.Path if utils.Config.ForceWebp && !strings.HasSuffix(path, ".webp") && r.Header.Get("Sec-Fetch-Dest") == "image" && r.URL.Query().Get("no_webp") == "" && utils.Accepts(r, "image/webp") && !strings.HasPrefix(path, "/stack") { url = strings.ReplaceAll(url, ".png", ".webp") url = strings.ReplaceAll(url, ".jpg", ".webp") url = strings.ReplaceAll(url, ".jpeg", ".webp") filename := strings.TrimPrefix(path, "/") w.Header().Set("Content-Disposition", mime.FormatMediaType("attachment", map[string]string{"filename*": filename})) } queryStr := r.URL.Query().Encode() if strings.HasPrefix(path, "/stack") && queryStr != "" { url = url + "?" + queryStr } req, err := http.NewRequest("GET", url, nil) if err != nil { return err } utils.SetReqHeaders(req) rng := r.URL.Query().Get("Range") if rng != "" { req.Header.Set("Range", rng) } res, err := http.DefaultClient.Do(req) if err != nil { return err } if res.StatusCode == 404 || strings.Contains(res.Request.URL.String(), "error/404") { return RenderError(w, r, 404) } else if res.StatusCode == 429 { return RenderError(w, r, 429) } w.Header().Set("Accept-Ranges", "bytes") w.Header().Set("Content-Type", res.Header.Get("Content-Type")) w.Header().Set("Content-Length", res.Header.Get("Content-Length")) if res.Header.Get("Content-Range") != "" { w.Header().Set("Content-Range", res.Header.Get("Content-Range")) } _, err = io.Copy(w, res.Body) return err }