Files

97 lines
2.3 KiB
Go
Raw Permalink Normal View History

2024-06-11 16:31:51 -03:00
package api
import (
"bytes"
"errors"
"image"
2024-06-11 16:31:51 -03:00
"io"
"net/http"
"net/url"
"strconv"
"www/internals"
"github.com/chai2010/webp"
"github.com/sunshineplan/imgconv"
2024-06-11 16:31:51 -03:00
)
func ImgOptimize(i image.Image, threshold int) image.Image {
w := i.Bounds().Max.X
if threshold >= w {
return i
}
d := w / threshold
return imgconv.Resize(i, &imgconv.ResizeOption{Width: w / d})
}
2024-06-11 16:31:51 -03:00
func Image(w http.ResponseWriter, r *http.Request) {
error := internals.HttpErrorHelper(w)
2024-06-11 16:31:51 -03:00
params, err := url.ParseQuery(r.URL.RawQuery)
if error("Error trying to parse query parameters", err, http.StatusInternalServerError) {
2024-06-11 16:31:51 -03:00
return
}
if _, some := params["url"]; !some {
error("\"url\" parameter missing", errors.New("Missing argument"), http.StatusBadRequest)
return
}
u, err := url.Parse(params.Get("url"))
if error("\"url\" is not a valid URL string", err, http.StatusBadRequest) {
2024-06-11 16:31:51 -03:00
return
}
if u.Hostname() == "" {
if r.URL.Scheme == "" {
u.Scheme = "https"
2024-06-11 16:31:51 -03:00
} else {
u.Scheme = r.URL.Scheme
2024-06-11 16:31:51 -03:00
}
2024-06-12 16:15:23 -03:00
u.Host = r.Host
2024-06-11 16:31:51 -03:00
}
if _, some := params["threshold"]; !some {
error("\"threshold\" parameter missing", errors.New("Missing argument"), http.StatusBadRequest)
2024-06-11 16:31:51 -03:00
return
}
2024-06-12 16:15:37 -03:00
threshold, err := strconv.Atoi(params.Get("threshold"))
if error("\"threshold\" parameter is not a valid integer", err, http.StatusBadRequest) {
2024-06-11 16:31:51 -03:00
return
}
res, err := http.Get(u.String())
if error("Error trying to fetch the image", err, http.StatusInternalServerError) {
2024-06-11 16:31:51 -03:00
return
}
if res.StatusCode < 200 || res.StatusCode >= 300 {
error(
"Error trying to fetch the image, response is a non 2XX code",
errors.New("Status code: "+res.Status),
http.StatusInternalServerError,
)
2024-06-11 16:31:51 -03:00
}
data, err := io.ReadAll(res.Body)
if error("Error trying to read the image data", err, http.StatusInternalServerError) {
2024-06-11 16:31:51 -03:00
return
}
img, err := imgconv.Decode(bytes.NewReader(data))
if error("Error trying to decode the image", err, http.StatusInternalServerError) {
2024-06-11 16:31:51 -03:00
return
}
img = ImgOptimize(img, threshold)
2024-06-11 16:31:51 -03:00
err = webp.Encode(w, img, &webp.Options{Lossless: true})
if error("Error trying to encode the image", err, http.StatusInternalServerError) {
2024-06-11 16:31:51 -03:00
return
}
w.Header().Add("Cache-Control", "max-age=604800, stale-while-revalidate=86400, stale-if-error=86400")
2024-06-11 16:43:42 -03:00
w.Header().Add("CDN-Cache-Control", "max-age=604800")
w.Header().Add("Content-Type", "image/webp")
2024-06-11 16:31:51 -03:00
}