-
Notifications
You must be signed in to change notification settings - Fork 449
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
Non throwing Retrofit Either adapter #2621
Non throwing Retrofit Either adapter #2621
Conversation
4d01366
to
6c4e381
Compare
Very nice improvement |
0034d92
to
ff4293d
Compare
…ferent JSON converters
…te for type erasure
@lukaszkalnik is this ready for review? I saw you were still making some improvements yesterday. |
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.
Looks good to me, left a few questions/suggestions
...row-core-retrofit/src/main/kotlin/arrow/retrofit/adapter/either/networkhandling/CallError.kt
Outdated
Show resolved
Hide resolved
...row-core-retrofit/src/main/kotlin/arrow/retrofit/adapter/either/networkhandling/CallError.kt
Outdated
Show resolved
Hide resolved
...it/src/main/kotlin/arrow/retrofit/adapter/either/networkhandling/NetworkEitherCallAdapter.kt
Outdated
Show resolved
Hide resolved
c21e720
to
02a347c
Compare
02a347c
to
c2e2228
Compare
...it/src/main/kotlin/arrow/retrofit/adapter/either/networkhandling/NetworkEitherCallAdapter.kt
Show resolved
Hide resolved
@arrow-kt/maintainers should add @lukaszkalnik and @LordRaydenMK to the maintainers team? This PR looks good to me, and ready to be merged. Thanks for the review @LordRaydenMK & @hoc081098! 🙏 |
What about having a route that can return a 500 with no body, but for other failure status codes the body is of a custom type, that you want to match in the error handling? The only other solution I can think of is to use an OkHttp Interceptor, that throws a custom exception when the response code is 500 and then handle that with Either.catch in the api methods. That way one can keep the custom error type. Any other solution? This doesn't seem to check if the errorBody actually contains any data (only that errorBody is not null), which is not the case when there is no body. With that check in place and declaring the Left type (the custom error type) of the api method as optional, would that be a solution? |
It's not lost, error code and body are still in the
The whole point of this adapter is to avoid having to catch exceptions in your API calls.
You never have guarantees about what really comes inside the error body. As Jake Wharton writes here, errors may come from proxies, wifi portals, applications, you may suddenly have a human-readable HTML page inside the error response, and now you're dealing with two errors. I'm not sure if making this adapter more complex by allowing custom response body type is the way to go. I would rather have a choice - for general usage just take this adapter. When you need project-specific response body parsing then I would suggest creating your own adapter which supports that. The main premise of this adapter is to avoid throwing exceptions in case of network errors and to handle them as domain errors.
This is not my code. I'm not sure what you mean here. |
@andre-krueger Ok, I think I understood what you mean. This unfortunately won't work for the following reasons:
|
@nomisRev will there be some further review on this or could this be merged? |
@lukasz-kalnik-gcx |
By "empty" response body do you mean empty or null? Retrofit makes it impossible to have a null So this will never happen.
Yes, that's how you can go about it. Or you can create a custom CallAdapter based on this one which includes your custom error body type. |
I was using an express server to test the 500 response and was sending this for the route: That's what curl replied with, so it seems like an empty body.
So it failed here with an exception (it was EOFException, when I remember correctly). |
Yes, so the body was indeed empty and whatever JSON converter you have registered failed parsing it and threw the EOFException. Also you can take a look at square/retrofit#1554 |
Unfortunately, no luck with that. I will wait until these changes are merged - until then I just return the custom error in an interceptor in case of the 500 status response. |
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.
great addition, thanks @lukaszkalnik !
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.
Thanks @lukaszkalnik 👍🏾
Thank you so much @lukasz-kalnik-gcx for you patience, and the great addition 🙏 Finally merged! |
Currently implemented Retrofit adapters (
ArrowEitherCallAdapter
andArrowResponseECallAdapter
) only wrap HTTP errors (i.e. valid server responses with codes 4xx and 5xx) inLeft
.They still throw exceptions in the following cases:
Especially for mobile apps this is problematic, as losing a connection or experiencing a timeout is quite a normal case for them. The application has to deal with it gracefully.
Therefore I decided to implement a Retrofit adapter which converts all possible exceptions to domain errors (i.e. wrapping them with
Left
).This adapter requires the developer to define his Retrofit API passing the provided
CallError
type as theLeft
type argument for returnedEither
:The adapter then automatically wraps ocurring exceptions in appropriate
CallError
subclasses.This adapter also allows for
null
response body in case the defined Retrofit API expects aUnit
return type. This is useful e.g. when expecting a204 No Content
response:Note that bothThis will be fixed by #2625ArrowEitherCallAdapter
andArrowResponseECallAdapter
always throw when response body is null, effectively not allowing processing of responses like 204 No Content, which might be worth fixing.