Can not stop retrofit sending - java

I use retrofit and OkHttp3 library to send some messages to a server and set its as below :
okClient = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15,TimeUnit.SECONDS)
.addInterceptor(interceptor)
.build();
When I want to send a large message(which, for example, it takes about 2 minutes), Retrofit sends my file completely, and after 2 minutes, I get the TimeOut message. If I expect to stop sending after 15 seconds and show me the Error message.
Is there a specific item that I must comply with? Please guide me.
Or suggest me a standard way to break this operation after 15 second.
mycode:
class RetrofitFactory {
private static final RetrofitFactory INSTANCE = new RetrofitFactory();
public static RetrofitFactory getInstance() {
return INSTANCE;
}
public OkHttpClient getOkHttp()
{
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
okClient = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15,TimeUnit.SECONDS)
.addInterceptor(new GzipRequestInterceptor())
.addInterceptor(interceptor)
.build();
return okClient;
}
public myInterface getlimit()
{
if (retrofit == null) {
OkHttpClient okClient = getOkHttp();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
retrofit = new Retrofit.Builder()
.client(okClient)
.baseUrl(BuildConfig.BASEURL)
.addConverterFactory(JacksonConverterFactory.create(objectMapper))
.build();
}
return retrofit.create(myInterface.class);
}
}
public interface myInterface{
#POST("api/ReadingApi/Something")
Call<Something> DoReading(
#Body List<Something> list,
#Header("Authorization") String auth);
}
Call<DoReadResult> x = RetrofitFactory.getInstance().getlimit().DoReading(
data, "Something");
response = x.execute();
Update:
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-jackson:2.5.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'

As you said you are using retrofit , so you need to cancel your call easily with retrofit Call :
Call<ResponseBody> call =
uploadService.uploadSomething(fileUrl);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.d(TAG, "request success");
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e(TAG, "request failed");
}
});
}
call.cancel();
with call.cancel(); you can cancel your request.
See more here :
Retrofit Cancel Request

Related

Getting Model has not been initialized. Please buildModel first for a retrofit api call

I am making a retrofit call in this way:-
APIInterface apiInterface = APIClient.getClient().create(APIInterface.class);
AppLogger.getInstance().e("TAG", "Request visit: " +obj1);
Call<ResponseBody> call1=apimethod(obj1);
call1.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
AppLogger.getInstance().e("TAG", "Response add " + response.body()
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
AppLogger.getInstance().e("Tag", "Response add " +t);
}
});
and my API Call is like:-
#POST("route for the route")
Call<ResponseBody> apimethod(#Body Class1 obj);
and I am initializing retrofit object in this way:-
public static Retrofit getClient() {
HttpsTrustManager.allowAllSSL();
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
client=getUnsafeOkHttpClient().build();
retrofit = new Retrofit.Builder()
.baseUrl("<apiurl>")
.addConverterFactory(GsonConverterFactory.create())
.client(getUnsafeOkHttpClient().build())
.build();
return retrofit;
}
But while submitting the response:-
Req body is correct as per the api body
{Object }
and the final response is like which is very weird:-
I/okhttp.OkHttpClient: {"timestamp":"2020-06-28T12:28:20.410+0000","status":404,"error":"Not Found","message":"Model has not been initialized. Please buildModel first","path":"<route for it>"}
Here all details are getting initialised but unable to get why this is saying Model is not intialised

Basic authentication with retrofit2 for cloudinary

Im trying to authenticate to Cloudinary API service using the below code but i get 401 unauthorized error, it expects credentials in this format https://API_KEY:API_SECRET#..., when i substitute with actual values it works great with browser/postman but fails with retrofit2, below is my code.
// create and initialize retrofit2 client
public static OkHttpClient getClient(){
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(Level.BASIC);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.addHeader("API_KEY","API_SECRET")
.addHeader("Accept","Application/JSON").build();
return chain.proceed(request);
}
})
.addInterceptor(interceptor)
.build();
return client;
}
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl){
if (retrofit == null){
retrofit = new Retrofit.Builder()
.client(getClient())
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
// Interface with get methods to access image resources
public interface CloudinaryService {
#GET("resources/image")
Call<imageresponse> getImageResource();
}
// Util class to make requests
public class ApiUtils {
private static final String BASE_URL = "http://api.cloudinary.com/v...";
public static CloudinaryService getImageService(){
return RetrofitClient.getClient(BASE_URL)
.create(CloudinaryService.class);
}
}
Any help fixing the error will be highly appreciated, not sure if need custom converter. thanks
***** Edit******
public static String credentials = Credentials.basic(API_KEY,API_SECRET);
OkHttpClient client = new OkHttpClient.Builder()
// .authenticator(new Authenticator() {
// #Override
// public Request authenticate(Route route, Response response) throws IOException {
//
// return response.request().newBuilder().header("Authorization", credentials).build();
// }
// })
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = (chain.request().newBuilder()
.header("Accept","Application/JSON")
.header("Cache-Control", "public, max-age=" + 60)
.header("Authorization",credentials).build());
return chain.proceed(request);
}
})
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.addInterceptor(loggingInterceptor)
.addInterceptor(provideOfflineCacheInterceptor())
.addNetworkInterceptor(provideCacheInterceptor())
.cache(getCache())
.build();
return client;
}
I was able to fix the issue with adding authenticator to the builder.
.authenticator(new Authenticator() {
#Override
public Request authenticate(Route route, Response response) throws IOException {
return response.request().newBuilder().header("Authorization", credentials).build();
}
})
thanks for all your help.
request = chain.request();
builder = request.newBuilder();
if (TextUtils.isEmpty(request.header(AUTH)) && UserPreference.getInstance().isSignin())
builder.addHeader(AUTH, UserPreference.getInstance().getAccessToken());
if (NetUtil.hasNetwork(GridInnApplication.getInstance()))
builder.header(USER_AGENT, userAgent);
else
builder.cacheControl(CacheControl.FORCE_CACHE);
request = builder.build();
Response response = chain.proceed(request);
if (NetUtil.hasNetwork(GridInnApplication.getInstance())) {
String cacheControl = request.cacheControl().toString();
return response.newBuilder()
.header(CACHE_CONTROL, cacheControl)
.removeHeader(PRAGMA)
.build();
} else {
return response.newBuilder()
.addHeader(CACHE_CONTROL, CACHE_CONTROL_ONLY_CACHED)
.removeHeader(PRAGMA)
.build();
}
//you can results before returing intercept
The answer provided by leafNext will work but will cause every request to be sent twice - The authenticator only kicks in if the server responds with 401. You send the request, get 401 and then send it again with proper credentials.
The correct solution is to provide the credentials from the get go, using the interceptor. It's similar to what you tried to do originally, but you got the syntax wrong. The expected format is basic authentication.
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
// Request customization: add request headers
return chain.proceed(chain.request().newBuilder()
.header("Authorization", credentials).build());
}
});
Where credentials should follow the basic authentication protocol: Assuming the Api key is key and the secret is secret, you base64-encode the expression key:secret and prefix it with Basic. In this example the value of credentials should end up like so:
Basic a2V5OnNlY3JldA==
Edit - Added a fully working independent code bit to verify basic auth is working for okhttp (and thus with retrofit when using okhttp):
public int testBasicAuth() throws IOException {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = (chain.request().newBuilder()
.header("Authorization",okhttp3.Credentials.basic(KEY, SECRET)).build());
return chain.proceed(request);
}
}).build();
Request request = new Request.Builder()
.url("https://api.cloudinary.com/v1_1/[cloud_name]/resources/image")
.build();
int code = client.newCall(request).execute().code();
return code; // 200
}

retrofit 2.0 how to print the full json response?

I am moving from Volley to Retrofit currently version 2.0.
How to print the the full json response code ?
includes:
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
RestClient:
OkHttpClient client = new OkHttpClient();
client.interceptors().add(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return response;
}
});
Gson gson = new GsonBuilder()
.setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ROOT)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build();
REST_CLIENT = retrofit.create(APIService.class);
APIService:
#GET("my/json")
Call<Model> getFeed();
In Activity - Calling API:
Call<Model> call = RestClient.get().getFeed();
call.enqueue(new Callback<Model>() {
#Override
public void onResponse(Response<Model> response, Retrofit retrofit) {
Log.w("2.0 getFeed > response.raw() => ", response.raw().toString());//DONT WORK
Log.w("2.0 getFeed > retrofit => ", retrofit.toString());//DONT WORK
Log.w("2.0 getFeed > body => ", response.body().toString()); //DONT WORK
Log.w("2.0 getFeed > getStatus => ", response.body().getStatus());
}
#Override
public void onFailure(Throwable t) {
t.printStackTrace();
Log.e("2.0 getFeed > onFailure => ", t.toString());
}
});
To print the full response in json:
Log.w("2.0 getFeed > Full json res wrapped in gson => ",new Gson().toJson(response));
If you'd like to have pretty print feature, use:
Log.w("2.0 getFeed > Full json res wrapped in pretty printed gson => ",new GsonBuilder().setPrettyPrinting().create().toJson(response));
Note that this prints the deserialized data (not raw response as returned from server). To get the raw response, you may use one of these:
Use HttpLoggingInterceptor see: https://stackoverflow.com/a/33256827/2267723 or have your own version of interceptor
Use http debugging tools such Stetho. see: http://facebook.github.io/stetho/ or Charles Web Debugging Proxy. see: https://www.charlesproxy.com
Actually Square already create a class just for this, just add
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor).build();
And, in Retrofit
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.baseUrl("https://yourapi.com/api/")
.build();
The interceptor class is in maven central
compile 'com.squareup.okhttp3:logging-interceptor:3.5.0'
You can set the logging level in HttpLoggingInterceptor class. BODY is the verbose one (it print everything to the Body). Further information is available on OkHttp github
Caution!
Don't forget to remove Interceptors (or change Logging Level to NONE) in production! Otherwise people will be able to see your request and response on Log Cat.
Plug in the following interceptor class like this
OkHttpClient client = new OkHttpClient();
client.interceptors().add(new LoggingInterceptor());
//////Interceptor class
public static class LoggingInterceptor implements Interceptor {
#Override
public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
Log.i("LoggingInterceptor","inside intercept callback");
Request request = chain.request();
long t1 = System.nanoTime();
String requestLog = String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers());
if(request.method().compareToIgnoreCase("post")==0){
requestLog ="\n"+requestLog+"\n"+bodyToString(request);
}
Log.d("TAG","request"+"\n"+requestLog);
com.squareup.okhttp.Response response = chain.proceed(request);
long t2 = System.nanoTime();
String responseLog = String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers());
String bodyString = response.body().string();
Log.d("TAG","response only"+"\n"+bodyString);
Log.d("TAG","response"+"\n"+responseLog+"\n"+bodyString);
return response.newBuilder()
.body(ResponseBody.create(response.body().contentType(), bodyString))
.build();
}
public static String bodyToString(final Request request) {
try {
final Request copy = request.newBuilder().build();
final Buffer buffer = new Buffer();
copy.body().writeTo(buffer);
return buffer.readUtf8();
} catch (final IOException e) {
return "did not work";
}
}`
Courtesy: https://github.com/square/retrofit/issues/1072#
To get full response in Json in retrofit use below.
this works for me.
call.enqueue(new Callback<someList>() {
#Override
public void onResponse(Call<someList> call, Response<someList> response) {
if (response.isSuccessful())
Log.e("Success", new Gson().toJson(response.body()));
else
Log.e("unSuccess", new Gson().toJson(response.errorBody()));
}
#Override
public void onFailure(Call<someList> call, Throwable t) {
Log.e("onFailure", t.toString());
}
});
You can setLogLevel to your Retrofit adapter like below, and see the response and other data such as header, response code vs.
setLogLevel(LogLevel.FULL)
If you're using Retrofit version 2+ you have to set OkHttpLoggingInterceptor to see logs.
First add OkHttpLoggingInterceptor to your project:
com.squareup.okhttp3:logging-interceptor:${Versions.okHttpLoggingInterceptorVersion}
And than create init your interceptor:
HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY }
And finally add it to your OkHttpClient
with(OkHttpClient.Builder()) {
if (BuildConfig.DEBUG) addInterceptor(loggingInterceptor)
build()
}
Try this !!
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
/** Handles Log */
retrofit.client().interceptors().add(new LoggingInterceptor());
mRestClient = retrofit.create(RestServices.class);
class LoggingInterceptor implements Interceptor {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
long t1 = System.nanoTime();
Logger.d(String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
Response response = chain.proceed(request);
long t2 = System.nanoTime();
Logger.d(String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers()));
final String responseString = new String(response.body().bytes());
Logger.d("Response: " + responseString);
return response.newBuilder()
.body(ResponseBody.create(response.body().contentType(), responseString))
.build();
}
Check this Demo !!!
Log.e("TAG","2.0 getFeed > response.raw() => " + new Gson().toJson(response.body()));
public class HttpLoggingInterceptor {
HttpLoggingInterceptor provideHttpLoggingInterceptor(){
return new HttpLoggingInterceptor(message ->
Log.d("TAG", message)).setLevel(HttpLoggingInterceptor.Level.BODY);
}
}
public class OkHttpClient {
OkHttpClient provideOkHttpClient(#NonNull HttpLoggingInterceptor interceptor){
return new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
}
}
Try this :
Log.d("LOG","RESPONSE ==="+response.raw().toString());
Take a look on okhttp3.logging package, they already have HttpLoggingInterceptor that you can use for your needs.
And depending on them you can also specify logging level.
and you can include this interceptor to your request as mentioned - via OkHttpClient.Builder:
public OkHttpClient provideOkHttpClient() {
final OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
okHttpBuilder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));
return okHttpBuilder.build();
}
To get full json response with retrofit 2.0 follow code given below
Api Interface
#GET("my/json")
Call<JsonObject> getFeed();
Retrofit Call function
Call<JsonObject> call = RestClient.get().getFeed();
call.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
Log.d("res", response.body().toString());
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Log.d("error",t.getMessage());
}
});
Call<Model> call = RestClient.get().getFeed();call.enqueue(new Callbstrong
textack<Model>() {
#Override
public void onResponse(Response<Model> response, Retrofit retrofit) {
//try this
Call<Model> call = response.body();
// this is enough for retrieve model
}
#Override
public void onFailure(Throwable t) {
t.printStackTrace();
og.e("2.0 getFeed > onFailure => ", t.toString());
}
});

Adding header to all request with Retrofit 2

Retrofit 2's documentation says:
Headers that need to be added to every request can be specified using an OkHttp interceptor.
It can be done easily using the previous version, here's the related QA.
But using retrofit 2, I couldn't find something like setRequestInterceptor or setInterceptor method that can be applied to Retrofit.Builder object.
Also it seems that there's no RequestInterceptor in OkHttp anymore. Retrofit's doc refers us to Interceptor that I didn't quite understand how to use it for this purpose.
How can I do this?
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder().addHeader("parameter", "value").build();
return chain.proceed(request);
}
});
Retrofit retrofit = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create()).baseUrl(url).client(httpClient.build()).build();
The Latest Retrofit Version HERE -> 2.1.0.
lambda version:
builder.addInterceptor(chain -> {
Request request = chain.request().newBuilder().addHeader("key", "value").build();
return chain.proceed(request);
});
ugly long version:
builder.addInterceptor(new Interceptor() {
#Override public Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder().addHeader("key", "value").build();
return chain.proceed(request);
}
});
full version:
class Factory {
public static APIService create(Context context) {
OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
builder.readTimeout(10, TimeUnit.SECONDS);
builder.connectTimeout(5, TimeUnit.SECONDS);
if (BuildConfig.DEBUG) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
builder.addInterceptor(interceptor);
}
builder.addInterceptor(chain -> {
Request request = chain.request().newBuilder().addHeader("key", "value").build();
return chain.proceed(request);
});
builder.addInterceptor(new UnauthorisedInterceptor(context));
OkHttpClient client = builder.build();
Retrofit retrofit =
new Retrofit.Builder().baseUrl(APIService.ENDPOINT).client(client).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();
return retrofit.create(APIService.class);
}
}
gradle file (you need to add the logging interceptor if you plan to use it):
//----- Retrofit
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile "com.squareup.retrofit2:converter-gson:2.1.0"
compile "com.squareup.retrofit2:adapter-rxjava:2.1.0"
compile 'com.squareup.okhttp3:logging-interceptor:3.4.0'
Try this type header for Retrofit 1.9 and 2.0. For Json Content Type.
#Headers({"Accept: application/json"})
#POST("user/classes")
Call<playlist> addToPlaylist(#Body PlaylistParm parm);
You can add many more headers i.e
#Headers({
"Accept: application/json",
"User-Agent: Your-App-Name",
"Cache-Control: max-age=640000"
})
Dynamically Add to headers:
#POST("user/classes")
Call<ResponseModel> addToPlaylist(#Header("Content-Type") String content_type, #Body RequestModel req);
Call you method i.e
mAPI.addToPlayList("application/json", playListParam);
Or
Want to pass everytime then Create HttpClient object with http Interceptor:
OkHttpClient httpClient = new OkHttpClient();
httpClient.networkInterceptors().add(new Interceptor() {
#Override
public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
Request.Builder requestBuilder = chain.request().newBuilder();
requestBuilder.header("Content-Type", "application/json");
return chain.proceed(requestBuilder.build());
}
});
Then add to retrofit object
Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL).client(httpClient).build();
UPDATE if you are using Kotlin remove the { } else it will not work
For Logging your request and response you need an interceptor and also for setting the header you need an interceptor, Here's the solution for adding both the interceptor at once using retrofit 2.1
public OkHttpClient getHeader(final String authorizationValue ) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okClient = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.addNetworkInterceptor(
new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = null;
if (authorizationValue != null) {
Log.d("--Authorization-- ", authorizationValue);
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.addHeader("Authorization", authorizationValue);
request = requestBuilder.build();
}
return chain.proceed(request);
}
})
.build();
return okClient;
}
Now in your retrofit object add this header in the client
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.client(getHeader(authorizationValue))
.addConverterFactory(GsonConverterFactory.create())
.build();
In my case addInterceptor()didn't work to add HTTP headers to my request, I had to use addNetworkInterceptor(). Code is as follows:
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addNetworkInterceptor(new AddHeaderInterceptor());
And the interceptor code:
public class AddHeaderInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();
builder.addHeader("Authorization", "MyauthHeaderContent");
return chain.proceed(builder.build());
}
}
This and more examples on this gist
If you use addInterceptor method for add HttpLoggingInterceptor, it won't be logging the things that added by other interceptors applied later than HttpLoggingInterceptor.
For example: If you have two interceptors "HttpLoggingInterceptor" and "AuthInterceptor", and HttpLoggingInterceptor applied first, then you
can't view the http-params or headers which set by AuthInterceptor.
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.addNetworkInterceptor(logging)
.addInterceptor(new AuthInterceptor());
I solved it, via using addNetworkInterceptor method.
In kotlin adding interceptor looks that way:
.addInterceptor{ it.proceed(it.request().newBuilder().addHeader("Cache-Control", "no-store").build())}
Use this Retrofit Client
class RetrofitClient2(context: Context) : OkHttpClient() {
private var mContext:Context = context
private var retrofit: Retrofit? = null
val client: Retrofit?
get() {
val logging = HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
val client = OkHttpClient.Builder()
.connectTimeout(Constants.TIME_OUT, TimeUnit.SECONDS)
.readTimeout(Constants.TIME_OUT, TimeUnit.SECONDS)
.writeTimeout(Constants.TIME_OUT, TimeUnit.SECONDS)
client.addInterceptor(logging)
client.interceptors().add(AddCookiesInterceptor(mContext))
val gson = GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").create()
if (retrofit == null) {
retrofit = Retrofit.Builder()
.baseUrl(Constants.URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client.build())
.build()
}
return retrofit
}
}
I'm passing the JWT along with every request. Please don't mind the variable names, it's a bit confusing.
class AddCookiesInterceptor(context: Context) : Interceptor {
val mContext: Context = context
#Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val builder = chain.request().newBuilder()
val preferences = CookieStore().getCookies(mContext)
if (preferences != null) {
for (cookie in preferences!!) {
builder.addHeader("Authorization", cookie)
}
}
return chain.proceed(builder.build())
}
}
RetrofitHelper library written in kotlin, will let you make API calls, using a few lines of code.
Add headers in your application class like this :
class Application : Application() {
override fun onCreate() {
super.onCreate()
retrofitClient = RetrofitClient.instance
//api url
.setBaseUrl("https://reqres.in/")
//you can set multiple urls
// .setUrl("example","http://ngrok.io/api/")
//set timeouts
.setConnectionTimeout(4)
.setReadingTimeout(15)
//enable cache
.enableCaching(this)
//add Headers
.addHeader("Content-Type", "application/json")
.addHeader("client", "android")
.addHeader("language", Locale.getDefault().language)
.addHeader("os", android.os.Build.VERSION.RELEASE)
}
companion object {
lateinit var retrofitClient: RetrofitClient
}
}
And then make your call:
retrofitClient.Get<GetResponseModel>()
//set path
.setPath("api/users/2")
//set url params Key-Value or HashMap
.setUrlParams("KEY","Value")
// you can add header here
.addHeaders("key","value")
.setResponseHandler(GetResponseModel::class.java,
object : ResponseHandler<GetResponseModel>() {
override fun onSuccess(response: Response<GetResponseModel>) {
super.onSuccess(response)
//handle response
}
}).run(this)
For more information see the documentation
Kotlin version would be
fun getHeaderInterceptor():Interceptor{
return object : Interceptor {
#Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val request =
chain.request().newBuilder()
.header(Headers.KEY_AUTHORIZATION, "Bearer.....")
.build()
return chain.proceed(request)
}
}
}
private fun createOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.apply {
if(BuildConfig.DEBUG){
this.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC))
}
}
.addInterceptor(getHeaderInterceptor())
.build()
}

How to define a Header to all request using Retrofit?

I'm looking for a solution to define a unique Header to use in all requests. Today I use #Header to each request did pass like parameter but I want define only header that works in all requests without to need pass like a parameter, for example fixing this Header on my requests #GET and #POST
Today I use this. Note that each request #GET I need define Header as parameter.
//interface
#GET("/json.php")
void getUsuarioLogin(
#Header("Authorization") String token,
#QueryMap Map<String, String> params,
Callback<JsonElement> response
);
//interface
#GET("/json.php")
void addUsuario(
#Header("Authorization") String token,
#QueryMap Map<String, String> params,
Callback<JsonElement> response
);
//using
public void getUsuarioLogin(){
Map<String, String> params = new HashMap<String, String>();
params.put("email", "me#mydomain.com");
params.put("senha", ConvertStringToMD5.getMD5("mypassword"));
RestAdapter adapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(WebServiceURL.getBaseWebServiceURL())
.build();
UsuarioListener listener = adapter.create(UsuarioListener.class);
listener.getUsuarioLogin(
//header
"Basic " + BasicAuthenticationRest.getBasicAuthentication(),
params,
new Callback<JsonElement>() {
#Override
public void success(JsonElement arg0, Response arg1) {
Log.i("Usuario:", arg0.toString() + "");
}
#Override
public void failure(RetrofitError arg0) {
Log.e("ERROR:", arg0.getLocalizedMessage());
}
});
}
//using
public void addUsuario(){
Map<String, String> params = new HashMap<String, String>();
params.put("name", "Fernando");
params.put("lastName", "Paiva");
RestAdapter adapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(WebServiceURL.getBaseWebServiceURL())
.build();
UsuarioListener listener = adapter.create(UsuarioListener.class);
listener.addUsuario(
//header
"Basic " + BasicAuthenticationRest.getBasicAuthentication(),
params,
new Callback<JsonElement>() {
#Override
public void success(JsonElement arg0, Response arg1) {
Log.i("Usuario:", arg0.toString() + "");
}
#Override
public void failure(RetrofitError arg0) {
Log.e("ERROR:", arg0.getLocalizedMessage());
}
});
}
Official document:
Headers that need to be added to every request can be specified using a RequestInterceptor. The following code creates a RequestInterceptor that will add a User-Agent header to every request.
RequestInterceptor requestInterceptor = new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
request.addHeader("User-Agent", "Retrofit-Sample-App");
}
};
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com")
.setRequestInterceptor(requestInterceptor)
.build();
In Retrofit 2, you need to intercept the request on the network layer provided by OkHttp
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("User-Agent", "Your-App-Name")
.header("Accept", "application/vnd.yourapi.v1.full+json")
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
}
OkHttpClient client = httpClient.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
Check this, it explains the differences very well.
Depending on your OkHttp lib:
OkHttpClient httpClient = new OkHttpClient();
httpClient.networkInterceptors().add(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder().addHeader("User-Agent", System.getProperty("http.agent")).build();
return chain.proceed(request);
}
});
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient)
.build();
As the other answers have described, you need a RequestInterceptor. Luckily, this interface has a single method, so Java 8 and above will treat it as a functional interface and let you implement it with a lambda. Simple!
For example, if you're wrapping a specific API and need a header for each endpoint, you might do this when you build your adapter:
RestAdapter whatever = new RestAdapter.Builder().setEndpoint(endpoint)
.setRequestInterceptor(r -> r.addHeader("X-Special-Vendor-Header", "2.0.0"))
.build()
Here's the solution for adding header using retrofit 2.1. We need to add interceptor
public OkHttpClient getHeader(final String authorizationValue ) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okClient = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.addNetworkInterceptor(
new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = null;
if (authorizationValue != null) {
Log.d("--Authorization-- ", authorizationValue);
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.addHeader("Authorization", authorizationValue);
request = requestBuilder.build();
}
return chain.proceed(request);
}
})
.build();
return okClient;
}
Now in your retrofit object add this header in the client
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.client(getHeader(authorizationValue))
.addConverterFactory(GsonConverterFactory.create())
.build();

Categories