I am doing a asynchronous http request to a web service. I am not that sure if this is the correct way to do it but it works.
Is this the correct way to make POST + authentication with HttpAsyncClient?
Should I close the httpclient at the end with httpclient.close(); ?
public void asyncHttpRequest() {
try {
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(3000)
.setConnectTimeout(3000).build();
CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom()
.setDefaultRequestConfig(requestConfig)
.build();
httpclient.start();
String postParameter = new JSONObject().put("key", "value").toString(); //Creating JSON string
HttpPost httpPost = new HttpPost("http://www.url.com");
httpPost.setEntity(new StringEntity(postParameter));
UsernamePasswordCredentials creds
= new UsernamePasswordCredentials("username", "password");
httpPost.addHeader(new BasicScheme().authenticate(creds, httpPost, null));
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
httpclient.execute(httpPost, new FutureCallback<HttpResponse>() {
#Override
public void completed(final HttpResponse response) {
try {
InputStream responseBody = response.getEntity().getContent();
String serverResponse = IOUtils.toString(responseBody);
System.out.println("Server response : " + serverResponse);
System.out.println(httpPost.getRequestLine() + "->" + response.getStatusLine());
} catch (IOException | UnsupportedOperationException ex) {
//Do something
}
}
#Override
public void failed(final Exception ex) {
//Do something
}
#Override
public void cancelled() {
//Do something
}
});
} catch (IOException ex) {
//Do something
} catch (AuthenticationException ex) {
//Do something
}
}
Any help is appreciated!
I would suggest using a credentials provider like below, instead of explicitly adding a header for basic authentication:
CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials creds =
new UsernamePasswordCredentials("username", "password");
provider.setCredentials(AuthScope.ANY, creds);
CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom()
.setDefaultRequestConfig(requestConfig)
.setDefaultCredentialsProvider(provider)
.build();
Also, it would be best to explicitly close the httpclient after the request has been completely processed.
Related
I'm making REST API service with another REST API service.
When I post a request to use external REST API service, the post can't reach on target.
The target host requires static IP address and HTTP protcol, so I use Fixie on Heroku.
I get following messages on heroku.
o.apache.http.impl.execchain.RetryExec : I/O exception (org.apache.http.NoHttpResponseException) caught when processing request to {tls}->http://xxxxx.usefixie.com:80->https://my-target-host.com:443: The target server failed to respond
o.apache.http.impl.execchain.RetryExec : Retrying request to {tls}->http://xxxxx.usefixie.com:80->https://my-target-host.com:443 org.apache.http.NoHttpResponseException: my-target-host.com:443 failed to respond
Currentry, the host don't expose access log.
These are my Java code.
Code-A.
HttpPost post = new HttpPost("/action");
HttpHost targetHost = new HttpHost("my-target-host.com",443,"https");
post.setHeader("Content-Type", "application/json; charset=UTF-8");
try{
URL proxyUrl = new URL(System.getenv("FIXIE_URL"));
HttpHost proxy = new HttpHost(proxyUrl.getHost(), proxyUrl.getPort());
HttpRoutePlanner routePlanner = new HttpRoutePlanner() {
#Override
public HttpRoute determineRoute(HttpHost target, org.apache.http.HttpRequest request,
org.apache.http.protocol.HttpContext context) throws HttpException {
return new HttpRoute(target, null, new HttpHost(proxyUrl.getHost(), proxyUrl.getPort()), true);
}
};
try (CloseableHttpClient httpclient = HttpClients.custom().setRoutePlanner(routePlanner).build();) {
try {
post.setEntity(new StringEntity(CONTENT_JSON, StandardCharsets.UTF_8));
CloseableHttpResponse res = httpclient.execute(targetHost,post);
} catch (Exception e) {
e.printStackTrace();
}
}catch(Exception e){
e.printStackTrace();
}
}catch(Exception e){
e.printStackTrace();
}
Code-B.
HttpPost post = new HttpPost("/action");
HttpHost targetHost = new HttpHost("my-target-host.com",443,"https");
post.setHeader("Content-Type", "application/json; charset=UTF-8");
try{
URL proxyUrl = new URL(System.getenv("FIXIE_URL"));
String userInfo = proxyUrl.getUserInfo();
String user = userInfo.substring(0, userInfo.indexOf(':'));
String password = userInfo.substring(userInfo.indexOf(':') + 1);
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(proxyUrl.getHost(),proxyUrl.getPort()),
new UsernamePasswordCredentials(user,password));
try (CloseableHttpClient httpclient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();) {
HttpHost proxy = new HttpHost(proxyUrl.getHost(), proxyUrl.getPort());
RequestConfig config = RequestConfig.custom().setProxy(proxy).build();
post.setConfig(config);
String encodedAuth = Base64.getEncoder().encodeToString(userInfo.getBytes());
post.setHeader("Proxy-Authorization", "Basic " + encodedAuth);
try {
post.setEntity(new StringEntity(CONTENT_JSON, StandardCharsets.UTF_8));
CloseableHttpResponse res = httpclient.execute(targetHost,post);
} catch (Exception e) {
e.printStackTrace();
}
}catch(Exception e){
e.printStackTrace();
}
}catch(Exception e){
e.printStackTrace();
}
Code-C.
HttpPost post = new HttpPost("/action");
HttpHost targetHost = new HttpHost("my-tareget-host.com",443,"https");
try{
URL proxyUrl = new URL(System.getenv("FIXIE_URL"));
String userInfo = proxyUrl.getUserInfo();
String user = userInfo.substring(0, userInfo.indexOf(':'));
String password = userInfo.substring(userInfo.indexOf(':') + 1);
DefaultHttpClient httpclient_ = new DefaultHttpClient();
try {
httpclient_.getCredentialsProvider().setCredentials(
new AuthScope(proxyUrl.getHost(), proxyUrl.getPort()),
new UsernamePasswordCredentials(user, password));
HttpHost proxy = new HttpHost(proxyUrl.getHost(), proxyUrl.getPort());
httpclient_.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
String encodedAuth = Base64.getEncoder().encodeToString(userInfo.getBytes());
post.setEntity(new StringEntity(CONTENT_JSON, StandardCharsets.UTF_8));
post.setHeader("Proxy-Authorization", "Basic " + encodedAuth);
HttpResponse rsp = httpclient_.execute(targetHost, post);
} finally {
httpclient_.getConnectionManager().shutdown();
}
}catch(Exception e){
e.printStackTrace();
}
These code cause same result.
On same environment, this ruby code is reached.
RestClient.proxy = ENV['FIXIE_URL'] if ENV['FIXIE_URL']
RestClient.post("https://my-target-host.com/action", CONTENT_JSON, {
'Content-Type' => 'application/json; charset=UTF-8'
})
What's happend on access? What should I modify on Java?
I started to learn about how to make an Android application. I tried to connect my app to rails server by using httpclient, however I cannot understand how to connect between app and the remote server.
Here is part of my code, and I matched id form inside "BasicNameValuePair" with html id values. Please let me know how to check whether login is successful or not.
class SendPost extends AsyncTask<Void, Void, String>
{
protected String doInBackground(Void... unused) {
String content = executeClient();
return content;
}
protected void onPostExecute(String result) {
}
public String executeClient() {
ArrayList<NameValuePair> post = new ArrayList<NameValuePair>();
post.add(new BasicNameValuePair("user_name", "SallyCook"));
post.add(new BasicNameValuePair("user_email", "domain#ppls.kr"));
post.add(new BasicNameValuePair("user_password", "add123456"));
post.add(new BasicNameValuePair("user_password_confirmation", "add123456"));
post.add(new BasicNameValuePair("user_phone", "01013089579"));
HttpClient client = new DefaultHttpClient();
HttpParams params = client.getParams();
System.out.println(params);
HttpConnectionParams.setConnectionTimeout(params, 5000);
HttpConnectionParams.setSoTimeout(params, 5000);
HttpPost httpPost = new HttpPost("http://www.ppls.kr/users/sign_up");
try {
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(post, "UTF-8");
httpPost.setEntity(entity);
HttpResponse responsePost = client.execute(httpPost);
System.out.println(responsePost.getStatusLine());
HttpEntity resEntity=responsePost.getEntity();
if (resEntity != null) {
Log.w("RESPONSE", EntityUtils.toString(resEntity));
}
return EntityUtils.getContentCharSet(entity);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
I've been trying to get a simple android client server app working, and I've had nothing but trouble. I'm hoping someone can look at this code and see what I'm doing wrong, maybe I'm doing things in the wrong order, or forgetting something? Just adding the relevant parts
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.addRequestProperty("Content-Type", "application/json");
// set some made up parameters
String str = "{'login':'superman#super.com','password':'password'}";
byte[] outputInBytes = str.getBytes("UTF-8");
OutputStream os = conn.getOutputStream();
os.write( outputInBytes );
os.close();
// connection.setDoOutput(true); //should trigger POST - move above -> crash
conn.setRequestMethod("POST"); // explicitly set POST -move above so we can set params -> crash
conn.setDoInput(true);
The error I get is
'exception: java.net.ProtocolException: method does not support a
request body: GET'
If I just do a POST request without parameters it's fine, so I guess I should move the connection.setDoOutput(true); or conn.setRequestMethod("POST"); higher up, that should work right? When I do that I get the error:
exception: java.net.ProtocolException: Connection already established.
So, if I try to set to POST before adding parameters it doesn't work, if I try to do it after it doesn't work... what am I missing? Is there another way I should be doing this? Am I adding parameters incorrectly? I've been searching for a simple android networking example, and I can't find any, is there any example the official Android site? All I want to do is a very basic network operation, this is so frustrating!
EDIT: I need to use HttpsURLConnection for reasons not included in the above code- I need to authenticate, trust hosts, etc- so I'm really looking for a potential fix for the above code if possible.
Here is an example of how to post with a JSON Object:
JSONObject payload=new JSONObject();
try {
payload.put("password", params[1]);
payload.put("userName", params[0]);
} catch (JSONException e) {
e.printStackTrace();
}
String responseString="";
try
{
HttpPost httpPost = new HttpPost("www.theUrlYouQWant.com");
httpPost.setEntity(new StringEntity(payload.toString()));
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
HttpResponse response = new DefaultHttpClient().execute(httpPost);
responseString = EntityUtils.toString(response.getEntity());
}
catch (ClientProtocolException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
And example of how to get
String responseString = "";
//check if the username exists
StringBuilder builder = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("www.theUrlYouQWant.com");
ArrayList<String> existingUserName = new ArrayList<String>();
try
{
HttpResponse response = client.execute(httpGet);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) {
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(content));
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
}
else
{
Log.e(ParseException.class.toString(), "Failed to download file");
}
}
catch (ClientProtocolException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
I followed this tutorial on making http calls:
http://www.androidhive.info/2012/01/android-json-parsing-tutorial/
Works fine with no problems.
Below is a class that I have modified from the sample:
public class ServiceHandler {
static String response = null;
public final static int GET = 1;
public final static int POST = 2;
String TAG = ((Object) this).getClass().getSimpleName();
public ServiceHandler() {
}
/**
* Making service call
*
* #url - url to make request
* #method - http request method
*/
public String makeServiceCall(String url, int method) {
return this.makeServiceCall(url, method, null);
}
/**
* Making service call
*
* #url - url to make request
* #method - http request method
* #params - http request params
*/
public String makeServiceCall(String url, int method,
List<NameValuePair> params) {
try {
// http client
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is established.
// The default value is zero, that means the timeout is not used.
int timeoutConnection = 2000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 2000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
HttpEntity httpEntity = null;
HttpResponse httpResponse = null;
// Checking http request method type
if (method == POST) {
HttpPost httpPost = new HttpPost(url);
// adding post params
if (params != null) {
httpPost.setEntity(new UrlEncodedFormEntity(params));
}
httpResponse = httpClient.execute(httpPost);
} else if (method == GET) {
// appending params to url
if (params != null) {
String paramString = URLEncodedUtils
.format(params, "utf-8");
url += "?" + paramString;
}
Log.e("Request: ", "> " + url);
HttpGet httpGet = new HttpGet(url);
httpResponse = httpClient.execute(httpGet);
}
if (httpResponse != null) {
httpEntity = httpResponse.getEntity();
} else {
Log.e(TAG, "httpResponse is null");
}
response = EntityUtils.toString(httpEntity);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
}
And this is how I use the class:
nameValuePairs = new ArrayList<NameValuePair>();
String param_value = "value";
String param_name = "name";
nameValuePairs.add(new BasicNameValuePair(param_name, param_value));
// Creating service handler class instance
sh = new ServiceHandler();
String json = sh.makeServiceCall(Utils.getUrl, ServiceHandler.GET, nameValuePairs);
I need to send http POST request from mobile android application to the server side applcation.
This request need to contain json message in body and some key-value parametres.
I am try to write this method:
public static String makePostRequest(String url, String body, BasicHttpParams params) throws ClientProtocolException, IOException {
Logger.i(HttpClientAndroid.class, "Make post request");
HttpPost httpPost = new HttpPost(url);
StringEntity entity = new StringEntity(body);
httpPost.setParams(params);
httpPost.setEntity(entity);
HttpResponse response = getHttpClient().execute(httpPost);
return handleResponse(response);
}
Here i set parametres to request throught method setParams and set json body throught setEntity.
But it isn't work.
Can anybody help to me?
You can use a NameValuePair to do this..........
Below is the code from my project where I used NameValuePair to sent the xml data and receive the xml response, this will provide u some idea about how to use it with JSON.
public String postData(String url, String xmlQuery) {
final String urlStr = url;
final String xmlStr = xmlQuery;
final StringBuilder sb = new StringBuilder();
Thread t1 = new Thread(new Runnable() {
public void run() {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(urlStr);
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(
1);
nameValuePairs.add(new BasicNameValuePair("xml", xmlStr));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
Log.d("Vivek", response.toString());
HttpEntity entity = response.getEntity();
InputStream i = entity.getContent();
Log.d("Vivek", i.toString());
InputStreamReader isr = new InputStreamReader(i);
BufferedReader br = new BufferedReader(isr);
String s = null;
while ((s = br.readLine()) != null) {
Log.d("YumZing", s);
sb.append(s);
}
Log.d("Check Now",sb+"");
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
t1.start();
try {
t1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Getting from Post Data Method "+sb.toString());
return sb.toString();
}
I'm trying to connect to a SharePoint url so I used the example code in httpcomponents-client-4.2.1\examples\org\apache\http\examples\client\ClientAuthentication.java but changed it to NTCredentials to ignore certificate problems. Apart from this the code is the same but outputs this:
executing requestGET url HTTP/1.1
----------------------------------------
HTTP/1.1 401 Unauthorized
Response content length: 0
Here is the full code
public class DocumentApprover {
static final String user = "user"; // your account name
static final String pass = "password"; // your password for the account
public static DefaultHttpClient wrapClient(DefaultHttpClient base) {
try {
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = base.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", 443, ssf));
return new DefaultHttpClient(ccm, base.getParams());
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
DefaultHttpClient httpclient = wrapClient(new DefaultHttpClient());
try {
httpclient.getCredentialsProvider().setCredentials(
new AuthScope("host", 443),
new NTCredentials(user, pass, "workstation", "domain"));
HttpGet httpget = new HttpGet("url");
System.out.println("executing request" + httpget.getRequestLine());
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
}
EntityUtils.consume(entity);
} finally {
// When HttpClient instance is no longer needed,
// shut down the connection manager to ensure
// immediate deallocation of all system resources
httpclient.getConnectionManager().shutdown();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Why is it failing? If the credentials were wrong wouldn't I get a different error?