@@ -115,9 +115,42 @@ export async function defaultHandler(
115
115
return buildSuccessResponse ( result , options ?. streamCreator , etag ) ;
116
116
} catch ( e : any ) {
117
117
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
+
118
150
return buildFailureResponse (
119
- "Internal server error" ,
151
+ errorMessage ,
120
152
options ?. streamCreator ,
153
+ statusCode
121
154
) ;
122
155
}
123
156
}
@@ -255,7 +288,46 @@ async function downloadHandler(
255
288
try {
256
289
// Case 1: remote image URL => download the image from the URL
257
290
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
+ } ) ;
259
331
}
260
332
// Case 2: local image => download the image from S3
261
333
else {
0 commit comments