OkHTTP (v3.0.0-RC1) Post Request with Parameters - java

UPDATE
I'm using okHttp library, version 3.0.0 RC-1. I have a url and I have to send a post request with parameters. For example: https://myurl.com/login?username=123456&password=12345
I have code like this:
public String okHttpRequest(){
try {
final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
#Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
};
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null,trustAllCerts, new java.security.SecureRandom());
final javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory);
builder.hostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}).build();
final OkHttpClient client = new OkHttpClient();
HttpUrl url = HttpUrl.parse("https://myUrl.com/login").newBuilder()
.addQueryParameter("username", "123456")
.addQueryParameter("password", "123456")
.build();
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
Log.d("Request:", "Is NOT sent " + request.toString() + " METHOD: " + request.method());
e.printStackTrace();
}
#Override
public void onResponse(Response response) throws IOException {
Log.d("Request:", "Is sent " + response.toString());
}
});
}catch(Exception e){
e.printStackTrace();
}
return "okHttp is Working!!! ";
}
Whenever I try, It fails, so onFailure method is executing. What is the problem? Am I adding request params incorrectly? Please help...

Yes, you are adding the query parameters incorrectly. Here's how it should be done:
final OkHttpClient client = new OkHttpClient();
HttpUrl url = HttpUrl.parse("https://myUrl.com/login").newBuilder()
.addQueryParameter("password", "123456")
.addQueryParameter("username", "123456")
.build();
Request request = new Request.Builder()
.url(url)
.build();
(...)
The problem is that you are submitting your data in the body of the request, as if it were a HTML form submit, and not as a query parameter, as you intended. Using HttpUrl allows you to add query parameters to your URL.
Worth noting that you can also simply do this:
Request request = new Request.Builder()
.url("https://myurl.com/login?username=123456&password=12345")
.build();
So:
Use HttpUrl and it's builder to create your URL and add parameters.
Use FormBody to create the content of your request (as if it were a html form you're submitting), if you need it.
Also, make sure you have internet permission in your app, make sure you have an active internet connection, etc, but it seems you already have.
Note: this is for OkHttp 2.x (since that's what I use), but it should be the same or similar for 3.x.
Let me know if it works for you.

Related

Getting Request method 'GET' not supported in java using OkHTTP Client and HttpsURLConnection

As I need to send data through post for initiating the API, but getting get not supported error. Even I'm using post method ,Please suggest where I did mistake. I have tried OkHTTPClient and HTTPsURL connection, still getting same error
Error: **{"timestamp":"2021-03-23T06:26:43.508+0000","status":405,"error":"Method Not Allowed","message":"Request method 'GET' not supported","path":"/stsBankResponse/"}**
When I directly hit the URL in browser that time also getting method not allowed ,its valid error but programmatically using Post only even though same error
JSONObject jsobj=new JSONObject();
jsobj.put("authmode", "Abc");
JSONArray jaarray = new JSONArray();
jaarray.put(jsobj);
JSONObject mainObj = new JSONObject();
mainObj.put("bankResponseDtl", jaarray);
String str_jsonparams = String.valueOf(mainObj);
System.out.println("PU_Auth str_jsonparams->"+str_jsonparams);
String proxyhost=common_utility.getProxyHost();
String proxyport=common_utility.getProxyPort();
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyhost, new Integer(proxyport)));
OkHttpClient client = new OkHttpClient();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(30, TimeUnit.SECONDS);
builder.readTimeout(30, TimeUnit.SECONDS);
builder.writeTimeout(30, TimeUnit.SECONDS);
builder.proxy(proxy);
client = builder.build();
RequestBody body = RequestBody.create(JSON, str_jsonparams);
Request request = new Request.Builder()
.url(common_utility.getEmandateServerResponeURL())
.post(body)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
call.cancel();
System.out.println("ECEEEEE"+e);
}
#Override
public void onResponse(Call arg0, Response arg1) throws IOException {
}
});

Retrofit: Making Web Requests to Internal APIs

I want to make a request to my organisation api's. The request contains Headers, UserName, Password, & Cookie for session management.
Below is the actual code (in HttpClient) which I want to rewrite using Retrofit. I have heard that HttpClient libraries have been deprecated or someting so have opted Retrofit. I expect the response with 200 status code.
public static CookieStore cookingStore = new BasicCookieStore();
public static HttpContext context = new BasicHttpContext();
public String getAuth(String login,String password) {
String resp = null;
try {
String url = DOMAIN+"myxyzapi/myanything";
context.setAttribute(HttpClientContext.COOKIE_STORE, cookingStore);
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(url);
String log = URLEncoder.encode(login, "UTF-8");
String pass = URLEncoder.encode(password, "UTF-8");
String json = "username="+log+"&password="+pass+"&maintain=true&finish=Go";
StringEntity entity = new StringEntity(json);
post.setEntity(entity);
post.addHeader("Content-Type", "application/x-www-form-urlencoded");
HttpResponse response = client.execute(post,context);
resp = EntityUtils.toString(response.getEntity());
accountPoller();
} catch(Exception a) {
log.info("Exception in authentication api:"+a.getMessage().toString());
}
return resp;
}
Below is my code where I can't figure out how to pass the context with request. HttpResponse response = client.execute(post,**context**); using retrofit.
I don't even know if I have made my retrofit request right.
try {
String log = URLEncoder.encode(login, "UTF-8");
String pass = URLEncoder.encode(password, "UTF-8");
RequestBody formBody = new FormBody.Builder()
.add("username=", xyz)
.add("password=", mypass)
.add("&maintain=", "true")
.add("finish=", "Go")
.build();
String url = www.xyz.com+"myxyzapi/myanything";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).post(formBody).addHeader("Content-Type", "application/x-www-form-urlencoded").build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
final String myresp = response.body().string();
}
}
});
} catch(Exception a) {
a.getMessage();
}
You have to catch exception and use this class.
retrofit2.HttpException
retrofit2
Class HttpException
int
code()
HTTP status code.
String
message()
HTTP status message.
Response
response()
The full HTTP response.

javax.net.ssl.SSLHandshakeException?

I'm trying to connect to a WCF server using HTTPS connection (UrlHttpsConnection class) and always get the error "Trust anchor for certification path not found".
I found thousands examples on the Web about that issue but nothing that really helps me.
My WCF service works with a certificate signed by an internal CA that has been added to the list of trusted CAs on my smartphone. If I call the url https://myserver/myservice/test from Chrome on my smartphone, I no longer have warning, the certificate is considered as valid. From my app, I keep getting the error message.
Do you know why my app does not consider the server certificate as valid while Chrome does ? How can I fix that ?
For security reasons, I don't want ignore the SSL verification.
Thank you in advance for your suggestions.
Try this way but i used retrofit for api calling..
public class ApiClient {
//public final static String BASE_URL = "https://prod.appowiz.com/app/services/";
public final static String BASE_URL_SECURE = "Pass your url";
public static ApiClient apiClient;
private Retrofit retrofit = null;
private static Retrofit storeRetrofit = null;
public Retrofit getClient(Context context) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL_SECURE)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit;
}
public static Retrofit getStore() {
if (storeRetrofit == null) {
final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
#Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
}
#Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
}
#Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[0];
}
}};
// Install the all-trusting trust manager
final SSLContext sslContext;
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
try {
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
final OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.sslSocketFactory(sslSocketFactory).hostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
.build();
storeRetrofit = new Retrofit.Builder()
.baseUrl(BASE_URL_SECURE)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build();
} catch (NoSuchAlgorithmException | KeyManagementException e1) {
CustomLogHandler.printErrorlog(e1);
}
}
return storeRetrofit;
}
for api calling create interface..
public interface ApiInterface {
#POST("device/add_device_name")
Call<AddDeviceNameVo> addDeviceName(#Body JsonObject body);
}
called api into activity or fragment like this way..
apiInterface = ApiClient.getStore().create(ApiInterface.class);

GET request gives Connection refused

I have following CURL command which works fine using -k options, which means: insecure, Allow connections to SSL sites without certs.
I am using WSO2 API Manager tool version 1.9.1.
curl -k -d "grant_type=password&username=test&password=test" -H
"Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,
Content-Type: application/x-www-form-urlencoded"
https://XXX.XXX.XXX.XXX:8243/token
Now I wanted to achieve the same using the RestTemplate in Spring, so I developed the following code so far, and it's giving me a Connection refused error:
My Code
#Before
public void testBefore(){
disableSslVerification();
}
private static void disableSslVerification() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
#Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
#Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
#Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
#Test
public void testGetTokenFromWSo2(){
String url = "https://XXXXXXXXXXX:8243/token";
MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
map.add("grant_type", "password");
map.add("username", "test");
map.add("password", "test");
HttpHeaders headers =new HttpHeaders();
headers.add("Authorization", "Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
headers.add("Content-Type", "application/x-www-form-urlencoded");
RestTemplate restTemplate = new RestTemplate();
HttpEntity<String> entity = new HttpEntity<String>(headers);
HttpEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class, map);
System.out.println("RESPONSE : "+response.getBody());
}
The error I see
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://XXXXXXXXXXXXXX:8243/token":Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:567)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:520)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:463)
I was able to resolved this error. We can connect to SSL protected site by insecure way i.e, connecting to SSL sites without verifying cert. You can find the solution here and it works fine java.security.cert.CertificateException: No subject alternative names present;.

HTTP Get failing for HTTPS with javax.net.ssl.SSLPeerUnverifiedException

I have been using this infrastructure from past couple of months and it was working fine. I used to hit Google with https and get the result. Suddenly, I started getting SSLPeerVerifiedException for HTTPS URLs. I don't think anything changed. Can anyone point to the reason and resolution?
Various Versions:
Apache-HttpComponents-HttpCore = 4.1;
Apache-HttpComponents-HttpClient = 4.1.1;
JDK = 1.6_64;
Code Snippet:
public void execute(HttpContext httpContext, HttpUriRequest request, HttpHost proxy,
Credentials proxyCredentials) throws IOException {
HttpClient httpClient = getHttpClient(proxy, proxyCredentials, true,
configuration.getHttpConnectionTimeout(), configuration.getHttpSocketTimeout());
httpClient.execute(request, httpContext);
}
/**
* Default constructor
*/
public HttpClientUtil() throws IOException {
/*
* A TrustManager which trusts every server certificates.
*/
TrustManager tm = new X509TrustManager() {
#Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
#Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException { }
#Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException { }
};
try {
SSLContext context = SSLContext.getInstance("TLS");
context.init(new KeyManager[0], new TrustManager[]{tm}, new SecureRandom());
connectionManager = new ThreadSafeClientConnManager();
connectionManager.setMaxTotal(Constant.HTTP_CONNECTION_POOL_MAX_TOTAL_CONNECTIONS);
connectionManager.setDefaultMaxPerRoute(Constant.HTTP_CONNECTION_POOL_DEFAULT_MAX_CONNECTIONS_PER_ROUTE);
connectionManager.getSchemeRegistry().register(new Scheme(Constant.PROTOCOL_HTTPS, Constant.HTTPS_DEFAULT_PORT, new SSLSocketFactory(context)));
} catch (Exception e) {
throw new IOException(e);
}
}
private HttpClient getHttpClient(HttpHost proxy, Credentials proxyCredentials,
boolean followRedirects, int connectionTimeout, int soTimeout) {
DefaultHttpClient client = new DefaultHttpClient(connectionManager);
client.addRequestInterceptor(requestAcceptEncoding);
client.addResponseInterceptor(httpResponseMaskInterceptor);
client.addResponseInterceptor(responseContentEncoding);
HttpParams params = client.getParams();
if (proxy != null) {
params.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
if (proxyCredentials != null) {
client.getCredentialsProvider().setCredentials(
new AuthScope(proxy.getHostName(), proxy.getPort()), proxyCredentials);
}
}
HttpProtocolParams.setUserAgent(params, configuration.getUserAgent());
HttpConnectionParams.setConnectionTimeout(params, connectionTimeout);
HttpConnectionParams.setSoTimeout(params, soTimeout);
HttpClientParams.setRedirecting(params, followRedirects);
if (followRedirects) {
client.setRedirectStrategy(redirectStrategy);
}
return client;
}
Stack trace:
Caused by: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:352)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128)
at org.apache.http.conn.ssl.SSLSocketFactory.createLayeredSocket(SSLSocketFactory.java:446)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.updateSecureConnection(DefaultClientConnectionOperator.java:200)
at org.apache.http.impl.conn.AbstractPoolEntry.layerProtocol(AbstractPoolEntry.java:277)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.layerProtocol(AbstractPooledConnAdapter.java:142)
at org.apache.http.impl.client.DefaultRequestDirector.establishRoute(DefaultRequestDirector.java:758)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:565)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
at com.amazon.mobius.httpproxy.util.HttpClientUtil.execute(HttpClientUtil.java:390)
at com.amazon.mobius.httpproxy.ec2.RequestExecutor.executeViaEC2(RequestExecutor.java:267)
... 45 more
Any help would be appreciated.
Thanks,

Categories