Files
guz.one/api/image.go
2024-06-19 16:58:52 -03:00

97 lines
2.3 KiB
Go

package api
import (
"bytes"
"errors"
"image"
"io"
"net/http"
"net/url"
"strconv"
"www/internals"
"github.com/chai2010/webp"
"github.com/sunshineplan/imgconv"
)
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})
}
func Image(w http.ResponseWriter, r *http.Request) {
error := internals.HttpErrorHelper(w)
params, err := url.ParseQuery(r.URL.RawQuery)
if error("Error trying to parse query parameters", err, http.StatusInternalServerError) {
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) {
return
}
if u.Hostname() == "" {
if r.URL.Scheme == "" {
u.Scheme = "https"
} else {
u.Scheme = r.URL.Scheme
}
u.Host = r.Host
}
if _, some := params["threshold"]; !some {
error("\"threshold\" parameter missing", errors.New("Missing argument"), http.StatusBadRequest)
return
}
threshold, err := strconv.Atoi(params.Get("threshold"))
if error("\"threshold\" parameter is not a valid integer", err, http.StatusBadRequest) {
return
}
res, err := http.Get(u.String())
if error("Error trying to fetch the image", err, http.StatusInternalServerError) {
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,
)
}
data, err := io.ReadAll(res.Body)
if error("Error trying to read the image data", err, http.StatusInternalServerError) {
return
}
img, err := imgconv.Decode(bytes.NewReader(data))
if error("Error trying to decode the image", err, http.StatusInternalServerError) {
return
}
img = ImgOptimize(img, threshold)
err = webp.Encode(w, img, &webp.Options{Lossless: true})
if error("Error trying to encode the image", err, http.StatusInternalServerError) {
return
}
w.Header().Add("Cache-Control", "max-age=604800, stale-while-revalidate=86400, stale-if-error=86400")
w.Header().Add("CDN-Cache-Control", "max-age=604800")
w.Header().Add("Content-Type", "image/webp")
}