11

(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.

yshahak
  • 4,996
  • 1
  • 31
  • 37
  • Can you show full response which you get when do request with retrofit? As it was suggested below use logging-interceptor for this. – Divers Feb 17 '17 at 10:17
  • 1
    I think server response with `400: bad request`, probably because of wrong headers or cookies which you pass. – Divers Feb 17 '17 at 10:37
  • I know I'm getting 400, But with exact same headers I have 200 good respone with `OkHttp` so that exactly what I want to resolve here – yshahak Feb 17 '17 at 10:51
  • Obviously that it's not the same if you have different server resonse. Just post full log with logging-interceptor included in your intercepters list. Text of request and text of response. – Divers Feb 17 '17 at 10:57
  • Thanks, I updated my question with the relevant output. It looks like for some reason the `AddCookiesInterceptor` not working as I expected and my headers not added. – yshahak Feb 17 '17 at 11:16
  • retrofit encode your path, so instead of havign `.vast?n` you have `.vast%3Fn`. Why you can't do it as query params? In that case I think everything should be fine. – Divers Feb 17 '17 at 11:25
  • Also if you header is static, add them via annotation - https://futurestud.io/tutorials/retrofit-add-custom-request-header – Divers Feb 17 '17 at 11:26
  • The headers not static, they static just in the test code. – yshahak Feb 17 '17 at 11:31
  • Anyway, urls are different. So fix that firstly. – Divers Feb 17 '17 at 11:32
  • Ok, I need to take a break for the weekend but I will check when I'll be back if I can try something. It might be tricky as actualy I don't build the Url myself, I'm getting it from some place – yshahak Feb 17 '17 at 11:39
  • I thought I managed to solve it but it still not working. I switched to `QueryMap` and use static `Headers`, and while both ways use the exact same `GET`, the retrofit fails. I updated the question with the new code and logs. – yshahak Feb 18 '17 at 20:04
  • remove space between after **Cookie** `Cookie :`. – Divers Feb 18 '17 at 21:06
  • Thanks. It didn't change the response from 400. I added few logs that maybe can help. It looks like something with the encoding of the url. – yshahak Feb 19 '17 at 05:49
  • Ok, finally I made it work. The problem was that I kept the dynamic headers inserting with the `AddCookiesInterceptor` while I added the headers with the static way as you suggested, and for some reason it messed the `chain` of the interceptors. So I just removed the `AddCookiesInterceptor` and it worked as excpected. – yshahak Feb 19 '17 at 06:59

1 Answers1

2

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

Ilya Tretyakov
  • 6,848
  • 3
  • 28
  • 45
  • First thanks. I actually already implemented logging interceptor but didn't found something that helped me to solve the issue. The fact that the same `url` worked perfectly when used just with `OkHttp` but didn't what I tried with `retrofit` is what I can't unserstand. – yshahak Feb 15 '17 at 06:36