rust-axum.server-operation.mustache Maven / Gradle / Ivy
/// {{{operationId}}} - {{{httpMethod}}} {{{basePathWithoutHost}}}{{{path}}}
#[tracing::instrument(skip_all)]
async fn {{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}(
method: Method,
host: Host,
cookies: CookieJar,
{{#headerParams.size}}
headers: HeaderMap,
{{/headerParams.size}}
{{#pathParams.size}}
Path(path_params): Path,
{{/pathParams.size}}
{{#queryParams.size}}
Query(query_params): Query,
{{/queryParams.size}}
State(api_impl): State,
{{#vendorExtensions}}
{{^x-consumes-multipart-related}}
{{^x-consumes-multipart}}
{{#bodyParam}}
{{#vendorExtensions}}
{{#x-consumes-json}}
Json(body): Json<{{^required}}Option<{{/required}}{{{dataType}}}{{^required}}>{{/required}}>,
{{/x-consumes-json}}
{{#x-consumes-form-urlencoded}}
Form(body): Form<{{^required}}Option<{{/required}}{{{dataType}}}{{^required}}>{{/required}}>,
{{/x-consumes-form-urlencoded}}
{{#x-consumes-plain-text}}
{{#isString}}
body: String,
{{/isString}}
{{^isString}}
body: Bytes,
{{/isString}}
{{/x-consumes-plain-text}}
{{/vendorExtensions}}
{{/bodyParam}}
{{/x-consumes-multipart}}
{{/x-consumes-multipart-related}}
{{#x-consumes-multipart}}
body: Multipart,
{{/x-consumes-multipart}}
{{#x-consumes-multipart-related}}
body: axum::body::Body,
{{/x-consumes-multipart-related}}
{{/vendorExtensions}}
) -> Result
where
I: AsRef + Send + Sync,
A: apis::{{classFilename}}::{{classnamePascalCase}},
{
{{#headerParams}}
{{#-first}}
// Header parameters
let header_params = {
{{/-first}}
let header_{{{paramName}}} = headers.get(HeaderName::from_static("{{{nameInLowerCase}}}"));
let header_{{{paramName}}} = match header_{{{paramName}}} {
Some(v) => match header::IntoHeaderValue::<{{{dataType}}}>::try_from((*v).clone()) {
Ok(result) =>
{{#required}}
result.0,
{{/required}}
{{^required}}
Some(result.0),
{{/required}}
Err(err) => {
return Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Invalid header {{{baseName}}} - {}", err))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
},
},
None => {
{{#required}}
return Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from("Missing required header {{{baseName}}}")).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
{{/required}}
{{^required}}
None
{{/required}}
}
};
{{/headerParams}}
{{#headerParams}}
{{#-first}}
models::{{{operationIdCamelCase}}}HeaderParams {
{{/-first}}
{{{paramName}}}: header_{{{paramName}}},
{{#-last}}
}
};
{{/-last}}
{{/headerParams}}
{{^disableValidator}}
{{^allowBlockingValidator}}
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move ||
{{/allowBlockingValidator}}
{{#allowBlockingValidator}}
let validation =
{{/allowBlockingValidator}}
{{#vendorExtensions}}{{{x-operation-id}}}_validation{{/vendorExtensions}}(
{{#headerParams.size}}
header_params,
{{/headerParams.size}}
{{#pathParams.size}}
path_params,
{{/pathParams.size}}
{{#queryParams.size}}
query_params,
{{/queryParams.size}}
{{^x-consumes-multipart-related}}
{{^x-consumes-multipart}}
{{#bodyParam}}
body,
{{/bodyParam}}
{{/x-consumes-multipart}}
{{/x-consumes-multipart-related}}
)
{{^allowBlockingValidator}}).await.unwrap(){{/allowBlockingValidator}};
let Ok((
{{#headerParams.size}}
header_params,
{{/headerParams.size}}
{{#pathParams.size}}
path_params,
{{/pathParams.size}}
{{#queryParams.size}}
query_params,
{{/queryParams.size}}
{{^x-consumes-multipart-related}}
{{^x-consumes-multipart}}
{{#bodyParam}}
body,
{{/bodyParam}}
{{/x-consumes-multipart}}
{{/x-consumes-multipart-related}}
)) = validation else {
return Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(validation.unwrap_err().to_string()))
.map_err(|_| StatusCode::BAD_REQUEST);
};
{{/disableValidator}}
let result = api_impl.as_ref().{{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}(
method,
host,
cookies,
{{#headerParams.size}}
header_params,
{{/headerParams.size}}
{{#pathParams.size}}
path_params,
{{/pathParams.size}}
{{#queryParams.size}}
query_params,
{{/queryParams.size}}
{{#vendorExtensions}}
{{^x-consumes-multipart-related}}
{{^x-consumes-multipart}}
{{#bodyParams}}
{{#-first}}
body,
{{/-first}}
{{/bodyParams}}
{{/x-consumes-multipart}}
{{/x-consumes-multipart-related}}
{{#x-consumes-multipart}}
body,
{{/x-consumes-multipart}}
{{#x-consumes-multipart-related}}
body,
{{/x-consumes-multipart-related}}
{{/vendorExtensions}}
).await;
let mut response = Response::builder();
let resp = match result {
Ok(rsp) => match rsp {
{{#responses}}
apis::{{classFilename}}::{{{operationId}}}Response::{{#vendorExtensions}}{{x-response-id}}{{/vendorExtensions}}
{{#dataType}}
{{^headers}}
(body)
{{/headers}}
{{#headers}}
{{#-first}}
{
body,
{{/-first}}
{{{name}}}{{^-last}},{{/-last}}
{{#-last}}
}
{{/-last}}
{{/headers}}
{{/dataType}}
{{^dataType}}
{{#headers}}
{{#-first}}
{
{{/-first}}
{{{name}}}{{^-last}},{{/-last}}
{{#-last}}
}
{{/-last}}
{{/headers}}
{{/dataType}}
=> {
{{#headers}}
{{^required}}
if let Some({{{name}}}) = {{{name}}} {
{{/required}}
let {{{name}}} = match header::IntoHeaderValue({{{name}}}).try_into() {
Ok(val) => val,
Err(e) => {
return Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(Body::from(format!("An internal server error occurred handling {{name}} header - {}", e))).map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR });
}
};
{
let mut response_headers = response.headers_mut().unwrap();
response_headers.insert(
HeaderName::from_static("{{{nameInLowerCase}}}"),
{{name}}
);
}
{{^required}}
}
{{/required}}
{{/headers}}
{{#range}}
response.status::(body.code.parse().unwrap()); // {{{code}}}
{{/range}}
{{^range}}
let mut response = response.status({{{code}}});
{{/range}}
{{#produces}}
{{#-first}}
{{#dataType}}
{{#vendorExtensions}}
{
let mut response_headers = response.headers_mut().unwrap();
response_headers.insert(
CONTENT_TYPE,
HeaderValue::from_str("{{{x-mime-type}}}").map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR })?);
}
{{/vendorExtensions}}
{{/dataType}}
{{/-first}}
{{/produces}}
{{#dataType}}
{{#vendorExtensions}}
{{#x-produces-json}}
{{^allowBlockingResponseSerialize}}
let body_content = tokio::task::spawn_blocking(move ||
{{/allowBlockingResponseSerialize}}
{{#allowBlockingResponseSerialize}}
let body_content =
{{/allowBlockingResponseSerialize}}
serde_json::to_vec(&body).map_err(|e| {
error!(error = ?e);
StatusCode::INTERNAL_SERVER_ERROR
}){{^allowBlockingResponseSerialize}}).await.unwrap(){{/allowBlockingResponseSerialize}}?;
{{/x-produces-json}}
{{#x-produces-form-urlencoded}}
{{^allowBlockingResponseSerialize}}
let body_content = tokio::task::spawn_blocking(move ||
{{/allowBlockingResponseSerialize}}
{{#allowBlockingResponseSerialize}}
let body_content =
{{/allowBlockingResponseSerialize}}
serde_urlencoded::to_string(body).map_err(|e| {
error!(error = ?e);
StatusCode::INTERNAL_SERVER_ERROR
}){{^allowBlockingResponseSerialize}}).await.unwrap(){{/allowBlockingResponseSerialize}}?;
{{/x-produces-form-urlencoded}}
{{#x-produces-bytes}}
let body_content = body.0;
{{/x-produces-bytes}}
{{#x-produces-plain-text}}
let body_content = body;
{{/x-produces-plain-text}}
{{/vendorExtensions}}
response.body(Body::from(body_content))
{{/dataType}}
{{^dataType}}
response.body(Body::empty())
{{/dataType}}
},
{{/responses}}
},
Err(_) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
},
};
resp.map_err(|e| { error!(error = ?e); StatusCode::INTERNAL_SERVER_ERROR })
}