Skip to content

Commit 9bb4175

Browse files
committed
feat(rust-server): refactor server module templates to avoid a monolithic run function.
1 parent a336a4a commit 9bb4175

12 files changed

Lines changed: 3256 additions & 872 deletions

File tree

modules/openapi-generator/src/main/resources/rust-server/client-callbacks.mustache

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,24 @@ use crate::{{{operationId}}}Response;
4949
{{/callbacks}}
5050
{{>server-service-footer}}
5151

52+
{{! Per-operation handler functions — extracted from the match arms in run() to
53+
reduce per-function compilation-unit size and avoid rustc OOM on large APIs. }}
54+
{{#apiInfo}}
55+
{{#apis}}
56+
{{#operations}}
57+
{{#operation}}
58+
{{#callbacks}}
59+
{{#urls}}
60+
{{#requests}}
61+
{{>server-operation-handler}}
62+
63+
{{/requests}}
64+
{{/urls}}
65+
{{/callbacks}}
66+
{{/operation}}
67+
{{/operations}}
68+
{{/apis}}
69+
{{/apiInfo}}
5270
/// Request parser for `Api`.
5371
pub struct ApiRequestParser;
5472
impl<T> RequestParser<T> for ApiRequestParser {

modules/openapi-generator/src/main/resources/rust-server/server-mod.mustache

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@ pub mod callbacks;
3030
{{/pathSet}}
3131
{{>server-service-footer}}
3232

33+
{{! Per-operation handler functions — extracted from the match arms in run() to
34+
reduce per-function compilation-unit size and avoid rustc OOM on large APIs. }}
35+
{{#apiInfo}}
36+
{{#apis}}
37+
{{#operations}}
38+
{{#operation}}
39+
{{>server-operation-handler}}
40+
41+
{{/operation}}
42+
{{/operations}}
43+
{{/apis}}
44+
{{/apiInfo}}
3345
/// Request parser for `Api`.
3446
pub struct ApiRequestParser;
3547
impl<T> RequestParser<T> for ApiRequestParser {

modules/openapi-generator/src/main/resources/rust-server/server-operation-handler.mustache

Lines changed: 356 additions & 0 deletions
Large diffs are not rendered by default.

modules/openapi-generator/src/main/resources/rust-server/server-operation.mustache

Lines changed: 1 addition & 321 deletions
Large diffs are not rendered by default.

samples/server/petstore/rust-server/output/multipart-v3/src/server/mod.rs

Lines changed: 83 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,53 @@ impl<T, C, ReqBody> hyper::service::Service<(Request<ReqBody>, C)> for Service<T
256256

257257
// MultipartRelatedRequestPost - POST /multipart_related_request
258258
hyper::Method::POST if path.matched(paths::ID_MULTIPART_RELATED_REQUEST) => {
259+
handle_multipart_related_request_post(api_impl, uri, headers, body, context, validation, multipart_form_size_limit).await
260+
},
261+
262+
// MultipartRequestPost - POST /multipart_request
263+
hyper::Method::POST if path.matched(paths::ID_MULTIPART_REQUEST) => {
264+
handle_multipart_request_post(api_impl, uri, headers, body, context, validation, multipart_form_size_limit).await
265+
},
266+
267+
// MultipleIdenticalMimeTypesPost - POST /multiple-identical-mime-types
268+
hyper::Method::POST if path.matched(paths::ID_MULTIPLE_IDENTICAL_MIME_TYPES) => {
269+
handle_multiple_identical_mime_types_post(api_impl, uri, headers, body, context, validation, multipart_form_size_limit).await
270+
},
271+
272+
_ if path.matched(paths::ID_MULTIPART_RELATED_REQUEST) => method_not_allowed(),
273+
_ if path.matched(paths::ID_MULTIPART_REQUEST) => method_not_allowed(),
274+
_ if path.matched(paths::ID_MULTIPLE_IDENTICAL_MIME_TYPES) => method_not_allowed(),
275+
_ => Ok(Response::builder().status(StatusCode::NOT_FOUND)
276+
.body(BoxBody::new(http_body_util::Empty::new()))
277+
.expect("Unable to create Not Found response"))
278+
}
279+
}
280+
Box::pin(run(
281+
self.api_impl.clone(),
282+
req,
283+
self.validation,
284+
self.multipart_form_size_limit
285+
))
286+
}
287+
}
288+
289+
#[allow(unused_variables)]
290+
async fn handle_multipart_related_request_post<T, C, ReqBody>(
291+
mut api_impl: T,
292+
uri: hyper::Uri,
293+
headers: HeaderMap,
294+
body: ReqBody,
295+
context: C,
296+
validation: bool,
297+
multipart_form_size_limit: Option<u64>,
298+
) -> Result<Response<BoxBody<Bytes, Infallible>>, crate::ServiceError>
299+
where
300+
T: Api<C> + Clone + Send + 'static,
301+
C: Has<XSpanIdString> + Send + Sync + 'static,
302+
ReqBody: Body + Send + 'static,
303+
ReqBody::Error: Into<Box<dyn Error + Send + Sync>> + Send,
304+
ReqBody::Data: Send,
305+
{
259306
// Handle body parameters (note that non-required body parameters will ignore garbage
260307
// values, rather than causing a 400 response). Produce warning header and logs for
261308
// any unused fields.
@@ -383,10 +430,25 @@ impl<T, C, ReqBody> hyper::service::Service<(Request<ReqBody>, C)> for Service<T
383430
.body(body_from_string(format!("Unable to read body: {}", e.into())))
384431
.expect("Unable to create Bad Request response due to unable to read body")),
385432
}
386-
},
433+
}
387434

388-
// MultipartRequestPost - POST /multipart_request
389-
hyper::Method::POST if path.matched(paths::ID_MULTIPART_REQUEST) => {
435+
#[allow(unused_variables)]
436+
async fn handle_multipart_request_post<T, C, ReqBody>(
437+
mut api_impl: T,
438+
uri: hyper::Uri,
439+
headers: HeaderMap,
440+
body: ReqBody,
441+
context: C,
442+
validation: bool,
443+
multipart_form_size_limit: Option<u64>,
444+
) -> Result<Response<BoxBody<Bytes, Infallible>>, crate::ServiceError>
445+
where
446+
T: Api<C> + Clone + Send + 'static,
447+
C: Has<XSpanIdString> + Send + Sync + 'static,
448+
ReqBody: Body + Send + 'static,
449+
ReqBody::Error: Into<Box<dyn Error + Send + Sync>> + Send,
450+
ReqBody::Data: Send,
451+
{
390452
// Handle body parameters (note that non-required body parameters will ignore garbage
391453
// values, rather than causing a 400 response). Produce warning header and logs for
392454
// any unused fields.
@@ -571,10 +633,25 @@ impl<T, C, ReqBody> hyper::service::Service<(Request<ReqBody>, C)> for Service<T
571633
.body(body_from_string(format!("Unable to read body: {}", e.into())))
572634
.expect("Unable to create Bad Request response due to unable to read body")),
573635
}
574-
},
636+
}
575637

576-
// MultipleIdenticalMimeTypesPost - POST /multiple-identical-mime-types
577-
hyper::Method::POST if path.matched(paths::ID_MULTIPLE_IDENTICAL_MIME_TYPES) => {
638+
#[allow(unused_variables)]
639+
async fn handle_multiple_identical_mime_types_post<T, C, ReqBody>(
640+
mut api_impl: T,
641+
uri: hyper::Uri,
642+
headers: HeaderMap,
643+
body: ReqBody,
644+
context: C,
645+
validation: bool,
646+
multipart_form_size_limit: Option<u64>,
647+
) -> Result<Response<BoxBody<Bytes, Infallible>>, crate::ServiceError>
648+
where
649+
T: Api<C> + Clone + Send + 'static,
650+
C: Has<XSpanIdString> + Send + Sync + 'static,
651+
ReqBody: Body + Send + 'static,
652+
ReqBody::Error: Into<Box<dyn Error + Send + Sync>> + Send,
653+
ReqBody::Data: Send,
654+
{
578655
// Handle body parameters (note that non-required body parameters will ignore garbage
579656
// values, rather than causing a 400 response). Produce warning header and logs for
580657
// any unused fields.
@@ -677,23 +754,6 @@ impl<T, C, ReqBody> hyper::service::Service<(Request<ReqBody>, C)> for Service<T
677754
.body(body_from_string(format!("Unable to read body: {}", e.into())))
678755
.expect("Unable to create Bad Request response due to unable to read body")),
679756
}
680-
},
681-
682-
_ if path.matched(paths::ID_MULTIPART_RELATED_REQUEST) => method_not_allowed(),
683-
_ if path.matched(paths::ID_MULTIPART_REQUEST) => method_not_allowed(),
684-
_ if path.matched(paths::ID_MULTIPLE_IDENTICAL_MIME_TYPES) => method_not_allowed(),
685-
_ => Ok(Response::builder().status(StatusCode::NOT_FOUND)
686-
.body(BoxBody::new(http_body_util::Empty::new()))
687-
.expect("Unable to create Not Found response"))
688-
}
689-
}
690-
Box::pin(run(
691-
self.api_impl.clone(),
692-
req,
693-
self.validation,
694-
self.multipart_form_size_limit
695-
))
696-
}
697757
}
698758

699759
/// Request parser for `Api`.

samples/server/petstore/rust-server/output/no-example-v3/src/server/mod.rs

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,39 @@ impl<T, C, ReqBody> hyper::service::Service<(Request<ReqBody>, C)> for Service<T
219219

220220
// OpGet - GET /op
221221
hyper::Method::GET if path.matched(paths::ID_OP) => {
222+
handle_op_get(api_impl, uri, headers, body, context, validation).await
223+
},
224+
225+
_ if path.matched(paths::ID_OP) => method_not_allowed(),
226+
_ => Ok(Response::builder().status(StatusCode::NOT_FOUND)
227+
.body(BoxBody::new(http_body_util::Empty::new()))
228+
.expect("Unable to create Not Found response"))
229+
}
230+
}
231+
Box::pin(run(
232+
self.api_impl.clone(),
233+
req,
234+
self.validation
235+
))
236+
}
237+
}
238+
239+
#[allow(unused_variables)]
240+
async fn handle_op_get<T, C, ReqBody>(
241+
mut api_impl: T,
242+
uri: hyper::Uri,
243+
headers: HeaderMap,
244+
body: ReqBody,
245+
context: C,
246+
validation: bool,
247+
) -> Result<Response<BoxBody<Bytes, Infallible>>, crate::ServiceError>
248+
where
249+
T: Api<C> + Clone + Send + 'static,
250+
C: Has<XSpanIdString> + Send + Sync + 'static,
251+
ReqBody: Body + Send + 'static,
252+
ReqBody::Error: Into<Box<dyn Error + Send + Sync>> + Send,
253+
ReqBody::Data: Send,
254+
{
222255
// Handle body parameters (note that non-required body parameters will ignore garbage
223256
// values, rather than causing a 400 response). Produce warning header and logs for
224257
// any unused fields.
@@ -292,20 +325,6 @@ impl<T, C, ReqBody> hyper::service::Service<(Request<ReqBody>, C)> for Service<T
292325
.body(body_from_string(format!("Unable to read body: {}", e.into())))
293326
.expect("Unable to create Bad Request response due to unable to read body")),
294327
}
295-
},
296-
297-
_ if path.matched(paths::ID_OP) => method_not_allowed(),
298-
_ => Ok(Response::builder().status(StatusCode::NOT_FOUND)
299-
.body(BoxBody::new(http_body_util::Empty::new()))
300-
.expect("Unable to create Not Found response"))
301-
}
302-
}
303-
Box::pin(run(
304-
self.api_impl.clone(),
305-
req,
306-
self.validation
307-
))
308-
}
309328
}
310329

311330
/// Request parser for `Api`.

samples/server/petstore/rust-server/output/openapi-v3/src/client/callbacks.rs

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,45 @@ impl<T, C, ReqBody> hyper::service::Service<(Request<ReqBody>, C)> for Service<T
233233

234234
// CallbackCallbackWithHeaderPost - POST /{$request.query.url}/callback-with-header
235235
hyper::Method::POST if path.matched(paths::ID_REQUEST_QUERY_URL_CALLBACK_WITH_HEADER) => {
236+
handle_callback_callback_with_header_post(api_impl, uri, headers, body, context, validation).await
237+
},
238+
239+
// CallbackCallbackPost - POST /{$request.query.url}/callback
240+
hyper::Method::POST if path.matched(paths::ID_REQUEST_QUERY_URL_CALLBACK) => {
241+
handle_callback_callback_post(api_impl, uri, headers, body, context, validation).await
242+
},
243+
244+
_ if path.matched(paths::ID_REQUEST_QUERY_URL_CALLBACK) => method_not_allowed(),
245+
_ if path.matched(paths::ID_REQUEST_QUERY_URL_CALLBACK_WITH_HEADER) => method_not_allowed(),
246+
_ => Ok(Response::builder().status(StatusCode::NOT_FOUND)
247+
.body(BoxBody::new(http_body_util::Empty::new()))
248+
.expect("Unable to create Not Found response"))
249+
}
250+
}
251+
Box::pin(run(
252+
self.api_impl.clone(),
253+
req,
254+
self.validation
255+
))
256+
}
257+
}
258+
259+
#[allow(unused_variables)]
260+
async fn handle_callback_callback_with_header_post<T, C, ReqBody>(
261+
mut api_impl: T,
262+
uri: hyper::Uri,
263+
headers: HeaderMap,
264+
body: ReqBody,
265+
context: C,
266+
validation: bool,
267+
) -> Result<Response<BoxBody<Bytes, Infallible>>, crate::ServiceError>
268+
where
269+
T: Api<C> + Clone + Send + 'static,
270+
C: Has<XSpanIdString> + Send + Sync + 'static,
271+
ReqBody: Body + Send + 'static,
272+
ReqBody::Error: Into<Box<dyn Error + Send + Sync>> + Send,
273+
ReqBody::Data: Send,
274+
{
236275
// Path parameters
237276
let path: &str = uri.path();
238277
let path_params =
@@ -291,10 +330,24 @@ impl<T, C, ReqBody> hyper::service::Service<(Request<ReqBody>, C)> for Service<T
291330
}
292331

293332
Ok(response)
294-
},
333+
}
295334

296-
// CallbackCallbackPost - POST /{$request.query.url}/callback
297-
hyper::Method::POST if path.matched(paths::ID_REQUEST_QUERY_URL_CALLBACK) => {
335+
#[allow(unused_variables)]
336+
async fn handle_callback_callback_post<T, C, ReqBody>(
337+
mut api_impl: T,
338+
uri: hyper::Uri,
339+
headers: HeaderMap,
340+
body: ReqBody,
341+
context: C,
342+
validation: bool,
343+
) -> Result<Response<BoxBody<Bytes, Infallible>>, crate::ServiceError>
344+
where
345+
T: Api<C> + Clone + Send + 'static,
346+
C: Has<XSpanIdString> + Send + Sync + 'static,
347+
ReqBody: Body + Send + 'static,
348+
ReqBody::Error: Into<Box<dyn Error + Send + Sync>> + Send,
349+
ReqBody::Data: Send,
350+
{
298351
// Path parameters
299352
let path: &str = uri.path();
300353
let path_params =
@@ -332,21 +385,6 @@ impl<T, C, ReqBody> hyper::service::Service<(Request<ReqBody>, C)> for Service<T
332385
}
333386

334387
Ok(response)
335-
},
336-
337-
_ if path.matched(paths::ID_REQUEST_QUERY_URL_CALLBACK) => method_not_allowed(),
338-
_ if path.matched(paths::ID_REQUEST_QUERY_URL_CALLBACK_WITH_HEADER) => method_not_allowed(),
339-
_ => Ok(Response::builder().status(StatusCode::NOT_FOUND)
340-
.body(BoxBody::new(http_body_util::Empty::new()))
341-
.expect("Unable to create Not Found response"))
342-
}
343-
}
344-
Box::pin(run(
345-
self.api_impl.clone(),
346-
req,
347-
self.validation
348-
))
349-
}
350388
}
351389

352390
/// Request parser for `Api`.

0 commit comments

Comments
 (0)