Send HTTP PUT request to Cloudant - java

I am trying to send HTTP PUT request to Cloudant database to update a key "BPInc" to "N". Its current value is "Y". I am using HTTPURLConnection to make the connection and send request. I am able to send GET request successfully and retrieve the BPInc value. But when I am sending the PUT request, I am getting error code - 400.
I have also looked into cloudant-client library, but not able to get how to send PUT request and I want to stick to HTTPURLConnection method only.
Here's the code ,
// After retrieving _rev and _id using GET request......
String revID = "_rev of the document";
String docID = "_id of the document";
URL postUrl = new URL("<Cloudant URL>/<DB NAME>/" + docID);
String usernameColonPassword = "<API KEY>:<PASSWORD>";
String basicAuthPayload = "Basic " + Base64.getEncoder().encodeToString(usernameColonPassword.getBytes());
HttpURLConnection conn = (HttpURLConnection)postUrl.openConnection();
conn.setRequestMethod("PUT");
conn.setRequestProperty("Content-Type", "application/json; utf-8");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Authorization", basicAuthPayload);
conn.setDoOutput(true);
OutputStreamWriter json = new OutputStreamWriter(conn.getOutputStream());
json.write(String.format("{\"_rev\":revID, \"BPInc\":\"Y\"}"));
json.flush();
json.close();
int putResponseCode = conn.getResponseCode();
I am very new to this so I suppose I might be doing wrong something. Please suggest.

Related

How do i fetch the custom headers in java which is set in node js or sent by nodejs

Frontend pass the request to nodejs application and nodejs pass the request call to JAVA.
I am using following code to authenticate my REST apis and make connection to the specified url.
I want to add or print the custom headers passed in request.
public HttpURLConnection establishConnection(String baseurl, String methodtype, String userId,
HttpHeaders headers) {
URL url;
JSONObject userInfo=new JSONObject();
try {
url = new URL(baseurl);
output = "";
userInfo=getUserName(headers.getHeaderString(HttpHeaders.AUTHORIZATION));
String userpass=null;
if (userId.isEmpty())
userpass = userInfo.getString("username") + ":" + userInfo.getString("password");
else
userpass = userId + ":" + userInfo.getString("password");
String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization",basicAuth);
conn.setRequestMethod(methodtype);
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Content-Type", "application/json");
conn.setConnectTimeout(60000); // 60 seconds
conn.setDoOutput(true);
return conn;
}
}
How do i fetch the custom headers passed in request ? Which method should i use ? or Class that i can use to fetch the custom headers.
using #HeaderParam("customparamname") String param , with this param #HeaderParam i m able to get custom parameter value.

Adding value to path parameter in Java REST?

NOTICE UPDATE!!
The problem got solved and i added my own answer in the thread
In short, I have attempted to add the parameter "scan_id" value but since it is a POST i can't add the value directly in the url path.
using the code i already have, how would i go about modifying or adding so that the url is correct, that is, so that it accepts my POST?.
somehow i have been unable to find any examples that have helped me in figuring out how i would go about doing this..
I know how to do a POST with a payload, a GET with params. but a post with Params is very confusing to me.
Appreciate any help. (i'd like to continue using HttpUrlConnection unless an other example is provided that also tells me how to send the request and not only configuring the path.
I've tried adding it to the payload.
I've tried UriBuilder but found it confusing and in contrast with the rest of my code, so wanted to ask for help with HttpUrlConnection.
URL url = new URL("http://localhost/scans/{scan_id}/launch");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("tmp_value_dont_mind_this", "432432");
con.setRequestProperty("X-Cookie", "token=" + "43432");
con.setRequestProperty("X-ApiKeys", "accessKey="+"43234;" + " secretKey="+"43234;");
con.setDoInput(true);
con.setDoOutput(true); //NOT NEEDED FOR GETS
con.setRequestMethod("POST");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
//First example of writing (works when writing a payload)
OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
writer.write(payload);
writer.close();
//second attemp at writing, doens't work (wanted to replace {scan_id} in the url)
DataOutputStream writer = new DataOutputStream(con.getOutputStream());
writer.writeChars("scan_id=42324"); //tried writing directly
//writer.write(payload);
writer.close();
Exception:
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 400 for URL: http://localhost/scans/launch
I'd like one of the three response codes because then i know the Url is correct:
200 Returned if the scan was successfully launched.
403 Returned if the scan is disabled.
404 Returned if the scan does not exist.
I've tried several urls
localhost/scans/launch,
localhost/scans//launch,
localhost/scans/?/launch,
localhost/scans/{scan_id}/launch,
So with the help of a friend and everyone here i solved my problem.
The below code is all the code in an entire class explained bit by bit. at the bottom you have the full class with all its syntax etc, that takes parameters and returns a string.
in a HTTP request there are certain sections.
Such sections include in my case, Request headers, parameters in the Url and a Payload.
depending on the API certain variables required by the API need to go into their respective category.
My ORIGINAL URL looked like this: "http://host:port/scans/{scan_id}/export?{history_id}"
I CHANGED to: "https://host:port/scans/" + scan_Id + "/export?history_id=" + ID;
and the API i am calling required an argument in the payload called "format" with a value.
String payload = "{\"format\" : \"csv\"}";
So with my new URL i opened a connection and set the request headers i needed to set.
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
The setDoOutput should be commented out when making a GET request.
con.setDoInput(true);
con.setDoOutput(true);
con.setRequestMethod("POST");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
con.setRequestProperty("X-Cookie", "token=" + token);
con.setRequestProperty("X-ApiKeys", "accessKey="+"23243;" +"secretKey="+"45543;");
Here i write to the payload.
//WRITING THE PAYLOAD to the http call
OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
writer.write(payload);
writer.close();
After i've written the payload i read whatever response i get back (this depends on the call, when i do a file download (GET Request) i don't have a response to read as i've already read the response through another piece of code).
I hope this helps anyone who might encounter this thread.
public String requestScan(int scan_Id, String token, String ID) throws MalformedInputException, ProtocolException, IOException {
try {
String endpoint = "https://host:port/scans/" + scan_Id + "/export?history_id=" ID;
URL url = new URL(endpoint);
String payload= "{\"format\" : \"csv\"}";
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setDoInput(true);
con.setDoOutput(true);
con.setRequestMethod("POST");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
con.setRequestProperty("X-Cookie", "token=" + token);
con.setRequestProperty("X-ApiKeys", "accessKey="+"324324;" +
"secretKey="+"43242;");
//WRITING THE PAYLOAD to the http call
OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
writer.write(payload);
writer.close();
//READING RESPONSE
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuffer jsonString = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
jsonString.append(line);
}
br.close();
con.disconnect();
return jsonString.toString();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
As discussed here the solution would be to change the content type to application/x-www-form-urlencoded, but since you are already using application/json; charset=UTF-8 (which I am assuming is a requirement of your project) you have no choise to redesign the whole thing. I suggest you one of the following:
Add another GET service;
Add another POST service with content type application/x-www-form-urlencoded;
Replace this service with one of the above.
Do not specify the content type at all so the client will accept anything. (Don't know if possible in java)
If there are another solutions I'm not aware of, I don't know how much they would be compliant to HTTP protocol.
(More info)
Hope I helped!
Why you are not using like this. Since you need to do a POST with HttpURLConnection, you need to write the parameters to the connection after you have opened the connection.
String urlParameters = "scan_id=42324";
byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8);
DataOutputStream dataOutputStream = new DataOutputStream(conn.getOutputStream());
dataOutputStream.write(postData);
Or if you have launch in the end, just change the above code to the following,
String urlParameters = "42324/launch";
byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8);
DataOutputStream dataOutputStream = new DataOutputStream(conn.getOutputStream());
dataOutputStream.write(postData);
URL url = new URL("http://localhost/scans/{scan_id}/launch");
That line looks odd to me; it seems you are trying to use a URL where you are intending the behavior of a URI Template.
The exact syntax will depend on which template implementation you choose; an implementation using the Spring libraries might look like:
import org.springframework.web.util.UriTemplate;
import java.net.url;
// Warning - UNTESTED code ahead
UriTemplate template = new UriTemplate("http://localhost/scans/{scan_id}/launch");
Map<String,String> uriVariables = Collections.singletonMap("scan_id", "42324");
URI uri = template.expand(uriVariables);
URL url = uri.toURL();

How to make REST API call using a token?

I am newbie developer in Java. STEP 1 I have already done the the following:
Logged in to REST API server (with login&password)
Received a token in XML format which i parsed with SAX parser so now i
am in a position of a token. Below is the sample code for Login:
Java code:
String url1 = "https://api4.liverail.com/login";
URL obj = new URL(url1);
HttpsURLConnection con1 = (HttpsURLConnection) obj.openConnection();
String urlParameters ="username=paania#gmail.com&password=d372a15b714bd250e";
con1.setDoOutput(true);
con1.setRequestMethod("POST");
DataOutputStream wr = new DataOutputStream(con1.getOutputStream());
wr.writeBytes(urlParameters);
STEP 2: I want to pass the token to REST API to obtain some information e.g a list from category but when i send the request via GET method , i get a response in XML saying [CDATA[You need to be logged in]] This is the code in Java:
String url = "http://api4.liverail.com/advertising/category/list/?token="72938howdwoi";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
BufferedReader in = new BufferedReader(newInputStreamReader(con.getInputStream()));
in.close();
con.disconnect();
I am not sure what i am missing here.
Any suggestions?
Just changed your url for request of data :
String url = "http://api4.liverail.com/advertising/category/list/?token=72938howdwoi";

post data to server using Java, like jQuery's $.post()

I have a web backend, which works with the following jQuery post:
$.post(path + "login",
{"params": {"mode":"self", "username": "aaa", "password": "bbb"}},
function(data){
console.log(data);
}, "json");
How can I implement the same POST from Java, with HttpURLConnection? I'm trying with
URL url = new URL(serverUrl + loginUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Content-Length",
Integer.toString(postData.getBytes().length));
connection.setRequestProperty("Content-Language", "en-US");
connection.setUseCaches (false);
connection.setDoInput(true);
connection.setDoOutput(true);
DataOutputStream wr =
new DataOutputStream(connection.getOutputStream ());
wr.writeBytes(postData);
wr.flush ();
wr.close ();
BufferedReader br =
new BufferedReader(
new InputStreamReader(connection.getInputStream()));
, where postData = "{\"mode\": \"...\", ..... }"
but it doesn't work the same way.
The code on the server is written id Django, and tries to get the data in this way:
mode=request.POST.get("params[mode]")
You seem to be thinking all the time that jQuery sends JSON in its raw form to the server and that the HTTP server flawlessly understands it. This is not true. The default format for HTTP request parameters is application/x-www-form-urlencoded, exactly like as HTML forms in HTTP websites are using and exactly like as how GET query strings in URLs look like: name1=value1&name2=value2.
In other words, jQuery doesn't send JSON unmodified to the server. jQuery just transparently converts them to true request parameters. Pressing F12 in a sane browser and inspecting the HTTP traffic monitor should also have shown you that. The "json" argument which you specified there in end of $.post just tells jQuery which data format the server returns (and thus not which data format it consumes).
So, just do exactly the same as jQuery is doing under the covers:
String charset = "UTF-8";
String mode = "self";
String username = "username";
String password = "bbb";
String query = String.format("%s=%s&%s=%s&%s=%s",
URLEncoder.encode("param[mode]", charset), URLEncoder.encode(mode, charset),
URLEncoder.encode("param[username]", charset), URLEncoder.encode(username, charset),
URLEncoder.encode("param[password]", charset), URLEncoder.encode(password, charset));
// ... Now create URLConnection.
connection.setDoOutput(true); // Already implicitly sets method to POST.
connection.setRequestProperty("Accept-Charset", charset);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset);
try (OutputStream output = connection.getOutputStream()) {
output.write(query.getBytes(charset));
}
// ... Now read InputStream.
Note: do NOT use Data(Input|Output)Stream! Those are for creating/reading .dat files.
See also:
Using java.net.URLConnection to fire and handle HTTP requests
You should use efficient libraries to build (valid) json objects. Here is an example from the PrimeFaces library:
private JSONObject createObject() throws JSONException {
JSONObject object = new JSONObject();
object.append("mode", "...");
return object;
}
If you wish to have a nice and clean code to send and retrieve objects, take a look at the answer from Emil Adz ( Sending Complex JSON Object ).

Send cookies over HTTPURLConnection

I am trying use the HTTPURLConnection class to open connection to a JSP and receive a response from a servlet. A response header is set in the JSP that need to be read in the servlet.
The code sample is as below
String strURL = "http://<host>:<port>/<context>/mypage.jsp";
String sCookies = getCookie();//method to get the authentication cookie(**SSOAUTH**) and its value for the current logged in user
URL url = new URL(strURL);
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestProperty("Cookie", URLEncoder.encode(sCookies, "UTF-8"));
urlConnection.setRequestMethod("POST");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
DataOutputStream out = new DataOutputStream(urlConnection.getOutputStream());
out.writeBytes("lang=en");
out.flush();
out.close();
//reading the response received from JSP and retrieve header value
response.write(urlConnection.getHeaderField("commAuth") + "<br />");
The issue is the passed SSOAUTH cookie is not sent to the JSP. If I send the UID/PWD instead of cookie as below the authentication succeeds and response is sent correctly.
urlConnection.setRequestProperty("username", "testuser");
urlConnection.setRequestProperty("password", "testpwd");
Is this the right way of sending cookie over HTTPURLConnection? or are there other parameters that need to be set?
You may want to try removing the URLEncoder.encode from the entire sCookies String. The cookie format should be in the form of NAME=VALUE, but by URLEncoding the whole string you will escape the =.

Categories

Resources