Apache HttpClient post request with non string values in body - java

I'm using Apache HttpClient version 4.5.13 and I'm having trouble creating my POST request body. From the tutorials I've seen online, they tell me to use NameValuePair when creating the request entity. However, NameValuePair only accepts String for the values.
How can I set Integer, Double, and Booleans as well? The API I'm calling has a mixture of them in the JSON body. For example, my body can look like this:
{
"id": 3,
"name": "Test",
"accepted": false,
"street": "foo bar ave."
}
This is how the documentations recommend I create the body:
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
public static void main(String[] args) {
List<NameValuePair> body = new ArrayList<NameValuePair>();
body.add(new BasicNameValuePair("id", Integer.valueOf(3)));
body.add(new BasicNameValuePair("name", "Test"));
body.add(new BasicNameValuePair("accepted", Boolean.valueOf(false)));
body.add(new BasicNameValuePair("street", "foo bar ave."));
HttpPost httpPost = new HttpPost("http://my-url.com/test-api");
httpPost.setEntity(new UrlEncodedFormEntity(body));
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-Type", "application/json");
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = httpClient.execute(httpPost);
// etc...
}
But as you can see, I have to convert everything to String which the API I'm calling rejects because of the mismatch of data types. Is there some other way I can create the request which accepts various data types?

I was able to fix this by using StringEntity. I converted the code in the question to the following:
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.json.JSONObject;
public static void main(String[] args) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", 3);
jsonObject.put("name", "Test");
jsonObject.put("accepted", false);
jsonObject.put("street", "foo bar ave.");
HttpPost httpPost = new HttpPost("http://my-url.com/test-api");
httpPost.setEntity(new StringEntity(jsonObject.toString()));
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-Type", "application/json");
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = httpClient.execute(httpPost);
// etc...
}
And I was able to call the API in question without any errors. Hopefully, this helps someone!

Related

Send UrlEncodedForm data using euc-jp in Apache HttpClient

I am wondering how I can send form data using euc-jp encoding. My attempt at encoding below is still sending japanese text as ? and odd characters. Thank you!
This is how I am currently doing it (not working properly):
HttpPost request = new HttpPost("http://httpbin.org/post");
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("Testing", "雄大"));
request.setEntity(new UrlEncodedFormEntity(params, forName("EUC-JP")));
Your code seems good to me. httpbin.org doesn't seem to be handle EUC-JP in response. Instead you can use putsreq.com to see your request parameters.
import java.util.*;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.client.methods.*;
import org.apache.http.NameValuePair;
import java.nio.charset.*;
import org.apache.http.impl.client.*;
import org.apache.http.client.*;
import org.apache.http.*;
import java.io.*;
class Main {
public static void main(String[] args) throws Exception {
HttpClient httpclient = new DefaultHttpClient();
// Create new PutsReq URL by yourself
HttpPost request = new HttpPost("https://putsreq.com/xxxxxxxxxxxxxxxxxxxx");
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("Testing", "雄大"));
request.setEntity(new UrlEncodedFormEntity(params, Charset.forName("euc-jp")));
HttpResponse response = httpclient.execute(request);
BufferedReader reader = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));
while ((reader.readLine()) != null) {
System.out.println (reader.readLine());
}
reader.close();
}
}
And you will see
Testing=%CD%BA%C2%E7
in the inspect page. 0xCDBA means 雄 in EUC-JP.

Able to hit in postman but not in java

I am not able to get a response from eclipse when integrated in java code. I am able to retrieve the response from postman/insomnia, but not from eclipse. I masked the token and the URL in this image.
My current code is:
public class Test{
public static void main(String[] args) throws ParseException, IOException {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
httppost.addHeader("Authorization", "Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
httppost.addHeader("Accept", "*/*");
httppost.addHeader("Content-type", "multipart/form-data; boundary=X-INSOMNIA-BOUNDARY");
httppost.addHeader("Host","process-workorders-mti64mke4a-uc.a.run.app");
File fileToUse = new File("D:\\firstImage.jpg"); // this is the image I am uoploadin
FileBody data = new FileBody(fileToUse);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("mode", new StringBody("api"));
reqEntity.addPart("file", data);
*// seems there is issue here in passing form parameters*
httppost.setEntity(reqEntity);
HttpResponse response = httpclient.execute(httppost);
System.out.println( response ) ;
HttpEntity resEntity = response.getEntity();
System.out.println( resEntity ) ;
System.out.println( EntityUtils.toString(resEntity) );
EntityUtils.consume(resEntity);
httpclient.getConnectionManager().shutdown();
}
}
Below are the imports:
import java.io.File;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
Tried OKHTTPClient and it worked

Java Apache HTTP Client - Save Cookie for next request

i'm starting with Programming Java and wan't to create a simple "Backend Crawler". For this i need a login function by Post thats not problem but how i can do the cookies wars saved and on the next request the Script don't need login again?
Can you give me a example? I can't find a solution in the internet.
Maybe you can explain me how i can do the next request with the Cookies from the first Page? :)
Hope for your answer.
Sorry for my bad english.
Here is my first Logintest :P
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
public class Login {
public static String loginAndGetHTML() throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
String html;
HttpPost HttpPost = new HttpPost("http://www.google.com");
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("username", "admin"));
nvps.add(new BasicNameValuePair("password", "1234"));
HttpPost.setEntity(new UrlEncodedFormEntity(nvps));
HttpPost.addHeader("Referer", "http://tutorials.amazingcode.de/login/index.php");
HttpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0");
CloseableHttpResponse response = httpclient.execute(HttpPost);
try {
HttpEntity entity = response.getEntity();
html = EntityUtils.toString(entity);
EntityUtils.consume(entity);
} finally {
response.close();
}
if(html.contains("Falsche Nutzerdaten")) {
throw new Exception("Login fehlgeschlagen");
}
return html;
}
public static String parseHTML(String html) throws Exception {
Document doc = Jsoup.parse(html);
String zahl = doc.getElementById("zahl").text();
return zahl;
}
}
you need to retrieve the Set-Cookie header from the response, store its value,
and ask following requests with Cookie header and that value.
see this post for more explainer on cookies How are cookies passed in the HTTP protocol?

Connect to Dynamic CRM using Java Http Client

I have been trying to connect to CRM using the below Java code, but I am getting an authentication issue.
package com.raj;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
public class MSDynaOData {
/**
* #param args
*/
public static void main(String[] args) throws ClientProtocolException, IOException {
DefaultHttpClient httpclient = new DefaultHttpClient();
NTCredentials creds = new NTCredentials("XXXXXXXXXX", "XXXXXXX", "", "");
httpclient.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
HttpHost target = new HttpHost("XXXXXXXXX", 80, "http");
HttpContext localContext = new BasicHttpContext();
// Execute a cheap method first. This will trigger NTLM authentication
String url = "/XRMServices/2011/Organization.svc/Account";
url += "?$select=Name";
HttpGet httpget = new HttpGet(url);
httpget.addHeader("Accept", "application/json");
HttpResponse response = httpclient.execute(target, httpget, localContext);
HttpEntity entity = response.getEntity();
System.out.println(" Status :: " + response.getStatusLine());
for (Header header : response.getAllHeaders()) {
System.out.println(header.getName() + " : " + header.getValue());
}
System.out.println(IOUtils.toString(entity.getContent()));
}
}
Response contains :
Constants.TokenizedStringMsgs.GENERIC_ERROR = "<H1>Sorry, but we're having trouble signing you in</H1><p>Please try again in a few minutes. If this doesn't work, you might want to contact your admin and report the following error: #~#ErrorCode#~#.</p>";
Constants.TokenizedStringMsgs.UPN_DISAMBIGUATE_MESSAGE = "It looks like #~#MemberName_LS#~# is used with more than one account. Which account do you want to use?";
I am able to login to CRM 2011 online through the credentials used in Java code successfully, but when I used same credentials in the code I am getting the above login issue response.
Please let me know if I am missing anything in the above code.

Problems with HttpMethod.releaseConnection() and EntityUtils.consume(entity)

I'm having a problem: I've just copied the following code from NetBeans to Eclipse (an ADT project). I've imported all the same librarys I used in NetBeans, but I have 2 errors, in the following lines:
EntityUtils.consume(entity); - The method consume(HttpEntity) is undefined for the type EntityUtils
httpPut.releaseConnection(); - The method releaseConnection() is undefined for the type HttpPut
Complete code:
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.util.EntityUtils;
import com.android.lul.classes.User;
public class UserService {
private static final String BASE_URI = "http://localhost:8080/LULServices/webresources";
public static String Login (String login, String password, String ipAdd)
{
String toReturn = null;
final DefaultHttpClient httpclient = new DefaultHttpClient();
try {
httpclient.getCredentialsProvider().setCredentials(
new AuthScope("localhost", 8080),
new UsernamePasswordCredentials("xxxx", "xxxx"));
HttpPut httpPut = new HttpPut(BASE_URI + "/services.users/login");
HttpConnectionParams.setConnectionTimeout(httpclient.getParams(), 10000);
httpPut.addHeader("Content-type", "multipart/form-data");
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("login", "login"));
nameValuePairs.add(new BasicNameValuePair("password", "password"));
httpPut.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httpPut);
try {
HttpEntity entity = response.getEntity();
String putResponse = EntityUtils.toString(entity);
toReturn = putResponse;
EntityUtils.consume(entity);
} finally {
httpPut.releaseConnection();
}
} finally {
httpclient.getConnectionManager().shutdown();
return toReturn;
}
Can you help me?
Thanks
Android comes with a prepackaged version of Apache HttpClient that doesn't have those methods. They are no longer supporting development and that code is outdated.
The Android team recommends that you use HttpUrlConnection for new code instead of HttpClient. More information can be found at this blog on the Android Developers site.
I think you should follow a simpler example, as this one seems to be meant to upload files (multipart/form-data), but regarding the specific problems in your code:
Instead of EntityUtils.consume(entity); you can do entity.consumeContent();
http://developer.android.com/reference/org/apache/http/HttpEntity.html
The HTTPRequest classes (HttpPost, HttpPut) don't have any releaseConnection() method. Probably because they don't need to be released (somebody correct me if I'm wrong). That method is usually applicable for persistent connections which is not the case here.
Check your imports; What version of Apache HttpComponents are you using in your new project?

Categories