Skip to content

Commit 2569321

Browse files
feat: add async file stream support for reqwest client (#21771)
1 parent dbe0419 commit 2569321

File tree

27 files changed

+625
-559
lines changed

27 files changed

+625
-559
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,7 @@ public void postProcessParameter(CodegenParameter parameter) {
672672
@Override
673673
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> allModels) {
674674
OperationMap objectMap = objs.getOperations();
675+
boolean useAsyncFileStream = false;
675676
List<CodegenOperation> operations = objectMap.getOperation();
676677
for (CodegenOperation operation : operations) {
677678
if (operation.pathParams != null && operation.pathParams.size() > 0) {
@@ -707,6 +708,17 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
707708
}
708709
}
709710

711+
// If we use a file parameter, we need to include the imports and crates for it
712+
// But they should be added only once per file
713+
for (var param: operation.allParams) {
714+
if (param.isFile && supportAsync && !useAsyncFileStream) {
715+
useAsyncFileStream = true;
716+
additionalProperties.put("useAsyncFileStream", Boolean.TRUE);
717+
operation.vendorExtensions.put("useAsyncFileStream", Boolean.TRUE);
718+
break;
719+
}
720+
}
721+
710722
// http method verb conversion, depending on client library (e.g. Hyper: PUT => Put, Reqwest: PUT => put)
711723
if (HYPER_LIBRARY.equals(getLibrary())) {
712724
operation.httpMethod = StringUtils.camelize(operation.httpMethod.toLowerCase(Locale.ROOT));

modules/openapi-generator/src/main/resources/rust/Cargo.mustache

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,14 @@ reqwest-middleware = { version = "^0.4", features = ["json", "blocking", "multip
6969
{{/supportMiddleware}}
7070
{{/supportAsync}}
7171
{{#supportAsync}}
72+
{{#useAsyncFileStream}}
73+
tokio = { version = "^1.46.0", features = ["fs"] }
74+
tokio-util = { version = "^0.7", features = ["codec"] }
75+
reqwest = { version = "^0.12", default-features = false, features = ["json", "multipart", "stream"] }
76+
{{/useAsyncFileStream}}
77+
{{^useAsyncFileStream}}
7278
reqwest = { version = "^0.12", default-features = false, features = ["json", "multipart"] }
79+
{{/useAsyncFileStream}}
7380
{{#supportMiddleware}}
7481
reqwest-middleware = { version = "^0.4", features = ["json", "multipart"] }
7582
{{/supportMiddleware}}

modules/openapi-generator/src/main/resources/rust/reqwest/api.mustache

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ use reqwest;
44
use serde::{Deserialize, Serialize, de::Error as _};
55
use crate::{apis::ResponseContent, models};
66
use super::{Error, configuration, ContentType};
7+
{{#operations}}
8+
{{#operation}}
9+
{{#vendorExtensions.useAsyncFileStream}}
10+
use tokio::fs::File as TokioFile;
11+
use tokio_util::codec::{BytesCodec, FramedRead};
12+
{{/vendorExtensions.useAsyncFileStream}}
13+
{{/operation}}
14+
{{/operations}}
715

816
{{#operations}}
917
{{#operation}}
@@ -445,7 +453,23 @@ pub {{#supportAsync}}async {{/supportAsync}}fn {{{operationId}}}(configuration:
445453
{{#hasBodyParam}}
446454
{{#bodyParams}}
447455
{{#isFile}}
456+
{{#supportAsync}}
457+
{{#required}}
458+
let file = TokioFile::open({{{vendorExtensions.x-rust-param-identifier}}}).await?;
459+
let stream = FramedRead::new(file, BytesCodec::new());
460+
req_builder = req_builder.body(reqwest::Body::wrap_stream(stream));
461+
{{/required}}
462+
{{^required}}
463+
if let Some(param_value) = {{{vendorExtensions.x-rust-param-identifier}}} {
464+
let file = TokioFile::open(param_value).await?;
465+
let stream = FramedRead::new(file, BytesCodec::new());
466+
req_builder = req_builder.body(reqwest::Body::wrap_stream(stream));
467+
}
468+
{{/required}}
469+
{{/supportAsync}}
470+
{{^supportAsync}}
448471
req_builder = req_builder.body({{{vendorExtensions.x-rust-param-identifier}}});
472+
{{/supportAsync}}
449473
{{/isFile}}
450474
{{^isFile}}
451475
req_builder = req_builder.json(&{{{vendorExtensions.x-rust-param-identifier}}});
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# file_streaming_test.yaml
2+
swagger: "2.0"
3+
info:
4+
title: File Streaming Test API
5+
version: 1.0.0
6+
7+
paths:
8+
/upload:
9+
post:
10+
consumes:
11+
- application/octet-stream
12+
description: Upload a file from the local filesystem
13+
operationId: uploadFile
14+
parameters:
15+
- description: A test file
16+
in: body
17+
name: inputStream
18+
schema:
19+
format: binary
20+
type: string
21+
responses:
22+
'200':
23+
description: Success

0 commit comments

Comments
 (0)