Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrofit2 response is bad request while with OkHttp is working fine

(Edit I added a small demonstration test)

I'm new to Retrofit. What I need to do is the retrieve XML file from a server and convert it to POJO. The problem is that everything work perfect with static files on my test server, but when I'm trying this on the real server, I can't make it work with Retrofit2, but it do work when I just use directly with OkHttp, so something is wrong with the generated Request I guess.

Edit: I switched the code to use String converter to simply things, as the problem is exclusively with the response.

Here is my base implementation.

public interface ZedoClient {
@retrofit2.http.Headers({
        "User-Agent: Mozilla/5.0 (Linux; Android 5.1; Quattro_L50_HD LMY47D/Quattro_L50_HD)",
        "Cookie : ZCBC=1;FFcat=3533,3,90;FFad=0;FFMChanCap=5345280B3533,3#2605191|0,1#0,24:"
})
@GET("fns.vast")
Call<Vast> getVast(@QueryMap(encoded=true) Map<String, String> options);

I added two Interceptor in order to set the headers and the cookies: AddCookiesInterceptor.class

class AddCookiesInterceptor implements Interceptor {
    private final Headers headers;

    AddCookiesInterceptor(Headers headers) {
        this.headers = headers;
    }
    @Override
    public okhttp3.Response intercept(Chain chain) throws IOException {
        Request.Builder builder = chain.request().newBuilder();
        builder.headers(headers);
        return chain.proceed(builder.build());
    }
}

ReceivedCookiesInterceptor.class

class ReceivedCookiesInterceptor implements Interceptor {
    @Override
    public okhttp3.Response intercept(Chain chain) throws IOException {
        okhttp3.Response originalResponse = chain.proceed(chain.request());

        if (!originalResponse.headers("Set-Cookie").isEmpty()) {
            HashSet<String> cookies = new HashSet<>();
            for (String header : originalResponse.headers("Set-Cookie")) {
                cookies.add(header);
            }
        }
        return originalResponse;
    }
}

And here is the test I make that shows how with the raw OkHttp everything working as expected, but with retrofit2 it fail:

public static Vast test(String baseUrl, Map<String, String> queryParams, final Headers headers) {
    try {
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient httpClient = new OkHttpClient.Builder().addInterceptor(logging).build();
        Request.Builder request = new Request.Builder()
                .url("http://********/fns.vast?v=vast2&d=90&ct=mnf%3AKARBONN%5Emdn%3AQuattro_L50_HD%5Emdu%3AQuattro_L50_HD%5Etyp%3ASmartPhone%5Econ%3Awifi%5Eosn%3AAndroid%5Evsn%3A5.1%5Eosv%3A22%5Ecn%3AUS%5Elng%3Aen%5E&s=3&n=3533&c=3&z=0.4933822377892413");
        if (headers != null) {
            request.headers(headers);
        }
        okhttp3.Response oldRespnse = httpClient.newCall(request.build()).execute();
        System.out.println("successsForOkhttp: " + oldResponse.isSuccessful());
        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
        if (headers != null) {
            clientBuilder.networkInterceptors().add(logging);
            clientBuilder.networkInterceptors().add(new AddCookiesInterceptor(headers));
            clientBuilder.networkInterceptors().add(new ReceivedCookiesInterceptor());
        }
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(clientBuilder.build())
                .addConverterFactory(SimpleXmlConverterFactory.create())
                .build();

        ZedoClient client = retrofit.create(ZedoClient.class);
        Call<Vast> call = client.getVast(queryParams);
        Response<Vast> response = call.execute();
        System.out.println("successsForRetrofit: " + response.isSuccessful());
        if (response.isSuccessful()) {
            return response.body();
        } else {
            MyLog.e("error:" + response.raw().message());
            return null;
        }
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }

}

Here is the output:

I/System.out: successsForOkhttp: true
I/System.out: successsForRetrofit: false
I/System.out: error:Bad Request

As suggested, I added Logging-Interceptor for both, the OkHttp request and the Retrofit2 request, here is the output:

D/OkHttp: --> GET http://**********/fns.vast?v=vast2&d=90&ct=mnf%3AKARBONN%5Emdn%3AQuattro_L50_HD%5Emdu%3AQuattro_L50_HD%5Etyp%3ASmartPhone%5Econ%3Awifi%5Eosn%3AAndroid%5Evsn%3A5.1%5Eosv%3A22%5Ecn%3AUS%5Elng%3Aen%5E&s=3&n=3533&c=3&z=0.4933822377892413 http/1.1
D/OkHttp: User-Agent: Mozilla/5.0 (Linux; Android 5.1; Quattro_L50_HD LMY47D/Quattro_L50_HD)
D/OkHttp: Cookie: ZCBC=1;FFcat=3533,3,90;FFad=0;FFMChanCap=5345280B3533,3#2605191|0,1#0,24:
D/OkHttp: --> END GET
D/OkHttp: <-- 200 OK http://**********/fns.vast?v=vast2&d=90&ct=mnf%3AKARBONN%5Emdn%3AQuattro_L50_HD%5Emdu%3AQuattro_L50_HD%5Etyp%3ASmartPhone%5Econ%3Awifi%5Eosn%3AAndroid%5Evsn%3A5.1%5Eosv%3A22%5Ecn%3AUS%5Elng%3Aen%5E&s=3&n=3533&c=3&z=0.4933822377892413 (720ms)

D/OkHttp: --> GET http://**********/fns.vast?v=vast2&d=90&ct=mnf%3AKARBONN%5Emdn%3AQuattro_L50_HD%5Emdu%3AQuattro_L50_HD%5Etyp%3ASmartPhone%5Econ%3Awifi%5Eosn%3AAndroid%5Evsn%3A5.1%5Eosv%3A22%5Ecn%3AUS%5Elng%3Aen%5E&s=3&n=3533&c=3&z=0.4933822377892413 http/1.1
D/OkHttp: User-Agent: Mozilla/5.0 (Linux; Android 5.1; Quattro_L50_HD LMY47D/Quattro_L50_HD)
D/OkHttp: Cookie : ZCBC=1;FFcat=3533,3,90;FFad=0;FFMChanCap=5345280B3533,3#2605191|0,1#0,24:
D/OkHttp: Host: xp1.zedo.com
D/OkHttp: Connection: Keep-Alive
D/OkHttp: Accept-Encoding: gzip
D/OkHttp: --> END GET
D/OkHttp: <-- 400 Bad Request http://**********/fns.vast?v=vast2&d=90&ct=mnf%3AKARBONN%5Emdn%3AQuattro_L50_HD%5Emdu%3AQuattro_L50_HD%5Etyp%3ASmartPhone%5Econ%3Awifi%5Eosn%3AAndroid%5Evsn%3A5.1%5Eosv%3A22%5Ecn%3AUS%5Elng%3Aen%5E&s=3&n=3533&c=3&z=0.4933822377892413 (208ms)
D/OkHttp: Server: ******Host
D/OkHttp: Mime-Version: 1.0
D/OkHttp: Content-Type: text/html
D/OkHttp: Content-Length: 272
D/OkHttp: Expires: Sun, 19 Feb 2017 05:43:47 GMT
D/OkHttp: Date: Sun, 19 Feb 2017 05:43:47 GMT
D/OkHttp: Connection: close
D/OkHttp: <HTML><HEAD>
D/OkHttp: <TITLE>Invalid URL</TITLE>
D/OkHttp: </HEAD><BODY>
D/OkHttp: <H1>Invalid URL</H1>
D/OkHttp: The requested URL "http&#58;&#47;&#47;&#37;5bNo&#37;20Host&#37;5d&#47;jsc&#47;xp2&#47;fns&#46;vast&#63;", is invalid.<p>
D/OkHttp: Reference&#32;&#35;9&#46;756f87dd&#46;1487483027&#46;1f41287
 D/OkHttp: </BODY></HTML>

Althogth both calls use the same GET, the Retrofit2 call fails with 400. Probably something with the Headers or cookies, but I can't work it out.

like image 343
yshahak Avatar asked Feb 13 '17 10:02

yshahak


People also ask

Which is better OkHttp or Retrofit?

Custom construction of network process Underlying Retrofit, it is using Reflection. If we want to extend some class from it, might not be possible due to it is final by default. So if you want to have more control over your own network process, using OkHttp directly should provide you that flexibility.

Is OkHttp asynchronous?

OkHttp doesn't currently offer asynchronous APIs to receive a response body in parts.

Does Retrofit uses OkHttp?

It started as a component of OkHttp. Retrofit is a type-safe REST client for Java and Android application development. It consists of interfaces, classes, and methods that provide the required functionalities. JSON or XML data may be parsed and converted to POJOs (Plain Old Java Objects) using the Retrofit library.

What is OkHttp client?

OkHttp is an efficient HTTP & HTTP/2 client for Android and Java applications. It comes with advanced features, such as connection pooling (if HTTP/2 isn't available), transparent GZIP compression, and response caching, to avoid the network completely for repeated requests.


1 Answers

I think it is better to enable logging in OkHttp and check that

  1. requested url is correct
  2. received data is correct too.

More info on how to enable OkHttp Loggin could be found here: https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor

like image 77
Ilya Tretyakov Avatar answered Oct 30 '22 17:10

Ilya Tretyakov