@@ -115,9 +115,42 @@ export async function defaultHandler(
115115 return buildSuccessResponse ( result , options ?. streamCreator , etag ) ;
116116 } catch ( e : any ) {
117117 error ( "Failed to optimize image" , e ) ;
118+
119+ // Determine appropriate status code based on error
120+ let statusCode = 500 ; // Default to 500 for unknown errors
121+ let errorMessage = "Internal server error" ;
122+
123+ // Check if error has HTTP status information
124+ if ( e && typeof e === 'object' ) {
125+ if ( 'statusCode' in e && typeof e . statusCode === 'number' ) {
126+ statusCode = e . statusCode ;
127+ errorMessage = `HTTP Error: ${ statusCode } ` ;
128+ } else if ( 'code' in e ) {
129+ const code = e . code as string ;
130+ if ( code === 'ENOTFOUND' || code === 'ECONNREFUSED' ) {
131+ statusCode = 404 ;
132+ errorMessage = `Image not found: ${ e . message } ` ;
133+ }
134+ }
135+
136+ if ( e . message && typeof e . message === 'string' ) {
137+ // Try to extract status codes from error messages
138+ if ( e . message . includes ( '403' ) || e . message . includes ( 'Access Denied' ) ) {
139+ statusCode = 403 ;
140+ errorMessage = `Access denied: ${ e . message } ` ;
141+ } else if ( e . message . includes ( '404' ) || e . message . includes ( 'Not Found' ) ) {
142+ statusCode = 404 ;
143+ errorMessage = `Image not found: ${ e . message } ` ;
144+ } else {
145+ errorMessage = e . message ;
146+ }
147+ }
148+ }
149+
118150 return buildFailureResponse (
119- "Internal server error" ,
151+ errorMessage ,
120152 options ?. streamCreator ,
153+ statusCode
121154 ) ;
122155 }
123156}
@@ -255,7 +288,46 @@ async function downloadHandler(
255288 try {
256289 // Case 1: remote image URL => download the image from the URL
257290 if ( url . href . toLowerCase ( ) . match ( / ^ h t t p s ? : \/ \/ / ) ) {
258- pipeRes ( https . get ( url ) , res ) ;
291+ const request = https . get ( url , ( response ) => {
292+ // Check for HTTP error status codes
293+ if ( response . statusCode && response . statusCode >= 400 ) {
294+ error ( `Failed to get image: HTTP ${ response . statusCode } ` ) ;
295+ res . statusCode = response . statusCode ;
296+ res . end ( ) ;
297+ return ;
298+ }
299+ // IncomingMessage is a Readable stream, not a Writable
300+ // We need to pipe it directly to the response
301+ response . pipe ( res )
302+ . once ( "close" , ( ) => {
303+ if ( ! res . headersSent ) {
304+ res . statusCode = 200 ;
305+ }
306+ res . end ( ) ;
307+ } )
308+ . once ( "error" , ( pipeErr ) => {
309+ error ( "Failed to get image during piping" , pipeErr ) ;
310+ if ( ! res . headersSent ) {
311+ res . statusCode = 400 ;
312+ }
313+ res . end ( ) ;
314+ } ) ;
315+ } ) ;
316+
317+ request . on ( 'error' , ( err : NodeJS . ErrnoException ) => {
318+ error ( "Failed to get image" , err ) ;
319+ // Handle common network errors
320+ if ( err && typeof err === 'object' && 'code' in err ) {
321+ if ( err . code === 'ENOTFOUND' || err . code === 'ECONNREFUSED' ) {
322+ res . statusCode = 404 ;
323+ } else {
324+ res . statusCode = 400 ;
325+ }
326+ } else {
327+ res . statusCode = 400 ;
328+ }
329+ res . end ( ) ;
330+ } ) ;
259331 }
260332 // Case 2: local image => download the image from S3
261333 else {
0 commit comments