-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Adjust serializer selection fallback procedure #2147
Adjust serializer selection fallback procedure #2147
Conversation
In summary: 1. Choose by request type only when the server didn't provide a content type and it wasn't possible to detect it 2. If the server did provide a content type but we don't have a deserializer for it, try detection as a fallback
@dotnet-policy-service agree |
Looks good 👍 |
Adding a couple of tests would be nice. Mock a response with an incorrect content type, and see if it will work. |
The case how I came to it was this:
|
Alternative approaches I was considering: 1. Disable fallbacks for deserializer selection in case of HTTP errorsThis was the initial idea for changing Eventually, I realized that the applied logic is not ideal, even in non-error cases, which is why I preferred the general change of behavior proposed by this PR. 2. Change handling of deserialization exceptions In case of HTTP errorsI think it is correct to deserialize content (if present) even in case of HTTP errors. The behavior for throwing exceptions, which is controlled by What I'm wondering though, is whether it might be better to implement a slightly different handling in case of HTTP errors, where the HTTP error is typically the primary subject of interest. Which means, in case of HTTP errors
ConcludingI'm not sure what you think - |
Often when the server returns an error, it also returns something like problem details response. The issue atm is there's no de-factor standard for such responses. We can say "ok, let's assume it's problem details". Well, basically, problem detail response has a custom content type, so it might make sense to add a special path for that, should be relatively easy to do. If you get an error from something like Express, it has its own, quite well-know JSON format, but it has no definition as a standard. I was thinking a while ago how to make the client to expect one type for success and another for errors, but generic type constraints in C# make the code quite verbose. That's the reason I made content deserialisation function public, so one can check if the request was not successful (status code) and try deserialising content as an error. If I understand you correctly, in brief, if there's a server error, we should keep trying to deserialise the response content, but we can obviously expect that the JSON response is either missing, or it has a different schema (like problem details). So, deserialisation will most probably fail, but the user gets the deserialisation error instead of the actual error. Changing ti makes total sense to me. I'd say we can do the following:
I can suggest making the first part done in this PR, and open an issue for the second part, address it in a different PR |
If you mean by "de-facto standard" that every API is behaving differently, then that is true. But the OpenAPI standard covers this pretty well and explicitly leaves room for all kinds of different behavior. With OpenAPI, you can define a different response schema (model) for different HTTP status codes - which can also be a plain string.
Yes, I think that makes the most sense.
I think this PR makes the most sense in the first place.. And on top of that we could modify the behavior in error case in the following ways:
|
Summary:
Rationale
If we do have some indication about the content type, either from the response header or from detection, then there's no reason to ignore that information, just because we have no deserializer for it available. If we don't have a matching one for the given situation and parameters, then that's a fact, but it's logically not valid to choose a deserializer by request type.
Now, one might argue that servers are sometimes sending invcorrect headers, which is true of course, but for the case of a possibly (we don't know, we only know that we have no deserializer for it) incorrect header, we can use a better fallback: we can try to detect - which is currently only happening when there's no content tpye indicated by the server.
Doing this as a fallback makes more sense, because when our assumption (built on thin ice) would be true, we should at least get a different detection result than what the server indicates.
If that's not the case, then we can surely stop, because the probabiliy of 2 chances failing coincidently is near zero.
Simple word example: when the server says it's not Json and our detection doesn't say it's Json, then there's really no point in assuming that it's Json - even when the RequestType was Json.
So, using the RequestType for selection when we already have contradicting evidence is not quite valid. But there is in fact a case where it makes sense to use it as fallback, and that's cases where we have nothing at all: No server header and no result from detection. When we know nothing at all, then the RequestType will be our best bet.
This PR is re-ordering the selection logic according to the above.
Please let me know what you think.