Adding dynamic header to POST request with body (Retrofit v2.4.0) - android

I am using Retrofit v2.4.0 in my project. I need to get token using one API call and using this token in header of the POST request I should use another API call where I should add one header and two parameter to the body of the request. The following code is of the second API call (JavaRx is used):
#FormUrlEncoded
#POST("auth/sendCode")
#Headers("Content-Type: application/json")
Single<SendCodeResponse> sendCode(#Header("token") String token,
#Field("phoneNumber") String phoneNumber,
#Field("langCode") String langCode);
However, it is not working. When I log my request, it is showing that the request body is not correct.
What is wrong with my code above?

Related

Retrofit "form-urlencoded" request with #Field-annotated parameter

I have two queries:
#POST("/auth/login")
suspend fun login(#Body user: LoginUserDto): AuthResponse<TokenDto>
#FormUrlEncoded
#POST("/auth/refresh")
suspend fun refreshToken(#Field("refreshtoken") refreshToken: String): AuthResponse<TokenDto>
The first one is working well which means baseUrl is OK.
The second one returns HTTP 404 Not Found. WHen I look at Chucker interceptor logs, the url is correct and the refreshToken is present in the request. When I try to trigger it manually from request.rest in vsCode like this:
POST http://localhost:4000/auth/refresh/eyJhbGciOiJIUzI1NiIsInR5...blablabla
... it works fine.
The code of the endpoint starts like this (node.js server):
app.post('/auth/refresh/:refreshtoken', async (req, res) => {
const refreshToken = req.params.refreshtoken;
// some code
I believe I made mistake in my retrofit call refreshToken(#Field("refreshtoken") refreshToken: String).
Could smb help how make such #FormUrlEncoded request with retrofit properly?
Appreciate any help.
#Field is used to send #FormUrlEncoded request in Retrofit which hides your parameter and not attach with url to provide security.Used for POST request.
#Query parameter appended to the URL.
If you are using #Field request than it will hides your parameter and not append with the url.
If you are using #Query request than all your parameter is append to your request and visible to users.
Depend on your api request you have to use one of above annotation. If the api request accept the #FormUrlEncoded data than use #Field or if they want to attached it with url than use #Query.

What is the difference between #Field and #Query in retrofit

In some POST requests, I don't know when to use #Field with FormUrlEncoded and when to use #Query
For Example:
#POST("list-products-for-sale")
Call<ListAllProductsResponse> getNewProducts(#HeaderMap Map<String,
String> headers,#Query("lastProductId") String lastProductId);
When I tried to use #Field here it was not responding properly and when I switched it to #Query it's working great.
I want to know why #Field isn't working while Query can work perfectly and I did tested in POSTMAN where I sent the data as a formurlencoded and it's giving me the results fin.
EDIT
BTW I'm passing Content-Type:application/json, Accept: application/json with an Authorization key
#Field is used to send #FormUrlEncoded request in Retrofit which hides your parameter and not attach with url to provide security.Used for POST request.
#Query parameter appended to the URL.
If you are using #Field request than it will hides your parameter and not append with the url.
If you are using #Query request than all your parameter is append to your request and visible to users.
Depend on your api request you have to use one of above annotation. If the api request accept the #FormUrlEncoded data than use #Field or if they want to attached it with url than use #Query.
You can get more information from below link :
1) https://square.github.io/retrofit/2.x/retrofit/index.html?retrofit2/http/Query.html
2) https://square.github.io/retrofit/2.x/retrofit/retrofit2/http/Field.html

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.

Call Twitter Endpoint API to follow another user Android

I'm using Twitter end point API to follow another user. The API is:
https://api.twitter.com/1.1/friendships/create.json?follow=&screen_name=&user_id=
with Authorization header passed as:
#Headers("Authorization: OAuth oauth_consumer_key=DC0sePOBbQ8bYdC8Smg,oauth_signature_method=HMAC-SHA1,oauth_timestamp=1502774524,oauth_nonce=175308858,oauth_version=1.0,oauth_token=712057165-iQB4b4Q0hsNmHsAxiW4X5UF5xVB6JmKOPhxnW,oauth_signature=X0GExH5DBVgVv49jkO3LwfX8%3D")
#POST()
#FormUrlEncoded
Call<ResponseBody> followUser(#Url String url, #Field("follow") boolean follow, #Field("screen_name") String screenName, #Field("user_id") String userId);
in Retrofit API call from Android. This works fine. But the Auth header has to be generated dynamically for every logged in user. How to achieve that?
You can use #Header annotation in parameter list. Please check the official documentation.
Replaces the header with the value of its target.
#GET("/")
Call<ResponseBody> foo(#Header("Accept-Language") String lang);
Header parameters may be null which will omit them from the request.
Passing a List or array will result in a header for each non-null
item.
Note: Headers do not overwrite each other. All headers with the same
name will be included in the request.

Where in Retrofit build the full JSON before sending it?

I am using retrofit an get Bad Request , I would want to know if there is a place in this library where builds the full JSON in string format before sending it.
If it's about inspecting the JSON at runtime for debugging purposes, you can call setLogLevel(LogLevel.FULL) on your RestAdapter.Builder.
FULL logs the headers, body and metadata for both requests and responses to logcat.
new String(((TypedByteArray) request.getBody()).getBytes());
In order to build a JSON formatted body, create an object with a class whose properties are the same that you want to send to the server. The GSON Library set up (or whichever library you are using) with the RestAdapter should send the request with the body in JSON format.
Also ensure that the call is #POST annotated and the parameter annotd with #Body Below is an example:
#POST("/login")
User login(#Body LoginUser loginUser);

Categories

Resources