In previous retrofit versions it was possible to add an interceptor and use that to add query parameters that were globally needed for example:
.setRequestInterceptor(new RequestInterceptor() {
#Override
public void intercept(RequestFacade requestFacade) {
requestFacade.addQueryParam("platform", "android");
requestFacade.addQueryParam("app_version", com.package.BuildConfig.VERSION_NAME);
}
})
With the new implementation, it's required that you use OkHttpClient.interceptors. With this new approach, how would one append parameters without removing the original paramaters?
Here is an okhttp implementation --
OkHttpClient client = new OkHttpClient();
client.interceptors().add(new Interceptor() {
#Override
public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
HttpUrl url = request.httpUrl().newBuilder()
.addQueryParameter("platform", "android")
.addQueryParameter("app_version", com.package.BuildConfig.VERSION_NAME)
.build();
Request newRequest = chain.request().newBuilder().url(url).build();
return chain.proceed(newRequest);
}
});
Add the client to your retrofit --
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.example.com")
.client(client)
.build();
With retrofix 2.3.0 the following code can be used:
final OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
#Override
public Response intercept(final Chain chain) throws IOException
{
final Request request = chain.request();
final HttpUrl url = chain.request().url().newBuilder()
.addQueryParameter("platform", "android")
.addQueryParameter("app_version", com.package.BuildConfig.VERSION_NAME)
.build();
final Request newRequest = chain.request().newBuilder().url(url).build();
return chain.proceed(newRequest);
}
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.example.com")
.client(client)
.build();
Related
On some device i have no problems with a communication with the server used with the retrofit framework. I also used several Android versions to verify that the code run. But on some devices (Samsung S8) I got each time an error: 'Handshake failed'. Does anybody have an idea where is the problem? Thanks!
Here is my code:
protected static Retrofit getInstanceWithoutToken() {
final OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
final Request original = chain.request();
final Request request = original.newBuilder()
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
});
return new Retrofit.Builder()
.baseUrl(CommonConstantsRest.REST_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
}
The problem was the ssl communication. Adding the following CipherSuite solved the problem
protected static Retrofit getInstanceWithoutToken() {
ConnectionSpec spec = new
ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.cipherSuites(
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
.build();
final OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
httpClient.connectionSpecs(Collections.singletonList(spec));
httpClient
.addInterceptor(logging)
.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
final Request original = chain.request();
final Request request = original.newBuilder()
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
});
return new Retrofit.Builder()
.baseUrl(CommonConstantsRest.REST_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
}
I have Singleton dagger module for OkHttp client and I am trying to add header using Interceptor
#Provides
#Singleton
OkHttpClient provideOkhttpClient(Cache cache, final LocalData localData) {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.HEADERS);
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.readTimeout(60, TimeUnit.SECONDS);
client.addInterceptor(logging);
client.addNetworkInterceptor(new Interceptor() {
#Override
public Response intercept(#NonNull Chain chain) throws IOException {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.addHeader("Hp-Application", "Android");
Request request = requestBuilder.build();
Response originalResponse = chain.proceed(request);
try {
if (originalResponse.code() == 200) {
localData.setLastUpdateTime(System.currentTimeMillis());
}
} catch (Exception e) {
e.printStackTrace();
}
return originalResponse;
}
});
client.connectTimeout(60, TimeUnit.SECONDS);
client.cache(cache);
return client.build();
}
But looking to the logs I can't see expected header. Also I receive error, as specific call don't work without required header.
I also tried to add it with addInterceptor()/addNetworkInterceptor() using different class
public class HeaderInterceptor
implements Interceptor {
#Override
public Response intercept(Chain chain)
throws IOException {
Request request = chain.request();
request = request.newBuilder()
.addHeader("Hp-Application", "Android")
.build();
return chain.proceed(request);
}
}
But this way didn't work for me too.
How can I add this header to each call of application having only one implementation?
The order you add the interceptors matters. Your logging interceptor runs first, and only after that is the header-adding interceptor run.
For best logging experience, make the logging interceptor the last one you add.
Hey #Igor try this snippet this might help
public class RetrofitClient {
private static String BASE_URL = "http://192.168.0.100/rest/main.php/";
private static Retrofit retrofit = null;
public static Retrofit getRetroftInstance() {
if (retrofit == null) {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addNetworkInterceptor(new SessionRequestInterceptor());
httpClient.addNetworkInterceptor(new ReceivedCookiesInterceptor());
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
}
return retrofit;
}}
public class ReceivedCookiesInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
if (!originalResponse.headers("Set-Cookie").isEmpty()) {
HashSet<String> cookies = new HashSet<>();
for (String header : originalResponse.headers("Set-Cookie")) {
cookies.add(header);
if(header.startsWith("XSRF-TOKEN")) {
String newCookie[]=header.split(";");
System.out.println("newCookie Length: "+newCookie.length);
for(String ss:newCookie) {
if(ss.startsWith("XSRF-TOKEN")) {
System.out.println("Cookies ss: " + ss);
sharedPrefs.setToken(ss);
}
}
}
}
}
return originalResponse;
}
}
public class SessionRequestInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request.Builder request = original.newBuilder();
request.header("Cookie",ServiceSharedPrefs.getInstance().getToken()));
request.method(original.method(), original.body());
return chain.proceed(request.build());
}
}
new OkHttpClient.Builder()
.addInterceptor(
new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder().
header(AUTHENTICATION_HEADER, AUTHENTICATION_KEY).
method(original.method(), original.body());
Request request = requestBuilder.build();
//System.out.println(request.toString());
return chain.proceed(request);
}
}).addInterceptor(logging)
.build();
i using retrofit2 and want add some header using OkHttp3 addInterceptor
but not working
this is my code
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.removeHeader("Authorization")
.removeHeader("Content-type")
.removeHeader("User-Agent")
.addHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8")
.addHeader("Accept-Language", "en-US")
.addHeader("User-Agent", ApiConfig.userAgent)
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
});
OkHttpClient client = httpClient.build();
if (apiInterface == null) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiConfig.baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(client)
.build();
apiInterface = retrofit.create(ApiInterface.class);
}
return apiInterface;
please help me.
kind regards
Try this if it helps
RestAdapter.Builder builder = new RestAdapter.Builder()
.setRequestInterceptor(new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
request.addHeader("Accept", "application/json;versions=1");
if (isUserLoggedIn()) {
request.addHeader("Authorization", getToken());
}
}
});
I am using Retrofit 2 and Okhttp for my android project. I want to add multiple headers in the api request.
This is my interceptor code :
public class NetworkInterceptors implements Interceptor {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.addHeader("Userid", "10034")
.addHeader("Securitykey", "Fb47Gi")
.build();
return chain.proceed(request);
}
}
This is not working properly. In server side I am getting only the last added header (in the above example I am getting only Securitykey missing "Userid" )
Please Help.
Thanks for support
I found the answer, This is working fine for me
public class NetworkInterceptors implements Interceptor {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
Request newRequest;
newRequest = request.newBuilder()
.addHeader("Userid", "10034")
.addHeader("Securitykey", "Fb47Gi")
.build();
return chain.proceed(newRequest);
}
}
You can use this class pass the context in this class if user already logged in.
public class ApiClient {
public static final String BASE_URL = "";
private static Retrofit retrofit = null;
static Context mcontext;
public static Retrofit getClient(Context context,String baseUrl)
{
mcontext = context;
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(220, TimeUnit.SECONDS)// Set connection timeout
.readTimeout(220, TimeUnit.SECONDS)// Read timeout
.writeTimeout(220, TimeUnit.SECONDS)// Write timeout
.addInterceptor( HeaderInterceptor() )
// .addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)// Add cache interceptor
// .cache(cache)// Add cache
.build();
Gson gson = new GsonBuilder()
.setLenient()
.create();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
return retrofit;
}
private static Interceptor HeaderInterceptor() {
return new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
okhttp3.Request request = chain.request();
if(SharedPreference.getlogin(mcontext).equals("")){
request = request.newBuilder()
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer "+SharedPreference.gettoken(mcontext))
.build();
}
else {
request = request.newBuilder()
.addHeader("Accept", "application/json")
.build();
}
okhttp3.Response response = chain.proceed(request);
return response;
}
};
}
}
I'd like to intercept all responses received by the retrofit engine, and scan for HTTP error code, for example error 403.
I'm aware I can use the failure(RetrofitError error) callback of every request and check for 403's but I'd like to wrap the response globally.
I can see that request interception is possible, but I do not see a similar option for response.
Any suggestions?
I was able to accomplish that by adding an interceptor to the OkHttpClient that retrofit is using.
Kotlin + Retrofit 2.x
val clientBuilder = OkHttpClient.Builder()
clientBuilder.addInterceptor { chain ->
val request = chain.request()
val response = chain.proceed(request)
if (response.code() == 403) {
handleForbiddenResponse()
}
response
}
Retrofit 2.x:
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
clientBuilder.
addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
if (response.code() == 403) {
handleForbiddenResponse();
}
return response;
}
});
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(clientBuilder.build();)
.build();
Retrofit 1.x:
public class ForbiddenInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
if (response.code() == 403) {
handleForbiddenResponse();
}
return response;
}
}
OkHttpClient okHttpClient = Utils.createUnsafeOkHttpClient();
okHttpClient.interceptors().add(new ForbiddenInterceptor());
RestAdapter.Builder restAdapterBuilder = new RestAdapter.Builder()
.setEndpoint(API_BASE_URL)
.setClient(new OkClient(okHttpClient));
Another possibility is to override the execute method in Retrofit's OkClient. In my case I was looking for a specific response header, so it went something like this:
OkClient client = new OkClient(okHttpClient) {
#Override
public retrofit.client.Response execute(retrofit.client.Request request) throws IOException {
retrofit.client.Response response = super.execute(request);
// Do whatever with 'response', such as looking for the value of a particular header:
List<retrofit.client.Header> headers = response.getHeaders();
for (retrofit.client.Header header : headers) {
if (MY_HEADER.equalsIgnoreCase(header.getName())) {
this.savedValue = header.getValue();
break;
}
}
return response;
}
};
RestAdapter.Builder restAdapterBuilder = new RestAdapter.Builder()
.setEndpoint(API_BASE_URL)
.setClient(client);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
okhttp3.Response response = chain.proceed(request);
// todo deal with the issues the way you need to
if (response.code() == 500) {
startActivity(
new Intent(
ErrorHandlingActivity.this,
ServerIsBrokenActivity.class
)
);
return response;
}
return response;
}
})
.build();
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://your_url")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
As you can see in the snippet above, the okhttp3.Response response = chain.proceed(request); line accesses the server response. Consequently, we can check the status code with if (response.code() == 500) and then open the ServerIsBrokenActivity.