I would like to send POST request using Java equivalent of the following CURL example:
echo "param value" | curl --data-binary #- -uuser:pass https://url
I've tried apache http setEntity(FileEntity entity), 400 bad request
I've tried apache http setEntity(MultiPartEntity entity), 400 bad request
// ----------------
// General part
String url = "https://url";
String content = "param" + " " + "value";
File file = new File("test.txt");
try {
FileUtils.writeStringToFile(file, content, StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
String encoding = Base64.getEncoder().encodeToString(("user:pass").getBytes());
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
post.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + encoding);
// -----------------
// 1. FileEntity try
FileEntity reqEntity = new FileEntity (file, ContentType.DEFAULT_BINARY);
post.setEntity(reqEntity);
HttpResponse response = httpclient.execute(post);
// ----------------
// 2. Multipart try
MultipartEntity mpEntity = new MultipartEntity();
ContentBody cbFile = new FileBody(file, org.apache.http.entity.ContentType.DEFAULT_BINARY);
mpEntity.addPart("userfile", cbFile);
post.setEntity(mpEntity);
HttpResponse response = httpclient.execute(post);
I've expected to get 200, but got 400 Bad request.
Original CURL works as expected
Problem with boundary parameter is not in the Content-Type header
Actually If you are using one of multipart/ content types, you are actually required to specify the boundary parameter in the Content-Type header ,But in here with curl request not trying generate any boundary values , without boundary values the server (in the case of an HTTP request) will not be able to parse the payload
Related
I am trying to implement the MOT history API https://dvsa.github.io/mot-history-api-documentation/ and they give an example using CURL which works with the supplied api key successfully when using an online CURL tool.
I am trying to implement this in Android and realise I have to use something like HttpPost rather than CURL, this is my code:
//Tried with full URL and by adding the registration as a header.
//HttpPost httpPost = new HttpPost("https://beta.check-mot.service.gov.uk/trade/vehicles/mot-tests?registration=" + reg_selected);
HttpPost httpPost = new HttpPost("https://beta.check-mot.service.gov.uk/trade/vehicles/mot-tests");
httpPost.addHeader("Content-Type", "application/json");
httpPost.addHeader("Accept", "application/json+v6");
httpPost.addHeader("x-api-key", "abcdefgh123456");
httpPost.addHeader("registration", reg_selected);
StringEntity entity = new StringEntity(jsonObj.toString(), HTTP.UTF_8);
httpPost.setEntity(entity);
HttpClient client = new DefaultHttpClient();
try {
HttpResponse response = client.execute(httpPost);
if (response.getStatusLine().getStatusCode() == 200) {
InputStream inputStream = response.getEntity().getContent();
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String readLine = bufferedReader.readLine();
String jsonStr = readLine;
JSONObject myJsonObj = new JSONObject(jsonStr);
}else if (response.getStatusLine().getStatusCode() == 400){
//Bad Request Invalid data in the request. Check your URL and parameters
error_text = "Bad Request";
}else if (response.getStatusLine().getStatusCode() == 403){
//Unauthorised – The x-api-key is missing or invalid in the header
error_text = "Authentication error"; //<<<< FAILS HERE 403
}
response.getStatusLine().getStatusCode() returns • "403 – Unauthorised – The x-api-key is missing or invalid in the header".
However the x-api-key that I use works correctly with the online CURL test so the actual key is correct but how I am adding it to my android code request must be invalid or similar.
Can anyone throw any light as to the correct way to convert the CURL into Android java so that the server does not return 403?
Thanks
It's easy to do with Jsoup:
// CREATE CONNECTION
Connection conn=Jsoup.connect("URL_GOES_HERE");
// ADD POST/FORM DATA
conn.data("KEY", "VALUE");
// ADD HEADERS HERE
conn.header("KEY", "VALUE");
// SET METHOD AS POST
conn.method(Connection.Method.POST);
// ACCEPT RESPONDING CONTENT TYPE
conn.ignoreContentType(true);
try
{
// GET RESPONSE
String response = conn.execute().body();
// USE RESPONSE HERE
// CREATE JSON OBJECT OR ANYTHING...
} catch(HttpStatusException e)
{
int status = e.getStatusCode();
// HANDLE HTTP ERROR HERE
} catch (IOException e)
{
// HANDLE IO ERRORS HERE
}
Ps: I guess you are confused with Header and Post Data. The key etc (Credentials) must be used as Post Data and Content Type etc as Header.
I am trying to send a two binary file to one of the REST API. But I get 400 bad request response from the end point.
Need to send below key and values to endpoint.
userForm - user.xml
structureForm - structure.xdp
Below is the java code, [UPDATED CODE]
HttpPost request = new HttpPost(url);
File userForm = new File("D:\\Downloads\\user.xml");
LOG.info("length ---->" + userForm.length()); // See valid file size
HttpEntity userFormEntity = MultipartEntityBuilder.create()
.addPart("userForm", new FileBody(userForm))
.build();
File structureFile = new File("D:\\Downloads\\structure.xdp");
LOG.info("length structureFile ---->" + structureFile.length()); // See valid file size
HttpEntity structureEntity = MultipartEntityBuilder.create()
.addPart("structureForm", new FileBody(structureFile))
.build();
if (userFormEntity != null && structureEntity != null) {
request.setEntity(userFormEntity);
request.setEntity(structureEntity);
}
final CloseableHttpClient httpClient = HttpClientBuilder.create().build();
CloseableHttpResponse response = httpClient.execute(request);
Seemed like the key 'userForm' and 'structureForm' are not going properly to end point. Is it correct way to send the key?
It is working when I try to submit through postman as below
I want to using docker remote api in this.
I have succeed in this command to create container:
curl -v -X POST -H "Content-Type: application/json" -d '{"Image": " registry:2",}' http://192.168.59.103:2375/containers/create?name=test_remote_reg
Then,I use HttpClient(4.3.1) in java to try to create container via this code:
String containerName = "test_remote_reg";
String imageName = "registry:2";
String url = DockerConfig.getValue("baseURL")+"/containers/create?name="+containerName;
List<NameValuePair> ls = new ArrayList<NameValuePair>();
ls.add(new BasicNameValuePair("Image",imageName));
UrlEncodedFormEntity fromEntity = new UrlEncodedFormEntity(ls, "uTF-8");
HttpPost post = new HttpPost(url);
post.setHeader("Content-Type", " application/json");
if(null!=fromEntity) post.setEntity(fromEntity);
HttpClient client = new DefaultHttpClient();
client.execute(post);
It didn't work, and throw error:
invalid character 'I' looking for beginning of value
I just add header information and add param pair about "Image:test_remote_reg".
What is wrong about my java code? What difference is between they? What should I edit for my java code?
Considering this is a json call, you could use one of the answers of HTTP POST using JSON in Java, like (replace the JSON part by your JSON parameters):
HttpClient httpClient = new DefaultHttpClient();
try {
HttpPost request = new HttpPost("http://yoururl");
StringEntity params =new StringEntity("details={\"name\":\"myname\",\"age\":\"20\"} ");
request.addHeader("content-type", "application/json");
request.addHeader("Accept","application/json");
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
// handle response here...
}catch (Exception ex) {
// handle exception here
} finally {
httpClient.getConnectionManager().shutdown();
}
I am trying to post xml data to API using HTTP post method with credentials but a getting HTTP/1.1 400 Bad Request error .. Can anyone pl help me out ....
Here is my sample code:
BufferedReader br = new BufferedReader(new FileReader(new File("Data.xml")));
StringBuilder sb = new StringBuilder();
while((line=br.readLine())!= null){
sb.append(line.trim());
}
System.out.println("xml: "+sb);
params=sb.toString();
HttpPost request = new HttpPost("*****************url***************");
String urlaparam=URLEncoder.encode("importFormatCode:1&data:"+params,"UTF-8");
String userCredentials = "****:******";
byte[] auth = Base64.encodeBase64(userCredentials.getBytes());
StringEntity entity=new StringEntity(urlaparam);
request.addHeader("Content-type","application/x-www-form-urlencoded");
request.addHeader("Accept", "application/xml");
request.addHeader("Accept-Language", "en-US,en;q=0.5");
request.addHeader("Authorization", "Basic " + new String(auth));
request.setEntity(entity);
HttpResponse response = httpClient.execute(request);
System.out.println(response.getStatusLine());
System.out.println(request);
}
catch(Exception e)
{
}
First of all, your form parameters are not encoded correctly. You are using colon (:) to separate keys from their values, but instead, the equal sign (=) must be used:
Wrong: "importFormatCode:1&data:" + params
Correct: "importFormatCode=1&data=" + params
(See also W3C.org - Forms in HTML Documents - application/x-www-form-urlencoded)
Apart from that, you must not URL-encode the entire string but only the keys and the values. Otherwise you'll also encode the separator characters = and &!
The easiest way is to use the existing utility class org.apache.http.client.utils.URLEncodedUtils (assuming that you're using Apache HTTP Components):
String xmlData = // your xml data from somewhere
List<NameValuePair> params = Arrays.asList(
new BasicNameValuePair("importFormatCode", "1"),
new BasicNameValuePair("data", xmlData)
);
String body = URLEncodedUtils.format(params, encoding); // use encoding of request
StringEntity entity = new StringEntity(body);
// rest of your code
I'm trying to send the equivalent of the curl '-F' option to a designated URL.
This is what the command looks like using Curl:
curl -F"optionName=cool" -F"file=#myFile" http://myurl.com
I believe I am correct in using the HttpPost class in the Apache httpcomponents library.
I supply a name=value type of parameter. The optionName is simply a string and the 'file' is a file I have stored locally on my drive (hence the #myFile to indicate its a local file).
If I print the response I get an HTTP 500 error... I am not sure what is causing the issue here because the server responds as it should when using the Curl command mentioned above. Is there some simple mistake I am making when looking at the code below?
HttpPost post = new HttpPost(postUrl);
HttpClient httpClient = HttpClientBuilder.create().build();
List<BasicNameValuePair> nvps = new ArrayList<BasicNameValuePair>();
nvps.add(new BasicNameValuePair(optionName, "cool"));
nvps.add(new BasicNameValuePair(file, "#myfile"));
try {
post.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
HttpResponse response = httpClient.execute(post);
// do something with response
} catch (Exception e) {
e.printStackTrace();
}
Try to use a MultipartEntity instead of an UrlEncodedFormentity, to handle both parameters and file upload:
MultipartEntity entity = new MultipartEntity();
entity.addPart("optionName", "cool");
entity.addPart("file", new FileBody("/path/to/your/file"));
....
post.setEntity(entity);
Edit
MultipartEntity is deprecated and FileBody constructor takes a File, not a String, so:
MultipartEntityBuilder entity = MultipartEntityBuilder.create();
entity.addTextBody("optionName", "cool");
entity.addPart("file", new FileBody(new File("/path/to/your/file")));
....
post.setEntity(entity.build());
Thanks #CODEBLACK .