Marc
Marc

Reputation: 483

Retrofit connection failure returns RetrofitError.response as null

Using Retrofit 1.6.0, OkHTTP 2.0.0, and OkHTTP-UrlConnection 2.0.0.

I am doing a POST to a service using Retrofit to a URL that does not exist. The failure callback is called, as expected. However, the RetrofitError parameter does not have a response. I would really like to grab the HTTP status code that was returned by using

error.getResponse().getStatus()

but since getResponse() returns null, I can't.

Why is getResponse() null and how can I get the status?

Thanks.

Also, the error I am receiving is UnknownHostException, as expected. Repeat: I am expecting this error. I want to know how to get the HTTP status code or why error.getResponse() returns null.

Edit: Here's some code:

RestAdapterBuilderClass.java
    RestAdapter restAdapter = new RestAdapter.Builder()
            .setEndpoint("http://badURL.DoesntMatter/");
            .setRequestInterceptor(sRequestInterceptor)
            .setLogLevel(RestAdapter.LogLevel.FULL)
             .build();
    sService = restAdapter.create(ServiceInterface.class);

ServiceInterface.java
    @POST("/Login")
    void login(@Body JsonObject body, Callback<String> callback);

CallbackClass.java
    @Override
    public void failure(RetrofitError error) {
        if (error.getResponse() == null) {

            // error.getResponse() is null when I need to get the status code
            // from it.

            return;
        }
    }

Upvotes: 16

Views: 15003

Answers (4)

vvbYWf0ugJOGNA3ACVxp
vvbYWf0ugJOGNA3ACVxp

Reputation: 1116

Just to expand on @lyio's answer, I found from Fabric logging that getKind() sometimes returns UNEXPECTED and then if you parse the message you get timeouts and connection issues so I wrote the utility class below.

public class NetworkUtils {
    // Compiled from Fabric events
    private static final List<String> networkErrorStrings = new ArrayList<>(Arrays.asList(
        "Unable to resolve host",
        "Connection closed by peer",
        "Failed to connect",
        "timeout",
        "Connection timed out"));

    public static boolean isNetworkError(@Nullable RetrofitError retrofitError) {
        if (retrofitError != null) {
            if (retrofitError.getKind() != RetrofitError.Kind.NETWORK) {
                for (String error : networkErrorStrings) {
                    if (retrofitError.getMessage().contains(error)) {
                        return true;
                    }
                }
            } else {
                return true;
            }
        }

        return false;
}

}

Upvotes: 1

mustaq
mustaq

Reputation: 969

I am using Retrofit 2. When endpoint url end with "/" as in your case and again in your interface it starts with "/" [@POST("/Login")] causes this problem. Remove the "/" from .setEndpoint() method

Upvotes: 0

swanson
swanson

Reputation: 7482

RetrofitError has a method called isNetworkError() that you can use to detect a failed request due to network problems. I usually add a small helper method like this:

public int getStatusCode(RetrofitError error) {
    if (error.isNetworkError()) {
        return 503; // Use another code if you'd prefer
    }

    return error.getResponse().getStatus();
}

and then use that result to handle any additional failure logic (logout on 401, display error message on 500, etc).

Upvotes: 7

lyio
lyio

Reputation: 1427

When you get an UnknownHostException it means, that you were not able to establish a connection to the server. You cannot, in fact, expect a HTTP status in that case.

Naturally you only get a Http response (and with that a status) when you can connect to a server.

Even when you get a 404 status code, you made a connection to the server. That is not the same as a UnknownHostException.

The getResponse() can return null if you didn't get a response.

Upvotes: 10

Related Questions