Okhttp Interceptor issue - java

I'm trying to add a header to a simple okhttp (Get) request. How do I add the HttpHeader properly? Can I debug to ensure that my Header is actually sent to the server?
Request request = new Request.Builder()
.url("URL")
.build();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Request newRequest = originalRequest.newBuilder()
.addHeader("Header", "123")
.build();
return chain.proceed(newRequest);
}
})
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
}
I've looked for basic simple examples but they are with Retrofit, GSON, Interfaces, or in Kotlin. Need to understand it codewise.

You can use by method addHeader send chain as param and add headers.
Request getRequest = chain.request();
Request.Builder requestBuilder = getRequest.newBuilder()
.addHeader("Header", "123");
Request request = requestBuilder.build();
return chain.proceed(request);
You can also visit and look at the answers link1 and link2.
Here is the all-request Structure you can use.
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()
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
};
OkHttpClient client = httpClient.build();
Request request = new Request.Builder()
.url("URL")
.addHeader("Header", "123")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
Log.d("OKHTTP3", e.getMessage());
// You get this failure
runOnUiThread(() -> {
});
}
#Override
public void onResponse(Call call, Response response) throws IOException {
try {
final String _body = response.body().string();
Log.d("OKHTTP3", _body);
runOnUiThread(() -> {
});
} catch (InterruptedIOException e) {
runOnUiThread(() -> {
// Or this exception depending when timeout is reached
});
}
}
});

To check your request and to add headers, you can use interceptors.
To add headers, (copied from gist):
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();
To see your headers, you can use sample example provided here:
class LoggingInterceptor implements Interceptor {
#Override public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
long t1 = System.nanoTime();
logger.info(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.info(String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers()));
return response;
}
}

Use addHeader() to add headers. header() sets the already added header name to the value.
Request newRequest = originalRequest.newBuilder()
.addHeader("Header", "123")
.build();
And to verify it's working correctly, you can use HttpLoggingInterceptor to log your network requests.

Related

Unable to Refresh Bearer Token using Retrofit

I'm using Retrofit and OkHttp in my Project and i want to refresh token when the server gives 401 error code and store the new token in shared preference and make the same call again without notifing the user. Token type is bearer and expires every hour.
But the output that i desired is not coming, when the token expires the authenticator does nothing.
ApiInterface.java
public interface ApiInterface {
#FormUrlEncoded
#POST("auth/login")
Call<ResponseBody> login(#FieldMap HashMap<String, Object> map);
#FormUrlEncoded
#POST("auth/register")
Call<ResponseBody> register(#FieldMap HashMap<String, Object> map);
#FormUrlEncoded
#POST("auth/forgotpassword")
Call<ResponseBody> forgotPassword(#FieldMap HashMap<String, Object> map);
#POST("auth/refresh")
Call<ResponseBody> refreshToken(#Header("Authorization") String token);
#POST("auth/GetAllInterests")
Call<ResponseBody> getAllInterest();
#POST("auth/AddUserProfile")
#Multipart
Call<ResponseBody> addUserProfile(
#Part("display_name") RequestBody display_name,
#Part("children_age_show") RequestBody children_age_show,
#Part("address") RequestBody address,
#Part("no_of_children") RequestBody no_of_children,
#Part("children_age") RequestBody children_age,
#Part("date_of_birth") RequestBody date_of_birth,
#Part("interests") RequestBody interests,
#Part List<MultipartBody.Part> images
);
#POST("auth/GetUserProfile")
Call<ResponseBody> getUserProfile();
#FormUrlEncoded
#POST("auth/ChangePassword")
Call<ResponseBody> changePassword(#FieldMap HashMap<String, Object> map);
#POST("auth/logout")
Call<ResponseBody> logout();
}
ApiClient.java
public class ApiClient {
private static Retrofit retrofit = null;
private static ApiInterface apiInterface = null;
public static Retrofit getRetrofit(Context context) {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (AppPreference.getPreference(context, AppPersistence.keys.AUTH_TOKEN) != null) {
request = request.newBuilder()
.addHeader("Authorization", AppPreference.getPreference(context, AppPersistence.keys.AUTH_TOKEN))
.build();
}
return chain.proceed(request);
}
})
.authenticator(new TokenAuthenticator(context))
.build();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
}
return retrofit;
}
public static ApiInterface getApiInterface(Context context) {
if (apiInterface == null) {
getRetrofit(context);
apiInterface = retrofit.create(ApiInterface.class);
}
return apiInterface;
}
}
TokenAuthenticator.java
public class TokenAuthenticator implements Authenticator {
Context context;
public TokenAuthenticator(Context context) {
this.context = context;
}
#Override
public Request authenticate(Route route, Response response) throws IOException {
Log.d("Authenticator", "Authenticator Called");
if (response.code() == 401) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
Log.d("Authenticator", "Requesting for New Token");
ApiInterface apiInterface = retrofit.create(ApiInterface.class);
retrofit2.Response<ResponseBody> response1 = apiInterface
.refreshToken(AppPreference.getPreference(context, AppPersistence.keys.AUTH_TOKEN))
.execute();
if (response1.isSuccessful()) {
try {
String body = response1.body().string();
JSONObject jsonObject = new JSONObject(body);
if (jsonObject.getBoolean("status")) {
String newToken = "Bearer " + jsonObject.getJSONObject("Data").getString("access_token");
AppPreference.setPreference(context, AppPersistence.keys.AUTH_TOKEN, newToken);
Log.d("Authenticator", "New Token Generated");
return response.request().newBuilder()
.header("Authorization", newToken)
.build();
}
} catch (Exception e) {
Log.e("TokenAuthenticator", e.getMessage(), e);
}
}
Toast.makeText(context, response1.body().string(), Toast.LENGTH_SHORT).show();
}
return null;
}
}
Please try the below way
(1) HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
try {
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
// try the request
Response response = chain.proceed(request);
if (response shows expired token) {
// get a new token (I use a synchronous Retrofit call)
// create a new request and modify it accordingly using the new token
Request newRequest = request.newBuilder().build();
// retry the request
return chain.proceed(newRequest);
}
// otherwise just pass the original response on
return response;
}
});
} catch (Exception e) {
e.printStackTrace();
}
String baseUrl = "";
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
apiService = retrofit.create(ApiService.class);
(2) public class TokenAuthenticator implements Authenticator {
private final ApiService apiservice;
public TokenAuthenticator(TokenServiceHolder tokenServiceHolder) {
this.tokenServiceHolder = tokenServiceHolder;
}
#Override
public Request authenticate(Proxy proxy, Response response) throws IOException {
newtoken = apiservice.refreshToken().execute();
return response.request().newBuilder()
.header(AUTHORIZATIONKEY, newtoken)
.build();
}
#Override
public Request authenticateProxy(Proxy proxy, Response response) throws IOException {
// Null indicates no attempt to authenticate.
return null;
}
}
Hope it may help you

Java-Android okhttpclient post request timeout

I do a post request an api running on my localhost but it throws TimeOut exception.
I set every timeout for 1 minutes but still getting error of timeout.
Here is my code for request :
OkHttpClient client = new OkHttpClient.Builder()
.readTimeout(1,TimeUnit.MINUTES)
.writeTimeout(1,TimeUnit.MINUTES)
.connectTimeout(1, TimeUnit.MINUTES)
.build();
RequestBody formBody = new FormBody.Builder()
.add("Username", "***")
.add("Password", "****")
.build();
HttpUrl localUrl = HttpUrl.parse("http://192.168.1.40:44338/api/authorize/login");
Request request = new Request.Builder()
.url(localUrl)
.addHeader("Content-Type","application/json")
.post(formBody)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {
System.out.println("y" + e.getMessage());
e.printStackTrace();
}
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
System.out.println("ccc :" + response.body().string());
}
});

Synchronous request failing HTTP

I am using okHTTP library to make an http request. It goes through but sometimes, my work in android progresses without complete response arrival. I realize this is happening because of the nature of my request being ASYNC.
OkHttpClient client = new OkHttpClient();
String url = "https://beta-pp-api.polkadoc.com/v1.0/products?category=CP&available_via=mail_order";
{
Request request = new Request.Builder()
.url(url)
.addHeader("Authorization", authentication.getToken())
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("X-Service-Code", "PP")
.get()
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e){
//do nothing!
}
#Override
public void onResponse(Response response) throws IOException
try {
jsonArray = new JSONArray(response.body().string());
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
I have tried calling
Response response = client.newCall(request).execute();
However, it fails because in Android we cannot call Sync request on main thread. leads to error NetworkOnMainThread android.os.
Is there a solution to this problem.
Do the process in a background thread something like below:
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.build();
new AsyncTask<Void, Void, JSONArray>() {
#Override
protected JSONArray doInBackground(Void... voids) {
Request request = new Request.Builder()
.url(url)
.addHeader("Authorization", authentication.getToken())
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("X-Service-Code", "PP")
.get()
.build();
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
return new JSONArray(response.body().string());
} else {
// notify error
}
} catch (IOException e) {
// notify error e.getMessage()
}
return null;
}
#Override
protected void onPostExecute(JSONArray jsonArray) {
super.onPostExecute(jsonArray);
if (jsonArray != null && jsonArray.size() > 0) {
// notify status using LocalBroadcastManager or EventBus
}
}
}.execute();

Perform OkHttp network actions in background thread

I am using OKHttp to perform Post request to server, as follow:
public class NetworkManager {
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, JSONObject json) throws IOException {
try {
JSONArray array = json.getJSONArray("d");
RequestBody body = new FormEncodingBuilder()
.add("m", json.getString("m"))
.add("d", array.toString())
.build();
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
} catch (JSONException jsone) {
return "ERROR: " + jsone.getMessage();
}
}
}
and call it with:
NetworkManager manager = new NetworkManager();
String response = manager.post("http://www.example.com/api/", jsonObject);
When I try to run the App, it prompts an error in the logcat:
android.os.NetworkOnMainThreadException
at
android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1273)
With reference to other questions in SO, I added this to override the policy:
if (android.os.Build.VERSION.SDK_INT > 9)
{
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
Yet I think this is unhealthy and I would like to put the NetworkManager actions to background. How can I do so?
Since OkHttp supports async way too, so IMO you can refer to the following GET request sample, then apply for your POST request:
OkHttpClient client = new OkHttpClient();
// GET request
Request request = new Request.Builder()
.url("http://google.com")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
Log.e(LOG_TAG, e.toString());
}
#Override
public void onResponse(Response response) throws IOException {
Log.w(LOG_TAG, response.body().string());
Log.i(LOG_TAG, response.toString());
}
});
Hope it helps!

How to use OkHttp's HttpUrl with a request?

I have an http url:
HttpUrl httpurl = new HttpUrl.Builder()
.scheme("https")
.host("www.google.com")
.addPathSegment("search")
.addQueryParameter("q", "polar bears")
.build();
How do I use that with a request? That is, how do I send a request to the url constructed by httpurl?
Use Request.Builder#url(HttpUrl):
Request r = new Request.Builder()
.url(httpurl).build();
Then follow here.
Try this:
Request request = new Request.Builder()
.method(method, requestBody)
.url(httpurl)
.addHeader(headerName, headerValue);
.build();
OkHttpClient client = new OkHttpClient();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
}
#Override
public void onResponse(Response response) throws IOException {
}
});

Categories

Resources