(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://%5bNo%20Host%5d/jsc/xp2/fns.vast?", is invalid.<p>
D/OkHttp: Reference #9.756f87dd.1487483027.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.
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.
OkHttp doesn't currently offer asynchronous APIs to receive a response body in parts.
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.
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.
I think it is better to enable logging in OkHttp and check that
More info on how to enable OkHttp Loggin could be found here: https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With