-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
[Rust][Client] Multiple returns becomes optional (fixes #6650). #6673
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
[Rust][Client] Multiple returns becomes optional (fixes #6650). #6673
Conversation
| let entity: Option<UploadFileSuccess> = serde_json::from_str(&content).ok(); | ||
| let result = ResponseContent { status, content, entity }; | ||
| Ok(result) | ||
| serde_json::from_str(&content).map_err(Error::from) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing Ok() also i tried testing locally, didn't work for me:
java -jar ./modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g rust -i slack_web_modified.json -o slack --skip-validate-spec --remove-operation-id-prefix --library reqwest --additional-properties useSingleRequestParameter=true,supportAsync=true,supportMultipleReturns=true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi,
I generated a slack client from official Github JSON with the same parameters as yours:
java -jar ./modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g rust -i https://raw.githubusercontent.com/slackapi/slack-api-specs/master/web-api/slack_web_openapi_v2.json -o /tmp/slack --skip-validate-spec --remove-operation-id-prefix --library reqwest --additional-properties useSingleRequestParameter=true,supportAsync=true,supportMultipleReturns=true
The client compiles and works fine: can you provide some information to reproduce the problem?
PS: in issue #6650, @HenningHolmDE tested the commit with and without the new param and didn't notice a problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the code serde_json::from_str(&content).map_err(Error::from) you quoted, Ok() is not missing, since this line produces the expected return type Result<Entity, Error>.
This line is equivalent to Ok(serde_json::from_str(&content)?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
supportMultipleReturns=false
this was the only thing that worked for me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have an example OAS to reproduce your problem?
I have a compiling client (with Rust 1.44.0 and both values for supportMultipleReturns).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, using that spec file also works for me (rust stable as well as nightly):
java -jar ./modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g rust -i https://gist.githubusercontent.com/wing328/61225b4ad2d838447340a70494e09333/raw/b42fa7cf01df2a9269b910d19393a96081a246ff/slack_web_modified.json -o slack --skip-validate-spec --remove-operation-id-prefix --library reqwest --additional-properties useSingleRequestParameter=true,supportAsync=true,supportMultipleReturns=true
cd slack
cargo check
> Finished dev [unoptimized + debuginfo] target(s) in 0.14s
Or is the problem related to function instead of compilation?
|
I think the last thing here is to remove the unknown value/list variants from the error type. The api specification defines all possible response schemas. So those variants are redundant. |
Wouldn't it be useful to be able to access the data if the response type is unexpected? (This is of course an error, but we are talking error handling here.) (Just my two cents as I was mentioned erlier and got the notfication for the comment.) |
That's what we're doing at the moment in other clients to include the response payload in the error response object (e.g. ApiException class) so the developers can find out more clues on why the error occurs from the response payload. |
yeah, I understand your reasoning. @bcourtine let's limit it to just |
| Ok(result) | ||
| serde_json::from_str(&content).map_err(Error::from) | ||
| } else { | ||
| let entity: Option<FileresponsetestError> = serde_json::from_str(&content).ok(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in light of this, I don't think it's possible for serde_json::from_str() to fail because you've already covered serde_json::Value
ResponseContent should become:
struct ResponseContent {
entity: T,
status: StatusCode,
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you pointed out, the call to serde_json::from_str() won't fail due to unexpected Types as we have covered serde_json::Value - but it might fail when content does not contain valid JSON.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, then we should use the response.json() method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid this will not help, as in case of invalid JSON reqwest::Response.json() will also fail:
pub async fn json<T: DeserializeOwned>(self) -> Result<T>
Try to deserialize the response body as JSON.
[...]
Errors
This method fails whenever the response body is not in JSON format or it cannot be properly deserialized to target typeT. For more details please seeserde_json::from_reader.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes but then we already have an error for reqwest defined.
#[derive(Debug)]
pub enum Error<T> {
Reqwest(reqwest::Error),
Serde(serde_json::Error),
Io(std::io::Error),
ResponseError(ResponseContent<T>),
}so code becomes
let status = resp.status();
if status.is_success() {
// would recommend using derive_more::From for the error type
Ok(response.json().await.map_err(Error::Reqwest)?)
} else {
let entity: CloseError = response.json().await.map_err(Error::Reqwest)?;
let error = ResponseContent { status, entity };
Err(Error::ResponseError(error))
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hopefully, @bcourtine's comment clarifies things @HenningHolmDE
to clarify further:
What I'm advocating for is removing the
contentfield inResponseContent
because:
since the response content is malformed JSON, the only thing useful to do with it is: log to stdout/err
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since the response content is malformed JSON, the only thing useful to do with it is: log to stdout/err
It may or may not be malformed. We've seen issues in which a different type of object was returned (e.g. expecting array of Dog but get a single Dog, expecting a Cat but get a Dog due to invalid spec, expecting JSON but got XML as XML is the default when accept is not specified in the request header in that particular case) so my recommendation is still to include it in the Error response object to make developer's life easier in troubleshooting what's wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was under the impression that logging the reqwest Error had the response text, but after testing i just confirmed it doesn't so this is fine.
include it in the Error response object to make developer's life easier in troubleshooting what's wrong.
I think that's the last thing, we can finally get this merged? 🎊 🥳
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's the last thing, we can finally get this merged? 🎊 🥳
No objections from my side. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 👍 👍
@bcourtine Please update the doc as well when you've time. |
|
Any chance we can get this merged today? |
|
Just pushed ae1a050 to resolve the CI failure. Will merge if all tests pass. |
By default, rust client (using Reqwest) returns a simple return type. Handling multiple returns (several 2xx codes is optional).
PR checklist
./bin/generate-samples.shto update all Petstore samples related to your fix. This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master. These must match the expectations made by your contribution. You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example./bin/generate-samples.sh bin/config/java*. For Windows users, please run the script in Git BASH.mastercc @frol (2017/07) @farcaller (2017/08) @bjgill (2017/12) @richardwhiuk (2019/07) @paladinzh (2020/05) @wing328