-
-
Notifications
You must be signed in to change notification settings - Fork 6.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BUG][Rust][client][reqwest] Wrong representation of binary body (octet-stream) in request/response #18117
Comments
What do you think about first making a MVP that would work with We could have the generated code looking like for the download ? pub async fn download_get(configuration: &configuration::Configuration, ) -> Result<Vec<u8>, Error<DownloadGetError>> {
let local_var_configuration = configuration;
let local_var_client = &local_var_configuration.client;
let local_var_uri_str = format!("{}/download", local_var_configuration.base_path);
let mut local_var_req_builder = local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
}
let local_var_req = local_var_req_builder.build()?;
let local_var_resp = local_var_client.execute(local_var_req).await?;
let local_var_status = local_var_resp.status();
if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
let bytes = local_var_resp.bytes().await?;
Ok(bytes.into_iter().collect())
} else {
let local_var_content = local_var_resp.text().await?;
let local_var_entity: Option<DownloadGetError> = serde_json::from_str(&local_var_content).ok();
let local_var_error = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
Err(Error::ResponseError(local_var_error))
}
} |
That's definitely much better than current implementation - it will work at least. So it could be a first iteration, but doesn't solve the issue. It worth mentioning, that it generates not really secure client - Also, starting with |
Wouldn't the Should we try to keep the same types for reqwest and hyper ? I think neither support this now Also we have to make sure it also work when |
Yes, but that could be just a valid utf-8 file(e.g CSV) or even compromised data. I'm just saying both methods (
That's a good question, I do not think we have to, because these clients are in general operate with different types.
Yes, that's also fair point. And here we don't have many options, that's why returning I just find this more flexible, however it can be confusing why |
I get why we would like to return
The thing is that now this type is also expected when you want to send file or binary data This is the produced code pub async fn upload_post(configuration: &configuration::Configuration, body: reqwest::Response) -> Result<(), Error<UploadPostError>> {
let local_var_configuration = configuration;
let local_var_client = &local_var_configuration.client;
let local_var_uri_str = format!("{}/upload", local_var_configuration.base_path);
let mut local_var_req_builder = local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
}
local_var_req_builder = local_var_req_builder.body(body);
let local_var_req = local_var_req_builder.build()?;
let local_var_resp = local_var_client.execute(local_var_req).await?;
let local_var_status = local_var_resp.status();
if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
Ok(())
} else {
let local_var_content = local_var_resp.text().await?;
let local_var_entity: Option<UploadPostError> = serde_json::from_str(&local_var_content).ok();
let local_var_error = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
Err(Error::ResponseError(local_var_error))
}
}
It probably means we need a custom type inside the crate (or an existing one), what do you think ? |
Yes, this one is tricky, for client side we need to have another type here, and I believe it should be In fact, I'd prefer to return something like Body for responses too, but But I think it's pretty good middle ground to go with |
I think doing this modification will break the current multipart implementation as it uses the file method with the PathBuf input type |
Yes, we also need to distinguish Example in the issue is about And AFAIK there is already a check for that: |
Any progress regarding this issue? It would be good to just return bytes of the incoming file or something |
@Gaelik-git I see you already started a PR. Is there any chance you finish it? Otherwise I can look into it. |
Sorry I don't have time to work on this right now |
@DDtKey Hi, I created a new PR with the same code as @Gaelik-git to reproduce the errors he got and from what I can see, the main issue now is that, when setting the Do you have any tips regarding how to use a different type for the upload and download types? |
I think we have an option to control this on the level of mustache templates at least 🤔 , with checks like Probably there is a better way, but I will need to recall & double check the current structure |
@DDtKey Thanks for the quick reply! Actually, I just noticed that that's what @Gaelik-git did and it worked in When it fails, it looks like we enter the case where I'll investigate these differences. |
So we need to handle the situation where However, putting
So I'm wondering if we really want to support returning a response enum when the endpoint returns a file, even if |
@DDtKey For the moment I have implemented the following changes in #20031:
Do you think this approach is okay? |
Hi @ThomasVille, I find this reasonable at this stage, because currently it doesn't work at all and we have some working compromise. Personally, I vote for accepting this approach as first step forward. Thank you! |
Bug Report Checklist
Description
Currently any binaries in generate client for rust (with reqwest library at least) uses
std::path::PathBuf
.And several issues here:
E.g for request it generates the following code:
And for response it's even worse:
openapi-generator version
7.4.0
/7.3.0
and likely earlier versionsOpenAPI declaration file content or url
Generation Details
No special configs, just
generate -i ./test.yaml -g rust --package-name stream-test -o ./out --library reqwest
Steps to reproduce
reqwest
libraryRelated issues/PRs
Suggest a fix
First thought could be to use reqwest::Body - but it doesn't cover streaming of response (at least for reqwest
0.11.x
). OnlyResponse
itself can be converted with bytes_stream. As well as into bytes.But it's possible to wrap a
Stream
toreqwest::Body
.So I think it would be correct to go with this way:
reqwest::Body
(orInto<Body>
) if it's expected as a body of the requestreqwest::Response
if output type is binary (could be wrapper though, which containsStream
+headers
for example)The text was updated successfully, but these errors were encountered: