okhttp sends both if-modified-since date and if-none-match checksum headers in requests. There's usually no need for both and if-none-match is enough to figure out the version the client has. Sending both just confuses some http/1.1 server implementations
I have tried
builder = new Request.Builder().removeHeader("if-modified-since");
But that doesn't seem to do it. I assume the header is added later.
Is there a way to tell okhttp not to send if-modified-since ?
Yes. you can in builder.
You basically need to rebuild your request. Here is a complete sample:
httpClient.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request newRequest = chain
.request()
.newBuilder()
.removeHeader("if-modified-since")
.build();
return chain.proceed(newRequest);
}
});
Related
Is there any way to edit the body of a network call for adding a default attribute used in the 95% of the calls?
I've seen that a query parameter is pretty easy to add (link)
But, I have not seen it for a Body.
My problem is that I'm working with an old API that asks me to send in each request the token. So I need to add this line in most of the classes.
#SerializedName("token") val token: String
Any ideas?
You should use httpInterceptor to solve this problem if you send in header
final OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
// add token key on request header
// key will be using access token
.addHeader("token", yourToken)
.build();
return chain.proceed(request);
}
});
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
Edit : Im sorry, I've realized now you ask about sending in body.
I think it can be possible with old way(without Gson, Moshi etc). It is really more annoying than adding to every request.
How can we intercept java.net.HttpURLConnection network requests? However, we can achieve interception using OKHTTPClient. Please help.
If you want to modify request/response with OkHttpClient you can use interceptors. For example If you want to add a header to all requests, you can use the code below. Modifying other parts like body is similar.
OkHttpClient okHttpClient = new OkHttpClient().newBuilder().addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Request.Builder builder = originalRequest.newBuilder().header("Authorization",
Credentials.basic("aUsername", "aPassword"));
Request newRequest = builder.build();
return chain.proceed(newRequest);
}
}).build();
I'm using Retrofit2 to make requests to server.
The problem is: sometimes the server will return code 401 for every request from an user. If the user get this code, he should be immediately kicked out from the app (logged out and not be able to do anything before re-login).
So for every request that being sent to the server, I want to check if the server response this code. It's not beautiful writing this check in all the request calls, so I want to write this check only one and it will perform every time user makes request!
Retrofit (current release) needs an HTTP client to make requests. OkHttp library by same developer comes bundled with Retrofit as default client. OkHttp supports adding Interceptor's to the client which can intercept request execution.
For Example:
import android.util.Log;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class ErrorInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
// before request
Request request = chain.request();
// execute request
Response response = chain.proceed(request);
// after request
// inspect status codes of unsuccessful responses
switch (response.code()){
case 401:
// do something else
Log.e("TEST","Unauthorized error for: " +request.url());
// perhaps throw a custom exception ?
throw new IOException("Unauthorized !!");
}
return response;
}
}
To use it, include it in OkHttpClient that Retrofit instance uses:
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new ErrorInterceptor())
.build();
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.baseUrl("/")
.build();
So, you can implement an Interceptor for each "global logic" or "cross-cutting concern" and add them all in a sequence to Retrofit.
If you need check "401" code there is special object in OkHttp for it: Authenticator (Recipes in OkHttp). For example:
public class RefreshTokenAuthenticator implements Authenticator {
#Override
public Request authenticate(Route route, Response response) throws IOException {
// You get here, if response code was 401.
// Then you can somehow change your request or data in your app in this method and resend your request.
Request request = response.request();
HttpUrl url = request.url().newBuilder()
.setQueryParameter("access_token", "new_access_token_may_be")
.build();
request = request.newBuilder()
.url(url)
.build();
return request;
}
}
I'm using Retrofit library version 2 with OkHttpClient.
I want to get some header from all responses.
I found one solution with OkClient:
public class InterceptingOkClient extends OkClient{
public InterceptingOkClient()
{
}
public InterceptingOkClient(OkHttpClient client)
{
super(client);
}
#Override
public Response execute(Request request) throws IOException
{
Response response = super.execute(request);
for (Header header : response.getHeaders())
{
// do something with header
}
return response;
}
}
But how i can do this if i'm using OkHttpClient?
Yes, this is old question.. but still found to answer because myself too was searching similar one.
okHttpClient.interceptors().add(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", "auth-value"); // <-- this is the important line, to add new header - replaces value with same header name.
Request request = requestBuilder.build();
Response response = chain.proceed(request);
Headers allHeaders = response.headers();
String headerValue = allHeaders.get("headerName");
return response;
}
});
Hope, this helps!
P.S: no error handled.
You can use the logging interceptor for that. Add it as an interceptor to your OkHttpClient builder while building the client, set the log level and voila! You will have all the information regarding the request as well as the response.
Here's how you can add the interceptor -
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
okHttpBuilder.addInterceptor(loggingInterceptor);
client = okHttpBuilder.build();
There are four options when it comes to what you want to Log - NONE,BASIC,HEADERS, and BODY.
Now build the the retrofit instance with the above defined client and you will have all the data you need.
So some images I request require an authentication header to be added
I am using Retrofit 2.0 which has this OkHttp client with a interceptor to add the user token to the header to every request
okHttpClient.interceptors().add(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request(); //Current Request
Request requestWithToken = null; //The request with the access token which we will use if we have one instead of the original
requestWithToken = originalRequest.newBuilder().addHeader(Constants.UrlParamConstants.HEADER_AUTHORIZATION,String.format(Constants.UrlParamConstants.HEADER_AUTHORIZATION_VALUE, MyApplication.getInstance().getUser().getApiToken())).build();
Response response = chain.proceed((requestWithToken != null ? requestWithToken : originalRequest)); //proceed with the request and get the response
return response;
}
});
I would like to know how can I set the same okHttp client instance for Fresco library.
I am aware that you need to add this dependency to use OkHttp with Fresco but how about setting the client?
compile "com.facebook.fresco:imagepipeline-okhttp:0.8.0+"
At the end of the day I just need to set authentication header for an image request
thanks for reading
http://frescolib.org/docs/using-other-network-layers.html
Context context;
OkHttpClient okHttpClient; // build on your own
ImagePipelineConfig config = OkHttpImagePipelineConfigFactory
.newBuilder(context, okHttpClient)
. // other setters
. // setNetworkFetcher is already called for you
.build();
Fresco.initialize(context, config);