Skip to content

Commit f468e43

Browse files
committed
feat: speed up image retrival (at a cost of compile time)
1 parent de54081 commit f468e43

3 files changed

Lines changed: 50 additions & 25 deletions

File tree

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ require (
1818
github.com/go-viper/mapstructure/v2 v2.3.0 // indirect
1919
github.com/gofiber/template v1.8.3 // indirect
2020
github.com/gofiber/utils v1.1.0 // indirect
21+
github.com/h2non/bimg v1.1.9 // indirect
2122
github.com/jackc/pgpassfile v1.0.0 // indirect
2223
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
2324
github.com/jackc/pgx/v5 v5.7.5 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
3636
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
3737
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
3838
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
39+
github.com/h2non/bimg v1.1.9 h1:WH20Nxko9l/HFm4kZCA3Phbgu2cbHvYzxwxn9YROEGg=
40+
github.com/h2non/bimg v1.1.9/go.mod h1:R3+UiYwkK4rQl6KVFTOFJHitgLbZXBZNFh2cv3AEbp8=
3941
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
4042
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
4143
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=

twitterv1/cdnproxy.go

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ package twitterv1
22

33
import (
44
"fmt"
5-
"image"
6-
"image/gif"
7-
"image/jpeg"
8-
"image/png"
5+
"io"
96
"net/http"
107
"net/url"
118
"path/filepath"
@@ -14,9 +11,11 @@ import (
1411

1512
blueskyapi "github.com/Preloading/TwitterAPIBridge/bluesky"
1613
"github.com/gofiber/fiber/v2"
17-
"github.com/nfnt/resize"
14+
"github.com/h2non/bimg"
1815
)
1916

17+
var httpClient = &http.Client{}
18+
2019
func CDNDownscaler(c *fiber.Ctx) error {
2120
imageURL := c.Query("url")
2221
widthStr := c.Query("width")
@@ -101,19 +100,34 @@ func CDNDownscaler(c *fiber.Ctx) error {
101100
height = 0
102101
}
103102

104-
resp, err := http.Get(imageURL)
103+
resp, err := httpClient.Get(imageURL)
105104
if err != nil {
106105
return c.Status(fiber.StatusInternalServerError).SendString("Failed to fetch image")
107106
}
108107
defer resp.Body.Close()
109108

110-
img, format, err := image.Decode(resp.Body)
109+
if resizeOption == "none" || (width == 0 && height == 0) {
110+
c.Response().Header.Set("Cache-Control", "public, max-age=1209600")
111+
c.Response().Header.Set("Content-Type", resp.Header.Get("Content-Type"))
112+
imgBytes, err := io.ReadAll(resp.Body)
113+
if err != nil {
114+
return c.Status(fiber.StatusInternalServerError).SendString("Failed to recieve image")
115+
}
116+
return c.Send(imgBytes)
117+
}
118+
119+
imgBytes, err := io.ReadAll(resp.Body)
111120
if err != nil {
112-
return c.Status(fiber.StatusInternalServerError).SendString("Failed to decode image")
121+
return c.Status(fiber.StatusInternalServerError).SendString("Failed to recieve image")
122+
}
123+
124+
imgMetadata, err := bimg.Metadata(imgBytes)
125+
if err != nil {
126+
return c.Status(fiber.StatusInternalServerError).SendString("bad img")
113127
}
114128

115129
if maintainAspect {
116-
w, h := img.Bounds().Dx(), img.Bounds().Dy()
130+
w, h := imgMetadata.Size.Width, imgMetadata.Size.Height
117131
if w > h {
118132
w = width
119133
h = int(float64(width) * float64(h) / float64(w))
@@ -125,36 +139,44 @@ func CDNDownscaler(c *fiber.Ctx) error {
125139
height = h
126140
}
127141

142+
o := bimg.Options{}
143+
128144
if width > 0 || height > 0 {
129145
switch resizeOption {
130146
case "fit":
131-
img = resize.Resize(uint(width), uint(height), img, resize.Lanczos3)
147+
o = bimg.Options{
148+
Height: height,
149+
Width: width,
150+
}
132151
case "crop":
133-
img = resize.Thumbnail(uint(width), uint(height), img, resize.Lanczos3)
152+
o = bimg.Options{
153+
Height: height,
154+
Width: width,
155+
Crop: true,
156+
}
134157
case "none":
158+
c.Set("Content-Type", "image/"+imgMetadata.Type)
159+
160+
c.Response().Header.Set("Cache-Control", "public, max-age=1209600")
161+
return c.Send(imgBytes)
135162
// Do nothing
136163
default:
137-
img = resize.Resize(uint(width), uint(height), img, resize.Lanczos3)
164+
o = bimg.Options{
165+
Height: height,
166+
Width: width,
167+
}
138168
}
139169
}
140170

141-
c.Set("Content-Type", "image/"+format)
142-
switch format {
143-
case "jpeg":
144-
err = jpeg.Encode(c.Response().BodyWriter(), img, nil)
145-
case "png":
146-
err = png.Encode(c.Response().BodyWriter(), img)
147-
case "gif":
148-
err = gif.Encode(c.Response().BodyWriter(), img, nil)
149-
default:
150-
return c.Status(fiber.StatusInternalServerError).SendString("Unsupported image format")
151-
}
152-
171+
imgScaled, err := bimg.Resize(imgBytes, o)
153172
if err != nil {
154173
return c.Status(fiber.StatusInternalServerError).SendString("Failed to encode image")
155174
}
175+
176+
c.Set("Content-Type", "image/"+imgMetadata.Type)
177+
156178
c.Response().Header.Set("Cache-Control", "public, max-age=1209600")
157-
return nil
179+
return c.Send(imgScaled)
158180
}
159181

160182
func UserProfileImage(c *fiber.Ctx) error {

0 commit comments

Comments
 (0)