1- const fetch = ( ...args ) =>
2- import ( "node-fetch" ) . then ( ( { default : fetch } ) => fetch ( ...args ) ) ;
31const express = require ( "express" ) ;
42const sharp = require ( "sharp" ) ;
3+ const { Storage, ApiError } = require ( "@google-cloud/storage" ) ;
54
5+ const storage = new Storage ( ) ;
66const app = express ( ) ;
7+
78const PORT = 8080 ;
89const HOST = "0.0.0.0" ;
910const BASE_STORAGE_IMAGE_URL = "https://storage.googleapis.com/" ;
1011const BUCKET = process . env . STORAGE_BUCKET || "openbeta-prod" ;
1112
12- const getImage = ( path ) =>
13- fetch ( path ) . then ( async ( r ) => ( {
14- data : await r . arrayBuffer ( ) ,
15- status : r . status ,
16- } ) ) ;
1713const getFormat = ( webp , avif ) => {
1814 return webp ? "webp" : avif ? "avif" : "jpeg" ;
1915} ;
@@ -22,36 +18,44 @@ app.get("/healthy", (req, res) => {
2218 res . send ( "yep." ) ;
2319} ) ;
2420
21+ app . get ( "/version" , ( req , res ) => {
22+ res . send ( process . env . APP_VERSION ) ;
23+ } ) ;
24+
2525app . get ( "*" , async ( req , res ) => {
2626 try {
27- const { searchParams, pathname, href } = new URL (
28- `${ BASE_STORAGE_IMAGE_URL } ${ BUCKET } ${ req . url } ` ,
29- ) ;
30-
31- if ( ! / \. ( j p e ? g | p n g | g i f | w e b p ) $ / i. test ( pathname ) ) {
27+ if ( ! / \. ( j p e ? g | p n g | g i f | w e b p ) $ / i. test ( req . path ) ) {
3228 return res . status ( 400 ) . send ( "Disallowed file extension" ) ;
3329 }
3430
3531 const webp = req . headers . accept ?. includes ( "image/webp" ) ;
3632 const avif = req . headers . accept ?. includes ( "image/avif" ) ;
37- const quality = Number ( searchParams . get ( "q" ) ) || 90 ;
38- const width = Number ( searchParams . get ( "w" ) ) || undefined ;
39- const height = Number ( searchParams . get ( "h" ) ) || undefined ;
33+ const quality = Number ( req . query . q ) || 90 ;
34+ const width = Number ( req . query . w ) || undefined ;
35+ const height = Number ( req . query . h ) || undefined ;
4036 const format = getFormat ( webp , avif ) ;
4137
42- const { data, status } = await getImage ( href ) ;
43- if ( status > 399 ) {
44- return res
45- . status ( 415 )
46- . send ( "upstream server did not respond with a valid status code" ) ;
47- }
48-
4938 res
5039 . set ( "Cache-Control" , "public, max-age=15552000" )
5140 . set ( "Vary" , "Accept" )
5241 . type ( `image/${ format } ` ) ;
5342
54- sharp ( data )
43+ const pipeline = sharp ( ) ;
44+
45+ storage
46+ . bucket ( BUCKET )
47+ . file ( req . path . slice ( 1 ) ) // remove leading slash
48+ . createReadStream ( )
49+ . on ( "error" , function ( e ) {
50+ if ( e instanceof ApiError ) {
51+ if ( e . message ?. includes ( "No such object" ) )
52+ return res . status ( 404 ) . end ( ) ;
53+ }
54+ return res . status ( 500 ) . send ( JSON . stringify ( e ) ) ;
55+ } )
56+ . pipe ( pipeline ) ;
57+
58+ pipeline
5559 . rotate ( )
5660 . resize ( { width, height } )
5761 . toFormat ( format , { effort : 3 , quality, progressive : true } )
0 commit comments