Using HttpURLConnection to submit a json POST request - java

I am trying to submit a json post request using HttpURLConnection in Scala. I followed along to two tutorials and produced this:
def sendPost(url: String, jsonHash: String) {
val conn: HttpURLConnection = new URL(url).openConnection().asInstanceOf[HttpURLConnection]
conn.setRequestMethod("POST")
conn.setRequestProperty("Content-Type", "application/json")
conn.setRequestProperty("Accept", "application/json")
conn.setDoOutput(true)
conn.connect()
val wr = new DataOutputStream(conn.getOutputStream)
wr.writeBytes(jsonHash)
wr.flush()
wr.close()
val responseCode = conn.getResponseCode
println("Sent: " + jsonHash + " to " + url + " received " + responseCode)
val in = new BufferedReader(new InputStreamReader(conn.getInputStream))
var response: String = ""
while(response != null) {
response = in.readLine()
println(response)
}
in.close()
}
It responds with:
Sent: '{"schedule":"R/2014-02-02T00:00:00Z/PT24H", "name":"Scala-Post-Test", "command":"which scalac", "epsilon":"PT15M", "owner":"myemail#thecompany.com", "async":false}' to http://localhost:4040/scheduler/iso8601 received 500
java.io.IOException: Server returned HTTP response code: 500 for URL: http://localhost:4040/scheduler/iso8601
stemming from
val in = new BufferedReader(new InputStreamReader(conn.getInputStream))
but if I rebuild it as a curl request, it works fine:
curl -X POST -H 'Content-Type: application/json' -d '{"schedule":"R/2014-02-02T00:00:00Z/PT24H", "name":"Scala-Post-Test", "command":"which scalac", "epsilon":"PT15M", "owner":"myemail#thecompany.com", "async":false}' http://localhost:4040/scheduler/iso8601
requirement failed: Vertex already exists in graph Scala-Post-Test
(which is what I expect)
Any insight to what is wrong? I'm trying to sniff the packets now to determine what is different.
(Note: I had previously given up on sys.process._)

The issue is here:
Sent: '{"schedule":"R/2014-02-02T00:00:00Z/PT24H", "name":"Scala-Post-Test", "command":"which scalac", "epsilon":"PT15M", "owner":"myemail#thecompany.com", "async":false}' to http://localhost:4040/scheduler/iso8601 received 500
You'll note your JSON is surrounded by single quotes. This makes it invalid.
Also worth noting is that while this code works, you are using a DataOutputStream.writeBytes() to output your data. This would be problematic if your string including anything but single-byte characters; it strips the high 8 bits off each char (Java uses 2-byte chars to hold UTF-16 codepoints).
It's better to use something more suited for String output. The same technique you use for input, for example:
BufferedWriter out =
new BufferedWriter(new OutputStreamWriter(conn.getOutputStream));
out.write(jsonString);
out.close();

Related

How to transform a curl command to HTTP POST request using java

I would like to run this specific curl command with a HTTP POST request in java
curl --location --request POST "http://106.51.58.118:5000/compare_faces?face_det=1" \
--header "user_id: myid" \
--header "user_key: thekey" \
--form "img_1=https://cdn.dnaindia.com/sites/default/files/styles/full/public/2018/03/08/658858-577200-katrina-kaif-052217.jpg" \
--form "img_2=https://cdn.somethinghaute.com/wp-content/uploads/2018/07/katrina-kaif.jpg"
I only know how to make simple POST requests by passing a JSON object, But i've never tried to POST based on the above curl command.
Here is a POST example that I've made based on this curl command:
curl -X POST TheUrl/sendEmail
-H 'Accept: application/json' -H 'Content-Type: application/json'
-d '{"emailFrom": "smth#domain.com", "emailTo":
["smth#gmail.com"], "emailSubject": "Test email", "emailBody":
"708568", "generateQRcode": true}' -k
Here is how i did it using java
public void sendEmail(String url) {
try {
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
//add reuqest header
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json; utf-8");
con.setRequestProperty("Accept", "application/json");
con.setDoOutput(true);
// Send post request
JSONObject test = new JSONObject();
test.put("emailFrom", emailFrom);
test.put("emailTo", emailTo);
test.put("emailSubject", emailSubject);
test.put("emailBody", emailBody);
test.put("generateQRcode", generateQRcode);
String jsonInputString = test.toString();
System.out.println(jsonInputString);
System.out.println("Email Response:" + returnResponse(con, jsonInputString));
} catch (Exception e) {
System.out.println(e);
}
System.out.println("Mail sent");
}
public String returnResponse(HttpURLConnection con, String jsonInputString) {
try (OutputStream os = con.getOutputStream()) {
byte[] input = jsonInputString.getBytes("utf-8");
os.write(input, 0, input.length);
} catch (Exception e) {
System.out.println(e);
}
try (BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"))) {
StringBuilder response = new StringBuilder();
String responseLine = null;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
return response.toString();
} catch (Exception e) {
System.out.println("Couldnt read response from URL");
System.out.println(e);
return null;
}
}
I've found this useful link but i can't really understand how to use it in my example.
Is it any different from my example? and if yes how can i POST the following data?
Note: Required Data
HEADERS:
user_id myid
user_key mykey
PARAMS:
face_det 1
boxes 120,150,200,250 (this is optional)
BODY:
img_1
multipart/base64 encoded image or remote url of image
img_2
multipart/base64 encoded image or remote url of image
Here is the complete documentation of the API
There are three things that your HttpURLConnection needs:
The request method. You can set this with setRequestMethod.
The headers. You can set them with setRequestProperty.
The content type. The HTML specification requires that an HTTP request containing a form submission have application/x-www-form-urlencoded (or multipart/form-data) as its body’s content type. This is done by setting the Content-Type header using the setRequestProperty method, just like the other headers.
It’s not clear what you’re trying to do here. As Boris Verkhovskiy points out, curl’s --form option includes data as a part of a multipart request. In your command, the content of that request would be the characters of the URLs themselves. If you really want to submit URLs, not the images at those locations, you could use an application/x-www-form-urlencoded request body to do it. The body itself needs to URL-encoded, as the content type indicates. The URLEncoder class exists for this purpose.
The steps look like this:
String img1 = "https://cdn.dnaindia.com/sites/default/files/styles/full/public/2018/03/08/658858-577200-katrina-kaif-052217.jpg";
String img2 = "https://cdn.somethinghaute.com/wp-content/uploads/2018/07/katrina-kaif.jpg";
con.setRequestMethod("POST");
con.setDoOutput(true);
con.setRequestProperty("user_id", myid);
con.setRequestProperty("user_key", thekey);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
String body =
"img_1=" + URLEncoder.encode(img1, "UTF-8") + "&" +
"img_2=" + URLEncoder.encode(img2, "UTF-8");
try (OutputStream os = con.getOutputStream()) {
byte[] input = body.getBytes(StandardCharsets.UTF_8);
os.write(input);
}
However, if you want to submit the actual images, you will need to create a MIME request body. Java SE cannot do this, but the MimeMultipart class of JavaMail, which is part of the Java EE specification, can.
Multipart multipart = new MimeMultipart("form-data");
BodyPart part;
part = new MimeBodyPart();
part.setDataHandler(new DataHandler(new URL(img1)));
multipart.addBodyPart(part);
part = new MimeBodyPart();
part.setDataHandler(new DataHandler(new URL(img2)));
multipart.addBodyPart(part);
con.setRequestMethod("POST");
con.setDoOutput(true);
con.setRequestProperty("user_id", myid);
con.setRequestProperty("user_key", thekey);
con.setRequestProperty("Content-Type", multipart.getContentType());
try (OutputStream os = con.getOutputStream()) {
multipart.writeTo(os);
}
You should remove all catch blocks from your code, and amend your method signatures to include throws IOException (or throws IOException, MessagingException). You don’t want users of your application to think the operation was successful if in fact it failed, right?

cURL DELETE on java

I use command "curl -X DELETE --header 'Accept: application/json' 'http://10.10.1.29:8181/onos/v1/flows/application/olsrflow' -u karaf:karaf"
It Can work.
but use JAVA Code does't work.
have any problem in my JAVA code?
URL dc0ContrailUrl2 = new URL("http://10.10.1.29:8181/onos/v1/flows/application/olsrflow");
HttpURLConnection dcConn2 = (HttpURLConnection) dc0ContrailUrl2.openConnection();
dcConn2.setDoOutput(true);
String login = "karaf:karaf";
String content = URLEncoder.encode (login) ;
String basicAuth = "Basic " + new String(new Base64().encode(login.getBytes()));
dcConn2.setRequestProperty("Authorization",basicAuth);
dcConn2.setRequestProperty("Content-Type", "application/json");
dcConn2.setRequestMethod("DELETE");
BufferedReader in2 = new BufferedReader(new InputStreamReader(dcConn2.getInputStream()));
String inputLine2;
while ((inputLine2 = in2.readLine()) != null){ //while response is not null, assign response to inputLine and print inputLine
System.out.println(inputLine2);
}
in2.close();
error HTTP response code: 415
You did not add Accept type the same as curl. Add the following line and remove the Content-Type:
dcConn2.setRequestProperty("Accept", "application/json");
Typically it means that server does not support MediaType has been passed. You have to figure out what does it expect and setup it in your request accordingly.

elastic search not x content exception

I have been trying to put data in elastic search through java using the following code:
String url = "http://localhost:9200/testindex2/test/2";
HttpClient client = new DefaultHttpClient();
HttpPut put = new HttpPut(url);
JSONObject json = new JSONObject();
json.put("email", "abc#abof.com");
json.put("first_name", "abc");
StringEntity se = new StringEntity("JSON: " + json.toString());
se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,"Text"));
put.setEntity(se);
HttpResponse response = client.execute(put);
System.out.println("\nSending 'PUT' request to URL : " + url);
System.out.println("Put parameters : " + put.getEntity());
System.out.println("Response Code : " + response.getStatusLine().getStatusCode());
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null) {
result.append(line);
}
System.out.println(result.toString());
And I am getting the following error:
Sending 'PUT' request to URL : http://localhost:9200/testindex2/test/2
Put parameters : [Content-Type: text/plain; charset=ISO-8859-1,Content- Encoding: Text,Content-Length:
52,Chunked: false]
Response Code : 400
{"error":{"root_cause":[{"type":"mapper_parsing_exception","reason":"failed
to parse"}],"type":"mapper_parsing_exception","reason":"failed to
parse","caused_by":{"type":"not_x_content_exception","reason":"Compressor
detection can only be called on some xcontent bytes or compressed
xcontent bytes"}},"status":400}
Also when I try the same code from a rest client it runs just fine, not sure why this problem is happening.
Replaced
StringEntity se = new StringEntity("JSON: " + json.toString());
se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,"Text"));
with this:
StringEntity se = new StringEntity(json.toString(),ContentType.APPLICATION_JSON);
and its working now
Elastic search has special client to work with Java. And you don't need to generate JSON manually. Moreover you didn't describe import section, so a bit hard to understand what libraries you use.
I was getting the same error, but in my case, I was actually doing something like this in a Kubernetes configuration for an init container:
- args:
- -XPUT
- -k
- {{.Values.kibana.env.ELASTICSEARCH_URL}}/.logtrail/config/1?pretty
- -H
- 'Content-Type: application/json'
- --data
- /etc/logtrail/logtrail.json
The problem here is that when you specify a file in a curl POST/PUT, it needs to be appended by '#'. So the below configuration worked!
- args:
- -XPUT
- -k
- {{.Values.kibana.env.ELASTICSEARCH_URL}}/.logtrail/config/1?pretty
- -H
- 'Content-Type: application/json'
- --data
- '#/etc/logtrail/logtrail.json'
uri = 'http://projects.local:9200/'
_index = 'mydata/'
_type = '_doc/'
head = {'Content-Type': 'application/json'}
body = {
"capital" : "boston",
"state" : "massachusetts"
}
Using json.dumps to convert body to jbody worked for me
jbody = json.dumps(body)
response = requests.post(uri+_index+_type, headers=head, data=jbody)

Google Safe Browsing HTTP POST - 403 response

I'm working on a program that queries Google Safe Browsing for certain urls, but I'm getting an error that I don't think I should be getting.
I'm sending the following request:
2
http://google.com
http://facebook.com
via POST to: https://sb-ssl.google.com/safebrowsing/api/lookup?client=api&apikey=[KEY]&appver=1.5.2&pver=3.1
However, I'm getting a 403 response.
This is what the documentation says for HTTP POST lookup errors:
The server generates the following HTTP error codes for the POST request:
•200: AT LEAST ONE of the queried URLs are matched in either the phishing, malware, or unwanted software lists. The actual results are returned through the response body.
•204: NONE of the queried URLs matched the phishing, malware, or unwanted software lists, and no response body is returned.
•400: Bad Request—The HTTP request was not correctly formed.
•401: Not Authorized—The API key is not authorized.
•503: Service Unavailable—The server cannot handle the request. Besides the normal server failures, this could also indicate that the client has been “throttled” for sending too many requests.
The response code 403 isn't listed, yet I'm getting it.
I have triple-checked my API-key and made sure the API is enabled for my project. I'm using a Server-key, but I also tried a Browser-key.
I tried doing a GET request also, and that did work, but I cannot get POST to work. What's going on?
Here is my code:
try {
String baseURL="https://sb-ssl.google.com/safebrowsing/api/lookup";
String arguments = "";
arguments +=URLEncoder.encode("client", "UTF-8") + "=" + URLEncoder.encode("api", "UTF-8") + "&";
arguments +=URLEncoder.encode("apikey", "UTF-8") + "=" + URLEncoder.encode("[KEY]", "UTF-8") + "&";
arguments +=URLEncoder.encode("appver", "UTF-8") + "=" + URLEncoder.encode("1.5.2", "UTF-8") + "&";
arguments +=URLEncoder.encode("pver", "UTF-8") + "=" + URLEncoder.encode("3.1", "UTF-8");
// Construct the url object representing cgi script
URL url = new URL(baseURL + "?" + arguments);
// Get a URLConnection object, to write to POST method
HttpURLConnection connect = (HttpURLConnection) url.openConnection();
connect.setRequestMethod("POST");
// Specify connection settings
connect.setDoInput(true);
connect.setDoOutput(true);
// Get an output stream for writing
OutputStream output = connect.getOutputStream();
PrintStream pout = new PrintStream (output);
pout.print("2");
pout.println();
pout.print("http://www.google.com");
pout.println();
pout.print("http://www.facebook.com");
pout.close();
BufferedReader in = new BufferedReader(new InputStreamReader(connect.getInputStream()));
String decodedString;
while ((decodedString = in.readLine()) != null) {
System.out.println("w: " + decodedString);
}
in.close();
} catch(Exception e) {
e.printStackTrace();
}
I found the error. The CGI parameter was incorrect. It should have been key and not apikey. Still weird that you get an undocumented response-code though.

Attempt to get OAuth access token from Neteller produces error: "Server returned HTTP response code: 401 for URL"

I want to set a successful request to Neteller, I am trying to get an access token using the code from the Neteller documentation. However, it consistently fails with with the following exception:
java.io.IOException: Server returned HTTP response code: 401 for URL: https://test.api.neteller.com/v1/oauth2/token?grant_type=client_credentials
Here's the code (again, from the Neteller documentation):
String testUrl = " https://test.api.neteller.com";
String secureUrl = "https://api.neteller.com";
String url = testUrl;
if("live".equals(configBean.get("environment"))){
url = secureUrl;
}
url += "/v1/oauth2/token?grant_type=client_credentials";
String xml = "grant_type=client_credentials?grant_type=client_credentials";
xml = "";
String test = Base64.encodeBytes((accountID + ":" + secureID).getBytes());
try {
URL urls = new URL ("https://test.api.neteller.com/v1/oauth2/token?grant_type=client_credentials");
HttpURLConnection connection = (HttpURLConnection) urls.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty ("Authorization", "Bearer " + test);
connection.setRequestProperty ("Content-Type", "application/json");
connection.setRequestProperty ("Cache-Control", "no-cache");
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.flush();
wr.close();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
String accessToken = "";
} catch(Exception e) {
e.printStackTrace();
}
Why is my implementation failing here?
There is nothing wrong with your code. The problem is that you are trying use a regular member account for the API integration, where you need to be using a merchant account for that. Below are the steps you will need to complete in order to get it to work:
You need to get a test merchant account (http://www.neteller.com/business/contact-sales/). Registering on www.neteller.com creates a regular member account, which cannot receive payments via the API.
Once you have a test merchant account, you will need to white-list the IP address from which you will be making requests to the API. (pg. 31 of the manual).
Then, you will need to add an application to it (pg. 32 of the manual).
Once you have added the application, use the "client ID" and "client secret" in the Authorization header - just like you do now, base64 encoded values, separated with colon (:).

Categories

Resources