@@ -27,6 +27,7 @@ pub enum AppError {
27
27
Forbidden ( RpcError ) ,
28
28
NotFound ( RpcError ) ,
29
29
InternalServerError ( RpcError ) ,
30
+ NotAcceptable ( RpcError ) ,
30
31
}
31
32
32
33
impl IntoResponse for AppError {
@@ -36,6 +37,7 @@ impl IntoResponse for AppError {
36
37
AppError :: Forbidden ( err) => ( StatusCode :: FORBIDDEN , err) ,
37
38
AppError :: NotFound ( err) => ( StatusCode :: NOT_FOUND , err) ,
38
39
AppError :: InternalServerError ( err) => ( StatusCode :: INTERNAL_SERVER_ERROR , err) ,
40
+ AppError :: NotAcceptable ( err) => ( StatusCode :: NOT_ACCEPTABLE , err) ,
39
41
} ;
40
42
41
43
let body = Json ( json ! ( error_message) ) ;
@@ -88,7 +90,9 @@ fn process_help_response(help_response: serde_json::Value) -> String {
88
90
post,
89
91
path = "/v1/{rpc_method}" ,
90
92
responses(
91
- ( status = 201 , description = "Call rpc method" , body = serde_json:: Value ) ,
93
+ ( status = 201 , description = "Call rpc method" , body = serde_json:: Value ,
94
+ content( ( "application/json" ) , ( "application/yaml" ) , ( "application/xml" ) ,
95
+ ( "application/x-www-form-urlencoded" ) , ( "text/html" ) ) ) ,
92
96
( status = 401 , description = "Unauthorized" , body = serde_json:: Value ) ,
93
97
( status = 403 , description = "Forbidden" , body = serde_json:: Value ) ,
94
98
( status = 404 , description = "Not Found" , body = serde_json:: Value ) ,
@@ -153,19 +157,109 @@ pub async fn call_rpc_method(
153
157
154
158
verify_rune ( plugin. clone ( ) , rune, & rpc_method, & rpc_params) . await ?;
155
159
156
- match call_rpc ( plugin, & rpc_method, rpc_params) . await {
157
- Ok ( result) => {
158
- let response_body = Json ( result) ;
159
- let response = ( StatusCode :: CREATED , response_body) . into_response ( ) ;
160
- Ok ( response)
161
- }
160
+ let cln_result = match call_rpc ( plugin, & rpc_method, rpc_params) . await {
161
+ Ok ( result) => result,
162
162
Err ( err) => {
163
163
if let Some ( code) = err. code {
164
164
if code == -32601 {
165
165
return Err ( AppError :: NotFound ( err) ) ;
166
166
}
167
167
}
168
- Err ( AppError :: InternalServerError ( err) )
168
+ return Err ( AppError :: InternalServerError ( err) ) ;
169
+ }
170
+ } ;
171
+
172
+ convert_response ( headers, rpc_method, cln_result)
173
+ }
174
+
175
+ fn convert_response (
176
+ headers : axum:: http:: HeaderMap ,
177
+ rpc_method : String ,
178
+ cln_result : serde_json:: Value ,
179
+ ) -> Result < Response , AppError > {
180
+ let accept = headers
181
+ . get ( "accept" )
182
+ . and_then ( |v| v. to_str ( ) . ok ( ) )
183
+ . unwrap_or ( "application/json" ) ;
184
+
185
+ let format = match accept {
186
+ a if a. contains ( "application/json" ) => "json" ,
187
+ a if a. contains ( "application/yaml" ) => "yaml" ,
188
+ a if a. contains ( "application/xml" ) => "xml" ,
189
+ a if a. contains ( "application/x-www-form-urlencoded" ) => "form" ,
190
+ a if a. contains ( "text/html" ) => "html" ,
191
+ _ => {
192
+ return Err ( AppError :: NotAcceptable ( RpcError {
193
+ code : None ,
194
+ data : None ,
195
+ message : format ! ( "Unsupported accept header: {}" , accept) ,
196
+ } ) )
197
+ }
198
+ } ;
199
+
200
+ match format {
201
+ "html" => match serde_json:: to_string_pretty ( & cln_result) {
202
+ Ok ( txt) => {
203
+ let html = format ! (
204
+ "<html><body><h1>{} Result</h1><pre>{}</pre></body></html>" ,
205
+ rpc_method, txt
206
+ ) ;
207
+ Ok ( ( StatusCode :: CREATED , [ ( "Content-Type" , "text/html" ) ] , html) . into_response ( ) )
208
+ }
209
+ Err ( e) => Err ( AppError :: InternalServerError ( RpcError {
210
+ code : None ,
211
+ data : None ,
212
+ message : format ! ( "Could not serialize to HTML: {}" , e) ,
213
+ } ) ) ,
214
+ } ,
215
+ "yaml" => match serde_yml:: to_string ( & cln_result) {
216
+ Ok ( yaml) => Ok ( (
217
+ StatusCode :: CREATED ,
218
+ [ ( "Content-Type" , "application/yaml" ) ] ,
219
+ yaml,
220
+ )
221
+ . into_response ( ) ) ,
222
+ Err ( e) => Err ( AppError :: InternalServerError ( RpcError {
223
+ code : None ,
224
+ data : None ,
225
+ message : format ! ( "Could not serialize to YAML: {}" , e) ,
226
+ } ) ) ,
227
+ } ,
228
+ "xml" => match quick_xml:: se:: to_string_with_root ( & rpc_method, & cln_result) {
229
+ Ok ( xml) => Ok ( (
230
+ StatusCode :: CREATED ,
231
+ [ ( "Content-Type" , "application/xml" ) ] ,
232
+ xml,
233
+ )
234
+ . into_response ( ) ) ,
235
+ Err ( e) => Err ( AppError :: InternalServerError ( RpcError {
236
+ code : None ,
237
+ data : None ,
238
+ message : format ! ( "Could not serialize to XML: {}" , e) ,
239
+ } ) ) ,
240
+ } ,
241
+ "form" => match serde_qs:: to_string ( & cln_result) {
242
+ Ok ( form) => Ok ( (
243
+ StatusCode :: CREATED ,
244
+ [ ( "Content-Type" , "application/x-www-form-urlencoded" ) ] ,
245
+ form,
246
+ )
247
+ . into_response ( ) ) ,
248
+ Err ( e) => Err ( AppError :: InternalServerError ( RpcError {
249
+ code : None ,
250
+ data : None ,
251
+ message : format ! ( "Could not serialize to FORM-URLENCODED: {}" , e) ,
252
+ } ) ) ,
253
+ } ,
254
+ _ => {
255
+ let response_body = Json ( cln_result) ;
256
+ let response = (
257
+ StatusCode :: CREATED ,
258
+ [ ( "Content-Type" , "application/json" ) ] ,
259
+ response_body,
260
+ )
261
+ . into_response ( ) ;
262
+ Ok ( response)
169
263
}
170
264
}
171
265
}
0 commit comments