11use std:: { path:: Path , process, sync:: Arc } ;
22
33use anyhow:: { Result , anyhow, bail} ;
4+ use axum:: {
5+ http:: StatusCode ,
6+ response:: { IntoResponse , Response } ,
7+ } ;
48use clap:: { Parser , builder:: NonEmptyStringValueParser } ;
59use config:: { Config , File } ;
610use env_logger:: Env ;
@@ -25,6 +29,7 @@ use yomo::{
2529 model_api:: build_model_api,
2630 model_api_provider,
2731 model_list:: build_model_list_api,
32+ openai_http_mapping:: openai_error_response,
2833 router:: RouterImpl ,
2934 serve_config:: ServeConfig ,
3035 serverless:: { ServerlessHandler , ServerlessLanguage , ServerlessMemoryBridge } ,
@@ -38,6 +43,18 @@ use yomo::{
3843
3944const MAX_BUF_SIZE : usize = 64 * 1024 ;
4045
46+ fn method_not_allowed_response ( ) -> Response {
47+ openai_error_response (
48+ StatusCode :: METHOD_NOT_ALLOWED ,
49+ "Method Not Allowed" ,
50+ Some ( "invalid_request_error" ) ,
51+ )
52+ }
53+
54+ async fn handle_method_not_allowed ( ) -> impl IntoResponse {
55+ method_not_allowed_response ( )
56+ }
57+
4158/// CLI commands
4259#[ derive( Parser , Debug ) ]
4360#[ command( author, version, about, long_about = None ) ]
@@ -256,6 +273,8 @@ async fn serve(opt: ServeOptions) -> Result<()> {
256273 require_bearer_auth,
257274 ) ) ;
258275
276+ app = app. method_not_allowed_fallback ( handle_method_not_allowed) ;
277+
259278 info ! (
260279 "start HTTP API server on {}:{}" ,
261280 config. http_api. host, config. http_api. port,
@@ -396,3 +415,36 @@ async fn main() {
396415 process:: exit ( 1 ) ;
397416 }
398417}
418+
419+ #[ cfg( test) ]
420+ mod tests {
421+ use axum:: {
422+ body:: to_bytes,
423+ http:: { StatusCode , header} ,
424+ } ;
425+ use serde_json:: Value ;
426+
427+ use super :: method_not_allowed_response;
428+
429+ #[ tokio:: test]
430+ async fn method_not_allowed_response_uses_openai_error_payload ( ) {
431+ let response = method_not_allowed_response ( ) ;
432+
433+ assert_eq ! ( response. status( ) , StatusCode :: METHOD_NOT_ALLOWED ) ;
434+ assert_eq ! (
435+ response
436+ . headers( )
437+ . get( header:: CONTENT_TYPE )
438+ . and_then( |value| value. to_str( ) . ok( ) ) ,
439+ Some ( "application/json" )
440+ ) ;
441+
442+ let body = to_bytes ( response. into_body ( ) , usize:: MAX )
443+ . await
444+ . expect ( "read response body" ) ;
445+ let payload: Value = serde_json:: from_slice ( & body) . expect ( "parse json response body" ) ;
446+
447+ assert_eq ! ( payload[ "error" ] [ "message" ] , "Method Not Allowed" ) ;
448+ assert_eq ! ( payload[ "error" ] [ "type" ] , "invalid_request_error" ) ;
449+ }
450+ }
0 commit comments