I have a curl of the form curl -v -u username:password -H "Content-Type: application/json"........
Not able to crack how to get the -u part working. Have tried multiple options like
Authenticator proxyAuthenticator = new Authenticator() {
#Override
public Request authenticate(Route route, Response response) throws IOException {
String credential = Credentials.basic("username", "password");
return response.request().newBuilder()
.addHeader("Proxy-Authorization", credential)
.addHeader("Content-Type", "application/json")
.build();
}
};
and
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
RequestBody requestBody = new FormBody.Builder().add("username", "password").build();
Request request = original.newBuilder()
.addHeader("Content-Type", "application/json")
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
});
Both of which are not working. Not able to get it working even by posting it as header. Please help out!
Solved it by this.
protected Authenticator getBasicAuth(final String username, final String password) {
return new Authenticator() {
private int mCounter = 0;
#Override
public Request authenticate(Route route, Response response) throws IOException {
if (mCounter++ > 0) {
return null;
} else {
String credential = Credentials.basic(username, password);
return response.request().newBuilder().header("Authorization", credential).build();
}
}
};
}
then added this as authenticator to my client.
Related
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
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.
I need to make a request through a proxy that needs authentication.
public class WebClient {
private final OkHttpClient httpClient;
private static WebClient webClient;
private WebClient() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (Configurator.getInstance().useProxy()) {
builder.proxySelector(new CustomProxySelector());
builder.authenticator((Route route, Response response) -> {
String credential = Credentials.basic("MYUSER", "MYPSW");
return response.request().newBuilder().header("Authorization", credential).build();
});
} else
builder.proxy(Proxy.NO_PROXY);
httpClient = builder
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.build();
}
}
But using a debugger i see that the authenticator method never gets called and i receive 407 as response for any request.
However, when i use HttpURLConnection with Authenticator.setDefault, it works just fine and i can use my proxy authentication:
public boolean hasInternetConnection() throws IOException {
Request httpRequest = new Request.Builder().url("http://www.google.com/").build();
// This fails with 407
Response httpResponse = httpClient.newCall(httpRequest).execute();
java.net.Authenticator authenticator = new java.net.Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return (new PasswordAuthentication("MYUSER", "MYPSW".toCharArray()));
}
};
java.net.Authenticator.setDefault(authenticator);
URL obj = new URL("http://www.google.com/");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
// This works with 200
int responseCode = con.getResponseCode();
return false;
}
So i think the question is: why OkHttpClient.Builder.authenticator method is not getting called?
As Gimby pointed, one of the issues was that i was calling the wrong method. What confused me was that sometimes the proxyAuthenticator was not getting called and i was trying to figure why.
The application i develop needs to access resources inside and outside my job network. Therefore, when i need external access, i must use a proxy with authentication. It works like this:
A request to an internet host is made;
The ProxySelector decides that the HTTP client should use the proxy for this
request, since it is an internet host;
Since the proxy is set, the ProxyAuthenticator gets called to send
the authorization header in the request.
However, when a request is made to an internal host, the ProxySelector decides that there is no need to use a proxy. Therefore, the ProxyAuthenticator does not get called, since there is no active proxy.
Here is my implementation to anyone interested:
WebClient.java
public class WebClient {
private final OkHttpClient httpClient;
private static WebClient webClient;
private WebClient() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (Configurator.getInstance().useProxy()) {
CodeUtils.setProxy();
builder.proxySelector(new CustomProxySelector());
builder.proxyAuthenticator(new CustomProxyAuthenticator());
} else {
builder.proxy(Proxy.NO_PROXY);
CodeUtils.removeProxy();
}
httpClient = builder
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.build();
}
public static WebClient getInstance() {
return webClient != null ? webClient : (webClient = new WebClient());
}
public static void reload() {
webClient = null;
}
public String doGet(String url) throws IOException {
Request httpRequest = new Request.Builder().url(url).build();
Response httpResponse = httpClient.newCall(httpRequest).execute();
if (httpResponse.code() != 200) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("success", false);
jsonObject.put("msg", httpResponse.body().string());
jsonObject.put("httpCode", httpResponse.code());
return jsonObject.toString();
}
return httpResponse.body().string();
}
public String doPost(String url, JSONObject body) throws IOException {
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), body.toString());
Request request = new Request.Builder()
.header("Accept", "application/json")
.header("Content-type", "application/json; charset=UTF-8")
.url(url)
.post(requestBody).build();
Response response = httpClient.newCall(request).execute();
return response.body().string();
}
}
CustomProxyAuthenticator.java
public class CustomProxyAuthenticator implements Authenticator {
#Override
public Request authenticate(Route route, Response response) throws IOException {
String username = Configurator.getInstance().getProxyUser();
String password = Configurator.getInstance().getProxyPassword();
String credential = Credentials.basic(username, password);
return response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build();
}
}
CustomProxySelector.java
public class CustomProxySelector extends ProxySelector {
private Configurator configurator = Configurator.getInstance();
private List<String> nonProxyHosts = Arrays.asList(configurator.getNonProxyHosts().split("\\|"));
private String proxyHost = configurator.getProxyHost();
private int proxyPort = configurator.getProxyPort();
#Override
public List<Proxy> select(URI uri) {
final List<Proxy> proxyList = new ArrayList<>(1);
String host = uri.getHost();
if (host.startsWith("127.0.0.1") || nonProxyHosts.contains(host))
proxyList.add(Proxy.NO_PROXY);
else
proxyList.add(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)));
return proxyList;
}
#Override
public void connectFailed(URI arg0, SocketAddress arg1, IOException arg2) {
}
}
This error message of OkHttp v3.4.1 has already been discussed a few times, and each time I read about it, people were not closing the response body:
WARNING: A connection to http://www.example.com/ was leaked. Did you forget to close a response body?
But my code reads like this:
private String executeRequest(Request request) throws IOException {
Response response = httpClient.newCall(request).execute();
try (ResponseBody responseBody = response.body()) {
String string = responseBody.string();
logger.debug("Result: {}", string);
return string;
}
}
So responseBody.close() is always called. How come I get the above error? I configured a custom JWT interceptor, but I don't see how it could cause the problem:
public class JwtInterceptor implements Interceptor {
private String jwt;
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (jwt != null) {
request = request.newBuilder()
.addHeader("Authorization", "Bearer " + jwt)
.build();
}
Response response = chain.proceed(request);
String jwt = response.header("jwt");
if (jwt != null) {
this.jwt = jwt;
}
return chain.proceed(request);
}
}
Turns out my interceptor was bugged:
return chain.proceed(request);
should be:
return response;
We can use this way in Kotlin
try {
val req: Request = Request.Builder().url(url).get().build()
val client = OkHttpClient()
val resp: Response = client.newCall(req).execute()
val code: Int = resp.code() // can be any value
body= resp.body()
if (code == 200) {
body?.close() // I close it explicitly
}
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 {
}
});