-
-
Notifications
You must be signed in to change notification settings - Fork 7k
#1023 - [Scala] Use status family during response processing #1024
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
#1023 - [Scala] Use status family during response processing #1024
Conversation
Thanks for the PR but your commit (as shown in the Commits tab) is not linked to your Github account, which means this PR won't count as your contribution in https://github.com/OpenAPITools/openapi-generator/graphs/contributors. Let me know if you need help fixing it. |
Yes, that will be very nice if you will help me to fix this. Thank you! |
val status = Response.Status.fromStatusCode(resp.statusCode) | ||
status.getFamily match { | ||
case Family.SUCCESSFUL => process(reader.read(resp)) | ||
case _ => throw new ApiException(resp.statusCode, resp.statusText) |
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.
it's semantically incorrect to treat informational and redirection as errors. there is valuable information in the headers that should be sent back to the client. for instance, when you get a redirect, the header location will tell you where to go. can you please shed some light on the motivation for this change?
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.
You're right, I pushed a fix for informational and redirection statuses, please take a look.
… REDIRECTION & INFORMATIONAL support
|
||
# IntelliJ specific | ||
.idea | ||
*.iml |
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.
*.iml
should not be ignored. See reasoning: toptal/gitignore.io#186 (comment)
process(reader.read(resp)) | ||
val status = Response.Status.fromStatusCode(resp.statusCode) | ||
status.getFamily match { | ||
case Family.SUCCESSFUL | Family.REDIRECTION | Family.INFORMATIONAL => process(reader.read(resp)) |
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.
This assumes that a 1xx and 3xx status results in the same body structure as a 2xx message. I doubt this will ever be the case, and this would most likely always result in an deserialization error.
Unfortunately, I don't have a great solution to this. I left these cases as TODOs that throw not-implemented exceptions in the Kotlin client:
return when (response.responseType) {
ResponseType.Success -> {{#returnType}}(response as Success<*>).data as {{{returnType}}}{{/returnType}}{{^returnType}}Unit{{/returnType}}
ResponseType.Informational -> TODO()
ResponseType.Redirection -> TODO()
ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error")
ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error")
else -> throw kotlin.IllegalStateException("Undefined ResponseType.")
}
What makes these cases difficult is the potentially different type structure for all response families and the lack of common response structures for those status codes that support response bodies. In Scala, we could maybe solve this with an Either[A,B]
, but I've never liked that pattern for potentially unlikely use cases. While it's true that informational and redirects are not errors, I'm inclined to create a typed exception along the lines of the ClientException
and ServerException
that exist in the kotlin client code from above. One could argue that the result of calling an API invocation method is expected to be Family.SUCCESSFUL
and all other families are unexpected, with maybe 2 or 3 special cases.
A reason I am comfortable leaving these to throw exceptions in the kotlin client is that I haven't personally seen a use case for a majority of the 1xx and 3xx statuses. The few others would require some standardized way of handling them across all generators.
Informational
100 Continue
occurs after the server receives the request headers and determines whether or not it will continue processing. If the client sends the headersExpect: 100-Continue
, then it should handle waiting for the server's response. If the client didn't send this header, RFC 7231 Section 6.2.1 says the interim response can safely be ignored. All of this requires the server to support100 Continue
.101 Switching Protocols
would occur if upgrading from HTTP 1.1 to 2.0, or doing a switch from HTTP to websockets, or other similar "upgrades". I've never experienced the first case implemented correctly by a REST API, and I don't know that the second case would be supported by an HTTP Client.102 Processing
is a WebDAV extension (see RFC 2518 Section10.1), so I consider it a low priority (if any) to support.
Redirection
300 Multiple Choices
occurs when a server has multiple representations of a selected resource. The spec says that a non-HEAD request SHOULD provide a body explaining these representations (source). However, this is supposed to be either left up to the user agent or the user directly. The body logically wouldn't have the same structure as a 2xx body, so this would result in a deserialization error.301 Moved Permanently
with no standardized way to define where the resource has moved (spec only says it SHOULD be inLocation
header), I think an exception is most sufficient here because it indicates that the API for which the client was generated has changed. We could redirect to a new location if the header is present, but this begs the question about what else has changed with the underlying API; a blind redirect could potentially result in bad data or a loss of data (e.g. if request body has changed structure and server drops unknown properties).302 Found
I've never seen this used without automatically following redirects. If we receive this, the new location would be in theLocation
header, and we could automatically re-query… but the specification says the client should continue using the original Request-URI and suggests that the new URI be considered temporary or able to change in the future. So aside from potentially following aLocation
header, the spec suggests we could leave this as-is.303 See Other
indicates the server wants you to perform aGET
request to some other URI. This could result in a different deserialized type, so this type of redirect would need to be defined in theresponses
object of the OpenAPI specification. The likelihood that this happens (an API defines a successful type as well as a 'see this other endpoint' definition) is pretty slim.304 Not Modified
would indicate that the client can use a cache of its previously known copy of an object. I don't know that any of our client generators have client-side caching built in, so I doubt we're supporting 304s outside of whatever support exists in specific client frameworks. Also, 304s are not allowed to contain bodies, soprocess(reader.read(resp))
would fail.305 Use Proxy
: requires querying via proxy defined in theLocation
header. I understand 305 is widely considered a security concern, and is therefore not very common.307 Temporary Redirect
and308 Permanent Redirect
: being redirects, I would think the http-client framework would handle these directly.
@luzhanov thanks for the PR, which has been merged into master. The scala-httpclient generator has been deprecated since it's depending on an unmaintained HTTP lib. Please switch to scala-akka instead. |
* master: (48 commits) [Typescript AngularJS] fix Extra package prefix in api parameters operations (OpenAPITools#2522) OpenAPITools#1023 - [Scala] Use status family during response processing (OpenAPITools#1024) Generate setters for readonly properties in server code (OpenAPITools#1582) [JS] fix NPE for null string and improve Travis config file (OpenAPITools#2553) [elm] Update ISO 8601 library (fixes missing time zone designator) (OpenAPITools#2545) [csharp] update sample after OpenAPITools#2528 (OpenAPITools#2550) [JavaScript] fix index.js, ApiClient.js and test files generated to incorrect location (OpenAPITools#2511) Aspnetcore nullable support (OpenAPITools#2529) Csharp nullable support (OpenAPITools#2528) [C++] [Qt5] Add enum support for client and server (OpenAPITools#2339) Fixed typo in migration-from-swagger-codegen.md (OpenAPITools#2548) [TypeScript Client] fix install Aurelia + fix use deprecated function (OpenAPITools#2514) [KOTLIN] fix var name not correctly sanitized (OpenAPITools#2537) Update swagger-parser to '2.0.11-OpenAPITools.org-1' (OpenAPITools#2262) Add @karismann to Java and Kotlin technical committee (OpenAPITools#2542) Add GoDaddy to the list of companies using OpenAPI Generator (OpenAPITools#2541) [Kotlin SpringBoot Server] alternative: fix optional parameter not correctly declared in service (OpenAPITools#2539) improve indentation, update dependencies (OpenAPITools#2521) update kotlin spring samples [JAVA] Use specified data type in enum's fromValue instead of string (OpenAPITools#2347) ...
* master: (133 commits) #2503: fix out-of-memory issue with nested objects with arrays with maxItems set by limiting to max. 5 example items (#2536) remove emitDefaultValue option (#2559) fix EmitDefaultValue default vallue with false (#2558) Added API Key auth to rust-server (#2459) remove initialCaps and replace with camelize (#2546) Add packageName configuration to maven (#2429) [Typescript AngularJS] fix Extra package prefix in api parameters operations (#2522) #1023 - [Scala] Use status family during response processing (#1024) Generate setters for readonly properties in server code (#1582) [JS] fix NPE for null string and improve Travis config file (#2553) [elm] Update ISO 8601 library (fixes missing time zone designator) (#2545) [csharp] update sample after #2528 (#2550) [JavaScript] fix index.js, ApiClient.js and test files generated to incorrect location (#2511) Aspnetcore nullable support (#2529) Csharp nullable support (#2528) [C++] [Qt5] Add enum support for client and server (#2339) Fixed typo in migration-from-swagger-codegen.md (#2548) [TypeScript Client] fix install Aurelia + fix use deprecated function (#2514) [KOTLIN] fix var name not correctly sanitized (#2537) Update swagger-parser to '2.0.11-OpenAPITools.org-1' (#2262) ...
PR checklist
./bin/
to update Petstore sample so that CIs can verify the change. (For instance, only need to run./bin/{LANG}-petstore.sh
and./bin/security/{LANG}-petstore.sh
if updating the {LANG} (e.g. php, ruby, python, etc) code generator or {LANG} client's mustache templates). Windows batch files can be found in.\bin\windows\
.master
,3.3.x
,4.0.x
. Default:master
.@clasnake @jimschubert @shijinkui @ramzimaalej
Description of the PR
Issue: #1023