How do I get response headers with RxAndroid + Retrofit in Kotlin? - android

I have an API observable returning a CUSTOM_MODEL. I would like to get the response headers from this call too.

Change your retrofit definition to return Observable<Response<CUSTOM_MODEL>>. The headers can be accessed through the Response object and CUSTOM_MODEL will be available through Response.body().

Related

Get response from Retrofit with suspend method for generic objects with Kotlin

I have a generic method getData that should get from the server some POJOs of different objects. Before Retrofit 2.6 without coroutines I could create a method like this:
#POST("GetData")
fun getGenericData(#Query("sessionId") sessionId: UUID, #Body request: RemoteRequest): Call<ResponseBody>
An it was fine because I could handle the json contained in the body and deserialize it based on the object name declared in a property inside the json, but with Retrofit 2.6 and coroutines that is not possibile because the return type Call or ResponseBody throw an exception. I do not want to use Response because I do not know the type of the object at compile time and I want to deserialize the returned json separately. Any idea ?

How to read custom header response (json object) in retrofit

I have an authorization api that returns null body but with access token in headers.
I am able to read the okhttp3.Headers object and also get header names as Set using
Headers headers = response.headers(); // response object of type Response<T>
Set<String> headerNames = headers.names();
But in the code the headers object does not show the custom header (access_token) returned as response. However, in postman i can see the custom header as shown below:
access_token -> { "Token":"adklasldalksdalkdask",
"Provider":"ABC" }
I am using interceptors to get the header as shown:
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
Can someone suggest how to read the access token as part of the custom header in auth response?
First print the entire response, body, code, message, header(by logging or something else) and try to find a clue from there.
I would recommend you to read the API docs and see the type of request it is asking for.
Use Postman to check which one of the following is working:
1.form-data
2.x-www-form-Urlencoded
3.raw
4.binary
And then accordingly set the annotations in the method declarations in the interface.
eg: in my case it was taking x-www-form-Urlencoded so I had to mention it using
#FormUrlEncoded
#Headers("Content-Type: application/x-www-form-urlencoded")
in the method declaration.

Deserialize Retrofit response when response body is Void

I'm using Retrofit to get some data from a server. The problem is the response body is null (although I get a response code : 200 ) and if you check this github issue like I did you will see that they suggest you to use Call<Void> for empty response's body.
I did change it to Call<Void> and now when I'm making a request with Retrofit it enters onResponse and response is successful, but then I can't deserialize it with Gson.
Using :
DataServiceResponse serviceResponse = gson.fromJson(response.body(), DataServiceResponse.class);
is not possible since response.body() is void.

Passing dynamic value to url using retrofit

I am trying to make a simple weather app using retrofit library. I want the city name to be dynamic. This is what i have done so far:
full url:
http://api.openweathermap.org/data/2.5/forecast/daily?q=dhaka&cnt=7&appid=1111
base url:
http://api.openweathermap.org/
in the main activity
LinkedHashMap<String,String>data=new LinkedHashMap<>();
data.put("q",targetCity);
data.put("cnt",Integer.toString(7));
data.put("appid",getString(R.string.api_key));
Call<WeatherResponse>weatherResponseCall=weatherServiceApi.getAllWeatherReport(data);
and in my api interface:
#GET("data/2.5/forecast/daily?")
Call<WeatherResponse>getAllWeatherReport(#QueryMap LinkedHashMap<String,String>data);
I am neither getting any error, nor any response data.
Please help.
You aren't executing the call function...
WeatherResponse response = call.execute().body();
If I were you, I would try using a ResponseBody from okhttp to get the data returned. Then using response.string() you can see what's retrieved from the request.
Or, to log the body data of each request/response you should add this interceptor when building your Retrofit object:
OkHttpClient client = httpClient.addInterceptor(interceptor.setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
Retrofit retrofit = builder.client(client).build();
return retrofit.create(serviceClass);

POST body JSON using Retrofit

I'm trying to POST a JSONObject using the Retrofit library, but when I see the request at the receiving end, the content-length is 0.
In the RestService interface:
#Headers({
"Content-type: application/json"
})
#POST("/api/v1/user/controller")
void registerController(
#Body JSONObject registrationBundle,
#Header("x-company-device-token") String companyDeviceToken,
#Header("x-company-device-guid") String companyDeviceGuid,
Callback<JSONObject> cb);
And it gets called with,
mRestService.registerController(
registrationBundle,
mApplication.mSession.getCredentials().getDeviceToken(),
mApplication.mSession.getCredentials().getDeviceGuid(),
new Callback<JSONObject>() {
// ...
}
)
And I'm certain that the registrationBundle, which is a JSONObject isn't null or empty (the other fields are certainly fine). At the moment the request is made, it logs out as: {"zip":19312,"useAccountZip":false,"controllerName":"mine","registrationCode":"GLD94Q"}.
On the receiving end of the request, I see that the request has Content-type: application/json but has Content-length: 0.
Is there any reason why sending JSON in the body like this isn't working? Am I missing something simple in using Retrofit?
By default, you don't need to set any headers if you want a JSON request body. Whenever you test Retrofit code, I recommend setting .setLogLevel(RestAdapter.LogLevel.FULL) on your instance of RestAdapter. This will show you the full request headers and body as well as the full response headers and body.
What's occurring is that you are setting the Content-type twice. Then you're passing a JSONObject, which is being passed through the GsonConverter and mangled to look like {"nameValuePairs":YOURJSONSTRING} where YOURJSONSTRING contains your complete, intended JSON output. For obvious reasons, this won't work well with most REST APIs.
You should skip messing with the Content-type header which is already being set to JSON with UTF-8 by default. Also, don't pass a JSONObject to GSON. Pass a Java object for GSON to convert.
Try this if you're using callbacks:
#POST("/api/v1/user/controller")
void registerController(
#Body MyBundleObject registrationBundle,
#Header("x-company-device-token") String companyDeviceToken,
#Header("x-company-device-guid") String companyDeviceGuid,
Callback<ResponseObject> cb);
I haven't tested this exact syntax.
Synchronous example:
#POST("/api/v1/user/controller")
ResponseObject registerController(
#Body MyBundleObject registrationBundle,
#Header("x-company-device-token") String companyDeviceToken,
#Header("x-company-device-guid") String companyDeviceGuid);

Categories

Resources