android – Add cookies to retrofit 2 request-ThrowExceptions

Exception or error:

I need to add cookies with retrofit 2.0. If i understand correct, cookies – the same as headers. this cookies must be added:

private HashMap<String, String> cookies = new HashMap();
cookies.put("sessionid", "sessionId");
cookies.put("token", "token");

this one work with Jsoup lib:

String json = Jsoup.connect(apiURL + "/link")
                    .cookies(cookies)
                    .ignoreHttpErrors(true)
                    .ignoreContentType(true)
                    .execute()
                    .body();

here is my code with retrofit request:

@GET("link")
Call<CbGet> getData(@Header("sessionid") String sessionId, @Header("token") String token);

but it is doesn’t work…
i get 403 error code so there are no cookies in the request…

any idea?

How to solve:

First of all: cookie is not the same as a header. Cookie is a special HTTP header named Cookie followed by list of the pairs of keys and values (separated by “;”). Something like:

Cookie: sessionid=sessionid; token=token

Since you cannot set multiple Cookie headers in the same request you are not able to use two @Header annotations for separate values (sessionid and token in your sample). I can think of one very hacky workaround:

@GET("link")
Call<CbGet> getData(@Header("Cookie") String sessionIdAndToken);

You change your method to send sessionId and token in one string. So in this case you should manually generate cookie string beforehand. In your case sessionIdAndToken String object should be equal to “sessionid=here_goes_sessionid; token=here_goes_token

The proper solution is to set cookies by adding OkHttp‘s (that is library Retrofit uses for making underlying http calls) request interceptor. You can see solution or adding custom headers here.

###

why not using the cookieJar option?

new Retrofit.Builder()
    .baseUrl(BASE_URL)
    .client(
        new OkHttpClient().newBuilder()
            .cookieJar(new SessionCookieJar()).build())
    .build();

private static class SessionCookieJar implements CookieJar {

    private List<Cookie> cookies;

    @Override
    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
        if (url.encodedPath().endsWith("login")) {
            this.cookies = new ArrayList<>(cookies);
        }
    }


    @Override
    public List<Cookie> loadForRequest(HttpUrl url) {
        if (!url.encodedPath().endsWith("login") && cookies != null) {
            return cookies;
        }
        return Collections.emptyList();
    }
}

###

API web service example add Header

@FormUrlEncoded
@POST("getDriverRoutes")
Call<Guzergah> getGuzergah(@Header("Cookie") String userCookie, @Field("driver_id") int driver_id);

when you login to system save cookies to your local on Response like

 public void onResponse(Response<Login> response, Retrofit retrofit) {
            hidepDialog();
            String cookie = response.headers().get("Set-Cookie");
            editor.putString("user_cookie", cookie.split(";")[0]);
            editor.commit();

and in every service you need to be autorised send your cookies , get from sharepreference and send it with your web service

  String userCookie = shp.getString("user_cookie", ""); // here is cookies before send
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http://server.aracadabra.com:8080/").
                    addConverterFactory(GsonConverterFactory.create())
            .build();

    final APIService service = retrofit.create(APIService.class);

    final Call<SenMsgStatus> loginMCall = service.sendMessage(userCookie, type, route_id, user_id, passenger_id, passenger_status, text);

###

to add cookie header to okhttp request headers , add this in Interceptor:

request= request.newBuilder().addHeader("Cookie", sessionIdAndToken).build();

Ref:https://github.com/square/okhttp/wiki/Interceptors as mentioned by @Alexander Mironov

Full Example code here: Hope it helps you

import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.List;


public class LoggingInterceptor implements Interceptor {

    private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);
    @Override
    public Response intercept(Interceptor.Chain chain) throws IOException {
        Request request = chain.request();

        long t1 = System.nanoTime();
        request = processRequest(request);
        logger.info("Sending request with url:{} and connection status:{} and request headers:{}",
                request.url(), chain.connection(), request.headers());

        Response response = chain.proceed(request);
        long t2 = System.nanoTime();
        logger.info("Received response for url:{} and time taken:{} and response headers as:{}",
                response.request().url(), (t2 - t1) / 1e6d, response.headers());

        response = processResponse(response);
        return response;
    }
    //Add cookies for all subsequent requests
    private Request processRequest(Request request) {
        if(!request.url().toString().contains("/v1/authorize")) {
            final EmployeeSession session = getSession();
            StringBuilder etokenAndUId = new StringBuilder("etoken=");
            etokenAndUId.append(session.getEtoken()).append(";").append("uId=").append(session.getUId());
            logger.info("inside processRequest for all subsequent requests, sending cookies as etokenAndUId values:{}", etokenAndUId.toString());
            request= request.newBuilder().addHeader("Cookie", etokenAndUId.toString()).build();
        }
        return request;
    }

    //Extract cookies from login url
    private Response processResponse(Response response) {
        if(response.request().url().toString().contains("/v1/authorize")) {
            final List<String> cookieHeaders = response.headers("Set-Cookie");
            String etoken = "", uId = "";
            for (String cookieHeader : cookieHeaders) {
                if(cookieHeader.contains("etoken=")) {
                    etoken = cookieHeader.substring(7, cookieHeader.indexOf(';'));
                }
                else if(cookieHeader.contains("uId=")) {
                    uId = cookieHeader.substring(4, cookieHeader.indexOf(';'));
                }
            }
            logger.info("inside processResponse found cookies from login url response: etoken:{} and uid:{}", etoken, uId);
            setSession(etoken, uId, "c1");
            logger.info("current employee session:{}", getSession());
        }
        return response;
    }
 }    

Leave a Reply

Your email address will not be published. Required fields are marked *