1- use std:: sync:: { Arc , OnceLock } ;
21#[ cfg( not( target_arch = "wasm32" ) ) ]
32use std:: { any:: Any , collections:: HashMap , sync:: RwLock } ;
3+ use std:: {
4+ marker:: PhantomData ,
5+ sync:: { Arc , OnceLock } ,
6+ } ;
47
58use axum_extra:: routing:: TypedPath ;
69use http:: Method ;
@@ -15,7 +18,10 @@ use leptos::{
1518 ServerFnError ,
1619} ;
1720use matchit:: Router ;
18- use models:: { ApiEndpoint , ApiRequest , AppResponse , ErrorType } ;
21+ use models:: {
22+ prelude:: * ,
23+ utils:: { GenericResponse , IntoAxumResponse } ,
24+ } ;
1925use preprocess:: Preprocessable ;
2026use serde:: { Serialize , de:: DeserializeOwned } ;
2127
@@ -31,6 +37,27 @@ type ApiCallRegistryData = OnceLock<RwLock<HashMap<Method, Router<Box<dyn Any +
3137/// YOUR OWN. Use the [`make_request`] fn instead.
3238pub static API_CALL_REGISTRY : ApiCallRegistryData = OnceLock :: new ( ) ;
3339
40+ #[ derive( Debug , Clone , Copy , Default ) ]
41+ struct ApiEncoding < E > ( PhantomData < E > )
42+ where
43+ E : ApiEndpoint ;
44+
45+ impl < E > Encoding for ApiEncoding < E >
46+ where
47+ E : ApiEndpoint ,
48+ {
49+ const CONTENT_TYPE : & ' static str =
50+ if <E :: ResponseBody as IntoAxumResponse >:: is :: < GenericResponse > ( ) {
51+ // If the response body is a GenericResponse, then we can't know the
52+ // content type of the response. So we just return the default content
53+ // type of binary data.
54+ "application/octet-stream"
55+ } else {
56+ Json :: CONTENT_TYPE
57+ } ;
58+ const METHOD : Method = E :: METHOD ;
59+ }
60+
3461/// A struct that holds the request to be made to the backend. This is used
3562/// for the server fn to make the request to the backend.
3663struct MakeRequest < E >
5279{
5380 type Client = BrowserClient ;
5481 type Error = ErrorType ;
55- type InputEncoding = if E :: METHOD == Method :: GET {
56- GetJson
57- } else {
58- Json
59- } ;
82+ type InputEncoding = ApiEncoding < E > ;
6083 type Output = AppResponse < E > ;
6184 type OutputEncoding = Json ;
6285 #[ cfg( not( target_arch = "wasm32" ) ) ]
79102 }
80103}
81104
82- impl < E > IntoReq < Json , BrowserRequest , ErrorType > for MakeRequest < E >
105+ impl < E > IntoReq < ApiEncoding < E > , BrowserRequest , ErrorType > for MakeRequest < E >
83106where
84107 E : ApiEndpoint ,
85108 <E :: RequestBody as Preprocessable >:: Processed : Send ,
@@ -91,16 +114,16 @@ where
91114 path : & str ,
92115 accepts : & str ,
93116 ) -> Result < BrowserRequest , ServerFnError < ErrorType > > {
94- let request = if E :: METHOD == Method :: GET {
117+ if E :: METHOD == Method :: GET {
95118 BrowserRequest :: try_new_get ( path, Json :: CONTENT_TYPE , accepts, query)
96119 } else {
97- BrowserRequest :: try_new_post ( path, content_type , accepts, body)
120+ BrowserRequest :: try_new_post ( path, Json :: CONTENT_TYPE , accepts, body)
98121 }
99122 }
100123}
101124
102125#[ cfg( not( target_arch = "wasm32" ) ) ]
103- impl < E > FromReq < Json , http:: Request < axum:: body:: Body > , ErrorType > for MakeRequest < E >
126+ impl < E > FromReq < ApiEncoding < E > , http:: Request < axum:: body:: Body > , ErrorType > for MakeRequest < E >
104127where
105128 E : ApiEndpoint ,
106129 <E :: RequestBody as Preprocessable >:: Processed : Send ,
@@ -115,7 +138,8 @@ where
115138}
116139
117140#[ cfg( target_arch = "wasm32" ) ]
118- impl < E > FromReq < Json , leptos:: server_fn:: request:: BrowserMockReq , ErrorType > for MakeRequest < E >
141+ impl < E > FromReq < ApiEncoding < E > , leptos:: server_fn:: request:: BrowserMockReq , ErrorType >
142+ for MakeRequest < E >
119143where
120144 E : ApiEndpoint ,
121145 <E :: RequestBody as Preprocessable >:: Processed : Send ,
0 commit comments