@@ -10,18 +10,15 @@ use http::Method;
1010use leptos:: {
1111 server_fn:: {
1212 client:: browser:: BrowserClient ,
13- codec:: { Encoding , FromReq , IntoReq , Json } ,
13+ codec:: { Encoding , FromReq , GetUrl , IntoReq , PostUrl } ,
1414 middleware:: Layer ,
1515 request:: { browser:: BrowserRequest , ClientReq } ,
1616 ServerFn ,
1717 } ,
1818 ServerFnError ,
1919} ;
2020use matchit:: Router ;
21- use models:: {
22- prelude:: * ,
23- utils:: { GenericResponse , IntoAxumResponse } ,
24- } ;
21+ use models:: { prelude:: * , utils:: GenericResponse } ;
2522use preprocess:: Preprocessable ;
2623use serde:: { Serialize , de:: DeserializeOwned } ;
2724
@@ -47,15 +44,19 @@ where
4744 E : ApiEndpoint ,
4845{
4946 const CONTENT_TYPE : & ' static str =
50- if <E :: ResponseBody as IntoAxumResponse > :: is :: < GenericResponse > ( ) {
47+ if std :: any :: TypeId :: of :: < E :: ResponseBody > ( ) == std :: any :: TypeId :: of :: < GenericResponse > ( ) {
5148 // If the response body is a GenericResponse, then we can't know the
5249 // content type of the response. So we just return the default content
5350 // type of binary data.
5451 "application/octet-stream"
5552 } else {
56- Json :: CONTENT_TYPE
53+ GetUrl :: CONTENT_TYPE
5754 } ;
58- const METHOD : Method = E :: METHOD ;
55+ const METHOD : Method = if Method :: GET == E :: METHOD {
56+ Method :: GET
57+ } else {
58+ Method :: POST
59+ } ;
5960}
6061
6162/// A struct that holds the request to be made to the backend. This is used
8182 type Error = ErrorType ;
8283 type InputEncoding = ApiEncoding < E > ;
8384 type Output = AppResponse < E > ;
84- type OutputEncoding = Json ;
85+ type OutputEncoding = ApiEncoding < E > ;
8586 #[ cfg( not( target_arch = "wasm32" ) ) ]
8687 type ServerRequest = http:: Request < axum:: body:: Body > ;
8788 #[ cfg( target_arch = "wasm32" ) ]
9495 const PATH : & ' static str = <E :: RequestPath as TypedPath >:: PATH ;
9596
9697 async fn run_body ( self ) -> Result < Self :: Output , ServerFnError < Self :: Error > > {
97- todo ! ( )
98+ use std:: net:: { IpAddr , SocketAddr } ;
99+
100+ use axum:: extract:: ConnectInfo ;
101+ use axum_extra:: routing:: TypedPath ;
102+ use tower:: {
103+ ServiceBuilder ,
104+ ServiceExt ,
105+ service_fn,
106+ util:: { BoxCloneService , BoxLayer } ,
107+ } ;
108+
109+ let ConnectInfo ( socket_addr) = leptos_axum:: extract :: < ConnectInfo < SocketAddr > > ( )
110+ . await
111+ . map_err ( ErrorType :: server_error) ?;
112+ let layer = API_CALL_REGISTRY
113+ . get ( )
114+ . expect ( "API call registry not initialized" )
115+ . read ( )
116+ . expect ( "API call registry poisoned" )
117+ . get ( & E :: METHOD )
118+ . unwrap_or_else ( || panic ! ( "API call registry does not contain {}" , E :: METHOD ) )
119+ . at ( <E :: RequestPath as TypedPath >:: PATH )
120+ . unwrap_or_else ( |_| {
121+ panic ! (
122+ "could not find route at path `{}`" ,
123+ <E :: RequestPath as TypedPath >:: PATH
124+ )
125+ } )
126+ . value
127+ . downcast_ref :: < BoxLayer <
128+ BoxCloneService < ( ApiRequest < E > , IpAddr ) , AppResponse < E > , ErrorType > ,
129+ ( ApiRequest < E > , IpAddr ) ,
130+ AppResponse < E > ,
131+ ErrorType ,
132+ > > ( )
133+ . expect ( "unable to downcast layer" )
134+ . to_owned ( ) ;
135+ ServiceBuilder :: new ( )
136+ . layer ( layer)
137+ . service ( BoxCloneService :: new ( service_fn ( |_| async move {
138+ unreachable ! ( )
139+ } ) ) )
140+ . oneshot ( ( self . request , socket_addr. ip ( ) ) )
141+ . await
142+ . map_err ( ServerFnError :: WrappedServerError )
98143 }
99144
100145 fn middlewares ( ) -> Vec < Arc < dyn Layer < Self :: ServerRequest , Self :: ServerResponse > > > {
@@ -115,9 +160,21 @@ where
115160 accepts : & str ,
116161 ) -> Result < BrowserRequest , ServerFnError < ErrorType > > {
117162 if E :: METHOD == Method :: GET {
118- BrowserRequest :: try_new_get ( path, Json :: CONTENT_TYPE , accepts, query)
163+ BrowserRequest :: try_new_get (
164+ path,
165+ GetUrl :: CONTENT_TYPE ,
166+ accepts,
167+ serde_urlencoded:: to_string ( self . request . query )
168+ . unwrap ( )
169+ . as_str ( ) ,
170+ )
119171 } else {
120- BrowserRequest :: try_new_post ( path, Json :: CONTENT_TYPE , accepts, body)
172+ BrowserRequest :: try_new_post (
173+ path,
174+ PostUrl :: CONTENT_TYPE ,
175+ accepts,
176+ serde_json:: to_string ( & self . request . body ) . unwrap ( ) ,
177+ )
121178 }
122179 }
123180}
@@ -131,7 +188,7 @@ where
131188 E :: ResponseBody : Serialize + DeserializeOwned ,
132189{
133190 async fn from_req (
134- req : http:: Request < axum:: body:: Body > ,
191+ _req : http:: Request < axum:: body:: Body > ,
135192 ) -> Result < Self , ServerFnError < ErrorType > > {
136193 todo ! ( )
137194 }
@@ -168,80 +225,10 @@ where
168225{
169226 #[ cfg( not( target_arch = "wasm32" ) ) ]
170227 {
171- use std:: net:: { IpAddr , SocketAddr } ;
172-
173- use axum:: extract:: ConnectInfo ;
174- use axum_extra:: routing:: TypedPath ;
175- use tower:: {
176- ServiceBuilder ,
177- ServiceExt ,
178- service_fn,
179- util:: { BoxCloneService , BoxLayer } ,
180- } ;
181-
182- let ConnectInfo ( socket_addr) = leptos_axum:: extract :: < ConnectInfo < SocketAddr > > ( )
183- . await
184- . map_err ( ErrorType :: server_error) ?;
185- let layer = API_CALL_REGISTRY
186- . get ( )
187- . expect ( "API call registry not initialized" )
188- . read ( )
189- . expect ( "API call registry poisoned" )
190- . get ( & E :: METHOD )
191- . unwrap_or_else ( || panic ! ( "API call registry does not contain {}" , E :: METHOD ) )
192- . at ( <E :: RequestPath as TypedPath >:: PATH )
193- . unwrap_or_else ( |_| {
194- panic ! (
195- "could not find route at path `{}`" ,
196- <E :: RequestPath as TypedPath >:: PATH
197- )
198- } )
199- . value
200- . downcast_ref :: < BoxLayer <
201- BoxCloneService < ( ApiRequest < E > , IpAddr ) , AppResponse < E > , ErrorType > ,
202- ( ApiRequest < E > , IpAddr ) ,
203- AppResponse < E > ,
204- ErrorType ,
205- > > ( )
206- . expect ( "unable to downcast layer" )
207- . to_owned ( ) ;
208- ServiceBuilder :: new ( )
209- . layer ( layer)
210- . service ( BoxCloneService :: new ( service_fn ( |_| async move {
211- unreachable ! ( )
212- } ) ) )
213- . oneshot ( ( request, socket_addr. ip ( ) ) )
214- . await
215- . map_err ( ServerFnError :: WrappedServerError )
228+ MakeRequest { request } . run_body ( ) . await
216229 }
217230 #[ cfg( target_arch = "wasm32" ) ]
218231 {
219- use models:: utils:: Headers ;
220-
221- let response = REQWEST_CLIENT
222- . get_or_init ( reqwest:: Client :: new)
223- . request ( E :: METHOD , format ! ( "/api/{}" , request. path. to_string( ) ) )
224- . headers ( request. headers . to_header_map ( ) )
225- . query ( & request. query )
226- . json ( & request. body )
227- . send ( )
228- . await
229- . map_err ( |err| ServerFnError :: Request ( err. to_string ( ) ) ) ?;
230-
231- let status_code = response. status ( ) ;
232- let headers = E :: ResponseHeaders :: from_header_map ( response. headers ( ) )
233- . map_err ( |err| ServerFnError :: Response ( err. to_string ( ) ) ) ?;
234- let text = response
235- . text ( )
236- . await
237- . map_err ( |err| ServerFnError :: Response ( err. to_string ( ) ) ) ?;
238- let body =
239- serde_json:: from_str ( & text) . map_err ( |err| ServerFnError :: Response ( err. to_string ( ) ) ) ?;
240-
241- Ok ( AppResponse {
242- status_code,
243- headers,
244- body,
245- } )
232+ MakeRequest { request } . run_on_client ( ) . await
246233 }
247234}
0 commit comments