I get a cookie from my backend API that allows me to authenticate all subsequent user requests.
I'm using retrofit, and I can't get it to keep the session key between requests. I want to know how to configure retrofit so that it keeps the session key around and uses it for all future requests:
public class ApiClient{
private static final String API_URL = "http://192.168.1.25:8080";
private static RestAppApiInterface sRestAppService;
public static RestAppApiInterface getRestAppApiClient() {
if (sRestAppService == null) {
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(cookieManager);
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(API_URL)
.build();
sRestAppService = restAdapter.create(RestAppApiInterface.class);
}
return sRestAppService;
}
}
You need to set a Cookie persistent Client.
Since you're using Android and retrofit I suggest using OKHttp wich is better supported by retrofit and Android thread safe, the way to this is the following
//First create a new okhttpClient (this is okhttpnative)
OkHttpClient client = new OkHttpClient(); //create OKHTTPClient
//create a cookieManager so your client can be cookie persistant
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
client.setCookieHandler(cookieManager); //finally set the cookie handler on client
//OkClient is retrofit default client, ofcourse since is based on OkHttClient
//you can decorate your existing okhttpclient with retrofit's okClient
OkClient serviceClient = new OkClient(client);
//finally set in your adapter
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("Some eNdpoint")
.setClient(serviceClient)
.build();
The point of using Okhttp instead of the defaultHttpClient(by apache) is that okhttp is threadsafe for android and better supported by retrofit.
Remembar that if you create another adapter you will need to set the same client, perhaps if you implement singleton on the client instance you will use the same one for all your requests, keeping in the same context
I hope this helps,best
If you use Retrofit 2 you can add the library:
compile "com.squareup.okhttp3:okhttp-urlconnection:3.2.0"
then use the following code to manage cookies when you create your OkHttp client:
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.cookieJar(new JavaNetCookieJar(cookieManager));
Related
I am working on a project where I am using woocommerce API to add items to cart.Add to cart is working fine but when I kill the app from the background and reopen the app woocommerce API could not able to fetch the data using session key.
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
CookieHandler cookieHandler = new CookieManager();
PersistentCookieStore cookieStore = new PersistentCookieStore(MuraliFlutesApplication.getInstance());
CookieManager cookieManager = new CookieManager(cookieStore, CookiePolicy.ACCEPT_ORIGINAL_SERVER);
cookieHandler.setDefault(cookieManager);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.readTimeout(120, TimeUnit.HOURS).connectTimeout(120, TimeUnit.HOURS).addNetworkInterceptor(logging).cookieJar(new JavaNetCookieJar(cookieHandler));
httpClient.addInterceptor(logging);
I have an old app which uses raw okhttp calls and utilizes sessions.
OkHttp is setup by this code:
OkHttpClient okHttpClient = null;
try {
OkHttpClient.Builder builder = SupportRequests.getUnsafeOkHttpClient();
builder.readTimeout(5000, TimeUnit.MILLISECONDS);
builder.connectTimeout(10000, TimeUnit.MILLISECONDS);
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
builder.cookieJar(new JavaNetCookieJar(cookieManager));
okHttpClient = builder.build();
SupportRequests.setOkHttpClient(okHttpClient);
} catch (NoSuchAlgorithmException | KeyManagementException e) {
FirebaseCrash.report(e);
}
I want to switch to using retrofit. The app is quite big and contains several dozens requests. Making it in a one-time switch is not possible.
I tried to start switching and encountered a problem.
Retrofit and okHtpp raw calls do not share PHP session.
I create retrofit with following code:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Preferences.getInstance().server)
.addConverterFactory(GsonConverterFactory.create(SupportGson.get()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.build();
retrofitProvider.setRetrofit(retrofit);
But sessions are different for retrofit calls and raw okhttp calls.
Any idea how to make them share session?
Does anyone know in Android How to use Okhttpclient Create a Http Delete Or Put Method With Params?
Using java , this is what i have tried:
CookieJarImpl cookieJar = new CookieJarImpl(new PersistentCookieStore(context));
okHttpClient = new OkHttpClient.Builder()
.cookieJar(cookieJar)
.addInterceptor(new LoggerInterceptor("TAG"))
.connectTimeout(10000L, TimeUnit.MILLISECONDS)
.readTimeout(10000L, TimeUnit.MILLISECONDS) //其他配置
.build();
You can build a URL with query parameters using the HttpUrl class. Then you can use an okhttp3.Request.Buidler() along with either the post() or delete() methods:
HttpUrl url = new HttpUrl.Builder()
.host(host).addQueryParameter(name, value).build();
Request request = new Request.Builder()
.url(url).post(RequestBody.create(mediaType, body)).addHeader(type, header).build();
okhttpClient.newCall(request).enqueue(new Callback() {
...
});
You can check out the OkHttp wiki for recipes if you need further help. Or you could use Square's other wonderful library, Retrofit, which pairs well with OkHttp.
So i started using Okhttp 3 and most of the examples on the web talk about older versions
I need to add a cookie to the OkHttp client requests, how is it done with OkHttp 3?
In my case i simply want to statically add it to client calls without receiving it from the server
There are 2 ways you can do this:
OkHttpClient client = new OkHttpClient().newBuilder()
.cookieJar(new CookieJar() {
#Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
}
#Override
public List<Cookie> loadForRequest(HttpUrl url) {
Arrays.asList(createNonPersistentCookie());
}
})
.build();
// ...
public static Cookie createNonPersistentCookie() {
return new Cookie.Builder()
.domain("publicobject.com")
.path("/")
.name("cookie-name")
.value("cookie-value")
.httpOnly()
.secure()
.build();
}
or simply
OkHttpClient client = new OkHttpClient().newBuilder()
.addInterceptor(chain -> {
final Request original = chain.request();
final Request authorized = original.newBuilder()
.addHeader("Cookie", "cookie-name=cookie-value")
.build();
return chain.proceed(authorized);
})
.build();
I have a feeling that the second suggestion is what you need.
You can find here a working example.
If you need to set a cookie for a single request you can just add the header:
Request request = new Request.Builder()
.addHeader("Cookie", "yourcookie")
.url("http://yoursite.com")
.build();
Otherwise, if you want to read cookies returned by the server and attach them to other requests you will need a CookieJar. For Android you can use the PersistentCookieJar library which handles cookies properly and also saves them in the shared preferences:
ClearableCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(context));
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cookieJar(cookieJar)
.build();
I had the same needs, I made my own library.
You can force set cookies like this with OkHttp3CookieHelper on https://github.com/riversun/okhttp3-cookie-helper .
String url = "https://example.com/webapi";
OkHttp3CookieHelper cookieHelper = new OkHttp3CookieHelper();
cookieHelper.setCookie(url, "cookie_name", "cookie_value");
OkHttpClient client = new OkHttpClient.Builder()
.cookieJar(cookieHelper.cookieJar())
.build();
Request request = new Request.Builder()
.url(url)
.build();
Gradle
compile 'org.riversun:okhttp3-cookie-helper:1.0.0'
Maven
<dependency>
<groupId>org.riversun</groupId>
<artifactId>okhttp3-cookie-helper</artifactId>
<version>1.0.0</version>
</dependency>
I think a better way to do this is by adding the cookie to the cookieJar. OkHttp will then automatically add the cookies to the request with an interceptor: https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/internal/http/BridgeInterceptor.java
cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
JavaNetCookieJar cookieJar = new JavaNetCookieJar(cookieManager);
// add cookies to cookiejar
cookieJar.saveFromResponse("Cookie", listOfCookiesToAdd);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.cookieJar(cookieJar)
I didn't actually try this code, but it should work.
I see that ResponseInterceptors are present in OkHttp. I would like to use one, but I'm using Retrofit rather than OkHttp directly.
My question is firstly is it possible to use ResponseInterceptors with retrofit? If so how? There's api methods for Request interceptors but I can't find any corresponding Response methods.
For anyone who stumbles across this, I managed to find the answer after further searching. Note that the below requires OkHttp 2.2+ and retrofit 1.9+
//First create the OkHttp client and add your response interceptor
OkHttpClient httpClient = new OkHttpClient();
httpClient.interceptors().add(new ApiResponseInterceptor());
//then set the client on your RestAdapter
RestAdapter.Builder builder = new RestAdapter.Builder()
.setEndpoint(ACCOUNTS_SERVICE_BASE_URL)
.setClient(new OkClient(httpClient))
.setConverter(new GsonConverter(gson))
.setRequestInterceptor(getAuthRequestInterceptor())
.setLogLevel(RestAdapter.LogLevel.FULL);
See also this this question, which appears to be a duplicate of this one. One possibility is to override the execute method in Retrofit's OkClient:
OkClient client = new OkClient(okHttpClient) {
#Override
public retrofit.client.Response execute(retrofit.client.Request request) throws IOException {
retrofit.client.Response response = super.execute(request);
// Inspect 'response' before returning it
return response;
}
};
RestAdapter.Builder restAdapterBuilder = new RestAdapter.Builder()
.setEndpoint(API_BASE_URL)
.setClient(client);