curl and Java program are treated differently by CouchDB - java

This question might be a little bit naive...
I have written a small Java program that should query a CouchDB instance. However, CouchDB constantly returns that my user is not authorized. Using the same URL with curl works.
The Java Code:
HttpGet request = new HttpGet("http://admin:PASSWORD#localhost:5984/ecm_ng_nonpart/_security");
request.addHeader("accept", "application/xml");
try {
System.out.println("Executing request " + request.getMethod() + " " + request.getUri());
ClassicHttpResponse resp = httpClient.execute(request);
BufferedReader br = new BufferedReader(new InputStreamReader(resp.getEntity().getContent()));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
The response:
{"error":"unauthorized","reason":"You are not authorized to access this db."}
The curl output:
C:\Users\joche>curl -X GET http://admin:PASSWORD#localhost:5984/ecm_ng_nonpart/_security
{"members":{"roles":["_admin"],"names":["ecmnp","admin"]},"admins":{"roles":["_admin"],"names":["admin"]}}
Any idea what I am doing wrong?

Using the same URL with curl works.
Your posted information does not support this claim. Your URLs are different in the two cases.
Java: _sessions
HttpGet request = new HttpGet("http://admin:PASSWORD#localhost:5984/ecm_ng_nonpart/_sessions");
Curl: _security.
curl -X GET http://admin:PASSWORD#localhost:5984/ecm_ng_nonpart/_security

Related

How to attach document (image or etc.) to existing work item Azure DevOps using Java or curl utility

How to attach document (image or etc.) to existing work item Azure DevOps using Java or curl utility. I tried to do it with curl utility and java code, and it doesn't work. The example of java code:
try {
// urlOfAttachment - url of attachment to devops azure, got with this method:
// https://stackoverflow.com/questions/62034062/upload-an-attachment-to-azure-devops-rest-api
String jsonInputString = "[{\"op\":\"add\",\"path\":\"/relations/-\",\"value\":" +
"{\"rel\":\"HelloFile.txt\",\"url\":\"" + urlOfAttachment + "\"," +
"\"attributes\":{\"comment\":\"Spec for the work\"}}}]";
URL url = new URL(
"https://dev.azure.com/[organization]/[project]/_apis/wit" +
"/workItems/2?api-version=5.1");
// PAT - token
HttpURLConnection con = apiConnectionAttachToTicket(PAT, url, jsonInputString);
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());
}
System.out.println("There would be response");
System.out.println(response.toString());
System.out.println("End of response");
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
con.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
}
public static HttpURLConnection apiConnectionAttachToTicket(String PAT, URL url, String jsonInputString) {
HttpURLConnection con = null;
try {
String AuthStr = ":" + PAT;
Base64 base64 = new Base64();
String encodedPAT = new String(base64.encode(AuthStr.getBytes()));
con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("Authorization", "Basic " + encodedPAT);
con.setRequestProperty("Content-Type", "application/json-patch+json");
con.setDoOutput(true);
System.out.println("URL - " + url.toString());
System.out.println("PAT - " + encodedPAT);
con.setDoInput(true);
con.setRequestProperty("X-HTTP-Method-Override", "PATCH");
con.setRequestMethod("POST");
con.setRequestProperty("data", jsonInputString);
System.out.println("Exit from function");
} catch (Exception e) {
System.out.println(e.getMessage());
}
return con;
}
This method returns 411 error. I think because it doesn't set method type as PATCH, but uses POST. But POST isn't supported by DevOps Azure (I got it when tried to use curl). When I use curl, it returns message: "You must pass a valid document in the body of the request". But I checked it several times, and it seems right. The example of curl request:
curl -L -D- --user [mail]#gmail.com:[token] --header "Content-Type:application/json-patch+json" --request POST -d '{"op":"add","path":"/relations/-","value":"AttachedFile","url":"https://dev.azure.com/[orgranization]/280b4f85-e666-4069-8b3b-2116ff5d9b7a/_apis/wit/attachments/ff9f26e7-6595-462d-833c-40f9771f3035?fileName=HelloFile.txt","attributes":{"comment":"Spec for the work"}}}' https://dev.azure.com/[organization]/[project]/_apis/wit/workitems/2?api-version=6.0
Maybe any ideas?
You could first try to use Postman to test your JSON format. Check if you could use REST API with that json body to upload attachments.
If a comment isn't specified, it doesn't link correctly. i.e. This code:
Should have been:
json=[
{
"op": "add",
"path": "/relations/-",
"value": {
"rel": "AttachedFile",
"url": attachment_url,
"attributes": {
"comment": ""
}
},
}
]
In my case I was getting the "You must pass a valid document in the body of the request" forever until I stumbled upon reqbin.com post
Once I adopted the format to escape all the " (eg \") inside the curl -d argument, things were happy. I have noticed others seem to have luck using single quotes to encompass all of the -d argument (and ignore the " inside), but I cannot get that to work. I have also seen """ used all over the place but to me \" is cleaner/more readable.

Microsoft Graph: Requesting an Extension returns http 400 bad request

I added an open extension to an event in a calendar and am trying to read it back.
Here is the url:
https://graph.microsoft.com/v1.0/users/{userid}/calendars/{calendarId}=/events?$expand=Extensions($filter=Id eq 'c.i.m.p.server.entities.outlook.Event')
I cannot get this to work in a Java program. The following combinations do work:
It works my Java program if I remove the $expand... parameter. I can also ask for certain fields, that works too.
The request works in Postman (I just have to set the token)
The request works in Graph Explorer when I log in as the owner of the calendar
Here is the extension (inside one of the events) when I use Postman to read the event. It is the last item in the event:
"extensions#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('{userid}')/calendars('{calendarId}')/events('{eventId})/extensions",
"extensions": [
{
"#odata.type": "#microsoft.graph.openTypeExtension",
"id": "Microsoft.OutlookServices.OpenTypeExtension.c.i.m.p.server.entities.outlook.Event",
"extensionName": "c.i.m.p.server.entities.outlook.Event",
"adherentId": "12346",
"timeSlotID": "346463"
}
]
Here is the Java code (Java 8, using java.io and java.net libraries):
private static void doSomething(String _accessToken) throws IOException {
String urlString = "https://graph.microsoft.com/v1.0/users/{userId}/calendars/{calendarId}/events?$expand=Extensions($filter=Id eq 'c.i.m.p.server.entities.outlook.Event')";
URL url = new URL(urlString);
Proxy webProxy
= new Proxy(Proxy.Type.HTTP, new InetSocketAddress({proxy-address}, {port}));
HttpURLConnection connection = (HttpURLConnection) url.openConnection(webProxy);
// Set the appropriate header fields in the request header.
connection.setRequestProperty("Authorization", "Bearer " + _accessToken);
connection.setRequestProperty("Accept", "application/json");
connection.setDoOutput(true);
connection.setReadTimeout(5000);
connection.setRequestMethod(HttpMethod.GET);
try {
connection.connect();
int responseCode = connection.getResponseCode();
System.out.println("execute(), response code = " + responseCode);
String responseMessage = connection.getResponseMessage();
System.out.println("execute(), response Message = " + responseMessage);
String responseString = null;
try {
InputStream ins = connection.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(ins));
StringBuffer sb=new StringBuffer();
String line;
while ((line=br.readLine()) != null) {
sb.append(line);
}
responseString = sb.toString();
} catch (Exception e) {
System.out.println("Could not get input stream from response, error is " + e.toString());
}
System.out.println("execute(), httpResult = " + responseString);
} catch (IOException e) {
System.out.println(".execute(), IOException : " + e.toString());
} finally {
connection.disconnect();
}
}
How do I fix this? Thanks!
400 means bad request. It could be because of url encoding. Url encode the query string.
Something like
String query = "Extensions($filter=Id eq 'c.i.m.p.server.entities.outlook.Event'";
String url = "https://graph.microsoft.com/v1.0/users/{userId}/calendars/{calendarId}/events?
$expand=" + URLEncoder.encode(query, StandardCharsets.UTF_8.name());
Alternatively you could use graph service java api based on your need which will help abstract all the interactions for you or you could use any of the rest clients available.
First of all, you should provide more info on the error - Stacktrace and error message. But 400 code indicates that was a user mistake, meaning that you are sending an invalid request. Since you say that postman request works then compare all the headers that are sent by postman and see if your code misses some hearer. As for the code, instead of coding your own Http client functionality I would suggest using 3d party Http client. Here are a few suggestions:
Apache Http client - very popular and well known 3d party Http Client
OK Http client - Open-source Http client. Here is tutorial
MgntUtils Http client - very simple 3d party HttpClient: Provided in MgntUtils Open source library (written by me). Very simple in use. Take a look at Javadoc. Library itself provided as Maven artifacts and on Git (including source code and Javadoc).

Image share with linkedin v2 api not posting on page feed

Ok so this is my problem.. To share an image post via linkedin api, you first have to register your image file, you do that via a post request in which you send your binary file. Then you use the the image URN in the original request to submit your post. My request goes through, returns 201 code (which should be a successful request) but ends up not posting the image or the text. If i try to post only text, it works. I've tried registering my image using curl, and it posted on linkedin, so i think i'm not sending the binary file in a request properly, this is my request:
HttpClient client = HttpClientBuilder.create().build();
HttpPut request = new HttpPut(uploadUrl);
request.addHeader("Content-Type", "data/binary");
request.setHeader("X-Restli-Protocol-Version", "2.0.0");
request.setHeader("Authorization", "Bearer " + myToken);
File file = new File(pictureUrl);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody("upload-file", file);
request.setEntity(builder.build());
HttpResponse response = client.execute(request);
I get code 201 with this code, but it still doesn't post.
This is the curl example of the request that they give on Share API doc.
curl -i --upload-file /Users/peter/Desktop/superneatimage.png --header "Authorization: Bearer redacted" 'https://api.linkedin.com/mediaUpload/C5522AQGTYER3k3ByHQ/feedshare-uploadedImage/0?ca=vector_feedshare&cn=uploads&m=AQJbrN86Zm265gAAAWemyz2pxPSgONtBiZdchrgG872QltnfYjnMdb2j3A&app=1953784&sync=0&v=beta&ut=2H-IhpbfXrRow1'
Can you tell me what is wrong with my java equivalent?
Edit: Forgot to say i even tried calling curl from java, the same code i used in the terminal, and it still didn't work..
Process p;
try {
p = Runtime.getRuntime().exec("curl -i --upload-file" + " " + pictureUrl + " " + "--header \"Authorization: Bearer " + myToken + "\" '" + uploadUrl + "'");
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
String outputController = "";
while ((line = reader.readLine()) != null) {
outputController = outputController + '\n' + line;
}
System.out.println("out: ");
System.out.println(outputController);
return true;
} catch (IOException | InterruptedException ex) {
return false;
}
Output returned an empty String.
Edit2: Another funny thing, when i execute the main request, in which i send the text, and media urns that i get after submitting images, i get 201 again, like it's successful, and in the response i even get the post id. Then i try to use the another api endpoint and pull that post using the id i got from the response, and i get all the data, like the post is posted. It even says in the json that i get that lifecycle is PUBLISHED and the status of the medias is READY. Only thing that's different from the json an image post that is on linkedin is that the media object have thumbnails, and in this case they don't, it's just an empty json array.
I found curl to C# converter https://curl.olsh.me/
below is code snippet is generated:
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("PUT"), "https://api.linkedin.com/mediaUpload/C5522AQGTYER3k3ByHQ/feedshare-uploadedImage/0?ca=vector_feedshare&cn=uploads&m=AQJbrN86Zm265gAAAWemyz2pxPSgONtBiZdchrgG872QltnfYjnMdb2j3A&app=1953784&sync=0&v=beta&ut=2H-IhpbfXrRow1"))
{
request.Headers.TryAddWithoutValidation("Authorization", "Bearer redacted");
request.Content = new ByteArrayContent(File.ReadAllBytes("/test.png"));
var response = await httpClient.SendAsync(request);
}
}
Ok I've solved it, if anyone encounters the same problem, this is what i did wrong. In the request i added a multipart to request body, this is wrong, you just go RAW. So instead of
File file = new File(pictureUrl);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody("upload-file", file);
request.setEntity(builder.build());
you just put
request.setEntity(new FileEntity(new File(pictureUrl), ContentType.create(picture.getContentType())));
and then everything goes on ok.
Not familiar with Java, but I had the same problem using Ruby and I fixed it by adding the MIME type of the image I was uploading as the Content-Type in the request headers. So in your specific case it would be:
request.addHeader("Content-Type", "image/png");
Also take a look at my solution using Ruby's RestClient and Minimagick: https://stackoverflow.com/a/54902863/7844946
I was writing with kotlin and after struggling with the same problem for a long time I managed to fix it, for those struggling with the similar problem, I'll leave my sample codes below. For the visual you need to provide a direct URI path, also pay attention to the header structure.
Here are the codes.
var file = File(ImageURI)
val urls = URL(url)
var connection: HttpsURLConnection = urls.openConnection() as HttpsURLConnection
connection.setRequestProperty("Authorization","Bearer " + accesToken)
connection.setRequestProperty("Content-Type", "image/png")
connection.setRequestProperty("cache-control", "no-cache")
connection.setRequestProperty("X-Restli-Protocol-Version", "2.0.0")
connection.requestMethod = "POST"
connection.doOutput = true
connection.doInput = true
var request = DataOutputStream(connection.outputStream)
request.write(file.readBytes())
request.flush()
println("Response: "+connection.responseCode)

Ameritrade API POST Request JSON Response

I haven't coded in JAVA for years, and am trying to put an algorithm together to automatically make trades based on certain conditions.
I'm hoping to use the Ameritrade API
I've tried sending a cURL message in command prompt and I do indeed get a response back from the server 'Invalid Key'. I'd like to see the 'Invalid Key' response come back in Java as this will prove that I can send POST and receive JSON objects back into Java. From there I will work at authenticating but one step at a time!
Here's the curl message sent in command prompt that works, try it yourself by copying and pasting::
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=authorization_code&refresh_token=&access_type=offline&code=&client_id=&redirect_uri=" " https://api.tdameritrade.com/v1/oauth2/token
The first thing I'd like to do is be able to send this curl message in JAVA and receive the JSON response back in JAVA
This is what I have for code so far, but I get a 500 error, which makes me think its something with the way im sending the message to the server?
public void trytoAuthenticate() {
HttpURLConnection connection = null;
//
//this is the curl message in command prompt you can send to receive JSON response back
//curl -X POST --header "Content-Type: application/x-www-form-urlencoded" -d
//"grant_type=authorization_code&
//refresh_token=&
//access_type=offline&
//code=&
//client_id=&
//redirect_uri=" "https://api.tdameritrade.com/v1/oauth2/token"
try {
//Create connection
URL url = new URL("https://api.tdameritrade.com/v1/oauth2/token");
String urlParameters = "grant_type=" + URLEncoder.encode("authorization_code", "UTF-8") +
"&refresh_token=" + URLEncoder.encode("", "UTF-8") +
"&access_type=" + URLEncoder.encode("", "UTF-8") +
"&code=" + URLEncoder.encode("", "UTF-8") +
"&client_id=" + URLEncoder.encode("", "UTF-8") +
"&redirect_uri=" + URLEncoder.encode("", "UTF-8");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST"); //-X
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); //-H
connection.setRequestProperty("Content-Length",
Integer.toString(urlParameters.getBytes().length));
connection.setRequestProperty("Content-Language", "en-US");
connection.setUseCaches(false);
connection.setDoOutput(true);//connection will be output
connection.setDoInput(true);//connection will be input
//Send request
DataOutputStream wr = new DataOutputStream (connection.getOutputStream());
wr.writeBytes(urlParameters);
System.out.println(urlParameters); //added for testing
wr.close();
//Get Response
DataInputStream is = new DataInputStream (connection.getInputStream());
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
rd.readLine();
//StringBuffer response = new StringBuffer(); // or StringBuffer/StringBuilder if Java version 5+
//String line;
//while ((line = rd.readLine()) != null) {
// response.append(line);
// response.append('\r');
//}
rd.close();
//System.out.println(response.toString());
//return response.toString();
} catch (Exception e) {
e.printStackTrace();
//return null;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}
A few things:
You need four parameters: grant_type, access_type, redirect_url and code.
You should URLDecode the authorization code you got from the browser login you probably just performed (as per their instructions)
Remove empty parameters, leave only what I mentioned above.
The redirect URL must match EXACTLY the redirect URL you added when you created your APP in the console.
If this is an app (looks like it), you probably have to set the access_type to "offline". Again see their documentation. Depends on your application.
grant_type should be "authorization_code", as that's what you want.

replicate wget command in java

i have this command:
wget -O prova.csv --header="prova-user: guest" --header="prova-passwd: guest"
"http://www.....................80&albedo=0.2&horizon=1"
i want to do a batch scheduled in Java but I can not connect. When I try to take the imputstream return me this error:
ERROR message -8: Unregistered IP address
This is my piece of code:
URL myURL = new URL(url);
HttpURLConnection myURLConnection = (HttpURLConnection)myURL.openConnection();
String userCredentials = "guest:guest";
String basicAuth = "Basic " + new String(new Base64().encode(userCredentials.getBytes()));
myURLConnection.setRequestProperty ("Authorization", basicAuth);
myURLConnection.setRequestMethod("POST");
myURLConnection.setRequestProperty("Content-Language", "en-US");
myURLConnection.setUseCaches(false);
myURLConnection.setDoInput(true);
myURLConnection.setDoOutput(true);
// Show page.
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(myURLConnection.getInputStream(), "UTF-8"));
for (String line; ((line = reader.readLine()) != null);) {
System.out.println(line);
}
} finally {
if (reader != null) try { reader.close(); } catch (IOException ignore) {}
}
is it possible? and how can I do it?
Thanks in advance
You had provided 2 completely different commands.
The first is a wget that send in HTTP headers a sort of authentication infos, and GET a result.
The second is a java program that perform an HTTP request in POST with basic authentication.
If the first command is working, than you should forget about the basic authentication and set the proper HTTP headers as you did in the wget command.
I don't know why you try a POST, if the wget looks as a normal GET request.
Just use a GET request in java too.
And it should work.
About the error, I suppose is the server that sent you such error message.
So it could be as you haven't correctly authenticated.
But it is a strange error, I'm expecting such kind of error if the server have a white list of IP addresses allowed to connect.
Are you running the wget and the java code on the same server?

Categories