@@ -31,6 +31,7 @@ pub mod executor;
3131pub mod state;
3232
3333pub ( crate ) static TRACEPARENT : & str = "traceparent" ;
34+ pub ( crate ) static X_CDN_INTERNAL_STATUS : & str = "x-cdn-internal-status" ;
3435
3536#[ cfg( target_family = "unix" ) ]
3637type OwnedFd = std:: os:: fd:: OwnedFd ;
@@ -45,6 +46,16 @@ const FASTEDGE_OUT_OF_MEMORY: u16 = 531;
4546const FASTEDGE_EXECUTION_TIMEOUT : u16 = 532 ;
4647const FASTEDGE_EXECUTION_PANIC : u16 = 533 ;
4748
49+ /// Internal status codes returned in `X-CDN-Internal-Status` response header (range 3000–3999).
50+ pub ( crate ) const INTERNAL_STATUS_CONTEXT_ERROR : u16 = 3000 ;
51+ pub ( crate ) const INTERNAL_STATUS_EXECUTE_ERROR : u16 = 3001 ;
52+ pub ( crate ) const INTERNAL_STATUS_APP_EXIT_ERROR : u16 = 3002 ;
53+ pub ( crate ) const INTERNAL_STATUS_WASM_TRAP_OTHER : u16 = 3003 ;
54+ pub ( crate ) const INTERNAL_STATUS_TIMEOUT_INTERRUPT : u16 = 3010 ;
55+ pub ( crate ) const INTERNAL_STATUS_TIMEOUT_ELAPSED : u16 = 3011 ;
56+ pub ( crate ) const INTERNAL_STATUS_TIMEOUT_DEADLINE : u16 = 3012 ;
57+ pub ( crate ) const INTERNAL_STATUS_OUT_OF_MEMORY : u16 = 3020 ;
58+
4859#[ derive( Default ) ]
4960pub struct HttpConfig {
5061 pub all_interfaces : bool ,
@@ -310,7 +321,7 @@ where
310321 tracing:: warn!( cause=?error, app=%app_name,
311322 "failure on getting context"
312323 ) ;
313- return internal_fastedge_error ( "context error" ) ;
324+ return internal_fastedge_error ( "context error" , INTERNAL_STATUS_CONTEXT_ERROR ) ;
314325 }
315326 } ;
316327
@@ -331,7 +342,7 @@ where
331342 }
332343 Err ( error) => {
333344 tracing:: warn!( cause=?error, "execute" ) ;
334- let ( status_code, fail_reason, msg) = map_err ( error) ;
345+ let ( status_code, fail_reason, msg, internal_code ) = map_err ( error) ;
335346 stats. status_code ( status_code) ;
336347 stats. fail_reason ( fail_reason as u32 ) ;
337348 tracing:: debug!( ?fail_reason, ?request_id, "stats" ) ;
@@ -344,7 +355,9 @@ where
344355 None ,
345356 ) ;
346357
347- let builder = hyper:: Response :: builder ( ) . status ( status_code) ;
358+ let builder = hyper:: Response :: builder ( )
359+ . status ( status_code)
360+ . header ( X_CDN_INTERNAL_STATUS , internal_code) ;
348361 let res_headers = app_res_headers ( cfg) ;
349362 let builder = res_headers
350363 . iter ( )
@@ -357,15 +370,16 @@ where
357370 }
358371}
359372
360- fn map_err ( error : Error ) -> ( u16 , AppResult , HyperOutgoingBody ) {
373+ fn map_err ( error : Error ) -> ( u16 , AppResult , HyperOutgoingBody , u16 ) {
361374 let root_cause = error. root_cause ( ) ;
362- let ( status_code, fail_reason, msg) =
375+ let ( status_code, fail_reason, msg, internal_code ) =
363376 if let Some ( exit) = root_cause. downcast_ref :: < wasi_common:: I32Exit > ( ) {
364377 if exit. 0 == 0 {
365378 (
366379 StatusCode :: OK . as_u16 ( ) ,
367380 AppResult :: SUCCESS ,
368381 Empty :: new ( ) . map_err ( |never| match never { } ) . boxed ( ) ,
382+ 0 ,
369383 )
370384 } else {
371385 (
@@ -374,6 +388,7 @@ fn map_err(error: Error) -> (u16, AppResult, HyperOutgoingBody) {
374388 Full :: new ( Bytes :: from ( "fastedge: App failed" ) )
375389 . map_err ( |never| match never { } )
376390 . boxed ( ) ,
391+ INTERNAL_STATUS_APP_EXIT_ERROR ,
377392 )
378393 }
379394 } else if let Some ( trap) = root_cause. downcast_ref :: < wasmtime:: Trap > ( ) {
@@ -384,20 +399,23 @@ fn map_err(error: Error) -> (u16, AppResult, HyperOutgoingBody) {
384399 Full :: new ( Bytes :: from ( "fastedge: Execution timeout" ) )
385400 . map_err ( |never| match never { } )
386401 . boxed ( ) ,
402+ INTERNAL_STATUS_TIMEOUT_INTERRUPT ,
387403 ) ,
388404 wasmtime:: Trap :: UnreachableCodeReached => (
389405 FASTEDGE_OUT_OF_MEMORY ,
390406 AppResult :: OOM ,
391407 Full :: new ( Bytes :: from ( "fastedge: Out of memory" ) )
392408 . map_err ( |never| match never { } )
393409 . boxed ( ) ,
410+ INTERNAL_STATUS_OUT_OF_MEMORY ,
394411 ) ,
395412 _ => (
396413 FASTEDGE_EXECUTION_PANIC ,
397414 AppResult :: OTHER ,
398415 Full :: new ( Bytes :: from ( "fastedge: App failed" ) )
399416 . map_err ( |never| match never { } )
400417 . boxed ( ) ,
418+ INTERNAL_STATUS_WASM_TRAP_OTHER ,
401419 ) ,
402420 }
403421 } else if let Some ( _elapsed) = root_cause. downcast_ref :: < Elapsed > ( ) {
@@ -407,6 +425,7 @@ fn map_err(error: Error) -> (u16, AppResult, HyperOutgoingBody) {
407425 Full :: new ( Bytes :: from ( "fastedge: Execution timeout" ) )
408426 . map_err ( |never| match never { } )
409427 . boxed ( ) ,
428+ INTERNAL_STATUS_TIMEOUT_ELAPSED ,
410429 )
411430 } else if root_cause. to_string ( ) . ends_with ( "deadline has elapsed" ) {
412431 (
@@ -415,6 +434,7 @@ fn map_err(error: Error) -> (u16, AppResult, HyperOutgoingBody) {
415434 Full :: new ( Bytes :: from ( "fastedge: Execution timeout" ) )
416435 . map_err ( |never| match never { } )
417436 . boxed ( ) ,
437+ INTERNAL_STATUS_TIMEOUT_DEADLINE ,
418438 )
419439 } else {
420440 (
@@ -423,9 +443,10 @@ fn map_err(error: Error) -> (u16, AppResult, HyperOutgoingBody) {
423443 Full :: new ( Bytes :: from ( "fastedge: Execute error" ) )
424444 . map_err ( |never| match never { } )
425445 . boxed ( ) ,
446+ INTERNAL_STATUS_EXECUTE_ERROR ,
426447 )
427448 } ;
428- ( status_code, fail_reason, msg)
449+ ( status_code, fail_reason, msg, internal_code )
429450}
430451
431452fn remote_traceparent ( req : & hyper:: Request < hyper:: body:: Incoming > ) -> SmolStr {
@@ -436,10 +457,14 @@ fn remote_traceparent(req: &hyper::Request<hyper::body::Incoming>) -> SmolStr {
436457 . unwrap_or ( nanoid:: nanoid!( ) . to_smolstr ( ) )
437458}
438459
439- /// Creates an HTTP 500 response.
440- fn internal_fastedge_error ( msg : & ' static str ) -> Result < hyper:: Response < HyperOutgoingBody > > {
460+ /// Creates an HTTP 530 response with an `X-CDN-Internal-Status` header.
461+ fn internal_fastedge_error (
462+ msg : & ' static str ,
463+ internal_code : u16 ,
464+ ) -> Result < hyper:: Response < HyperOutgoingBody > > {
441465 Ok ( hyper:: Response :: builder ( )
442466 . status ( FASTEDGE_INTERNAL_ERROR )
467+ . header ( X_CDN_INTERNAL_STATUS , internal_code)
443468 . body (
444469 Full :: new ( Bytes :: from ( format ! ( "fastedge: {}" , msg) ) )
445470 . map_err ( |never| match never { } )
0 commit comments