I'm new to Java and I need to send a CURL command to BrowserStack, saying that my automated test has failed. I have the following CURL command that I must run:
curl -u "XXX:YYY" -X PUT -H "Content-Type: application/json" -d "{\"status\":\"failed\", \"reason\":\"\"}" https://api.browserstack.com/automate/sessions/ZZZ.json
P.S: XXX and YYY redacted due to work
The only thing is that I need is to replace ZZZ with a variable in this command, so let's say I have this so far:
void sendCurlCommand(){
String sessionId = "123ABC";
// code to send this curl command here
}
I tried several solutions here in StackOverflow, but all the ones I tried, they run and give no errors at all, but nothing happens on BrowserStack side, so I can't debug what's happening. If I run this exact command on my Linux terminal, it works like a charm.
I could finally fail my testing using CURL. I use the following dependency on Maven:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.6</version>
</dependency>
And I used the following code:
URI uri = new URI("https://XXX:YYY#api.browserstack.com/automate/sessions/"
+ sessionId + ".json");
HttpPut putRequest = new HttpPut(uri);
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add((new BasicNameValuePair("status", "failed")));
nameValuePairs.add((new BasicNameValuePair("reason", "")));
putRequest.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpClientBuilder.create().build().execute(putRequest);
Related
I am trying to execute a curl command and get a part of the response as a string.
The command that I am trying to execute is as follows
curl -X POST "https://kakaoapi.aligo.in/akv10/token/create/30/s/" \
--data-urlencode "apikey=xxxxx" \
--data-urlencode "userid=xxxxx"
The response that I get when I execute this in the terminal is as follows
{"code":0,"message":"\uc815\uc0c1\uc801\uc73c\ub85c \uc0dd\uc131\ud558\uc600\uc2b5\ub2c8\ub2e4.","token":"tokenvalue","urlencode":"urlencoded"}%
The java code that I am trying to execute to get this result is something like this
String command =
"curl -X POST \"https://kakaoapi.aligo.in/akv10/token/create/30/s/\" \\\n" +
"\t--data-urlencode \"apikey=xxxxx\" \\\n" +
"\t--data-urlencode \"userid=xxxxx\"";
Process pr = Runtime.getRuntime().exec(command);
String result = new BufferedReader(
new InputStreamReader(pr.getInputStream()))
.lines()
.collect(Collectors.joining("\n"));
log.info(result);
I am currently getting a null value in the log.
It would be greatly appreciated if anyone could tell me what I am doing wrong, or suggest a better way of doing this.
I have tried doing this by creating a httpclient and sending a post request, and I did get a response but the authentication failed for some reason.
Thank you in advance!
A better way of doing this is by using Unirest library (http://kong.github.io/unirest-java):
Unirest.setTimeouts(0, 0);
HttpResponse<String> response = Unirest.post("https://kakaoapi.aligo.in/akv10/token/create/30/s/?apikey=xxxxx&userid=xxxxx")
.asString();
The first step is to install it's maven / gradle dependency and then try the code above.
I'm trying to execute a POST request using curl in order to do some authorization. The expected result is a token which will be provided in the Location response header
Issue
If I execute the command from within my bash, it'll work just fine (= with redirections etc.)
If I execute the exact same command (really just copy&paste) in my Java application, I get a slightly different result ( = missing token in the Location response header)
Expected result
Token located in the Location response header, like Location: /https://localhost:4200/token=123
Actual result
Some kind of error, like Location: my.policy
Command
This is the basic structure of the command. Basically, it is a POST request with some redirection involved.
curl -L -v --header \"something:special\” --cookie \"a=1;b=2\" --data \"param1¶m2\" https://url
What I've tried
Enabled the verbose mode via -v
Enabled redirection via -L
Checked for handshake (or common) errors
Checked for typos and encoding issues
Executed command within the bash
Tried executing the command using a Java based approach
Even tried to execute the command creating a bash from within the code and passing the command
Java code
String command = "SOME CURL COMMAND USING POST"
// execute the command
Process process = Runtime.getRuntime().exec(command);
// Since we will get a 302 (as expected), the result will be in the error stream
Scanner scanner = new Scanner(process.getErrorStream());
// Do some formatting...
String tmp = "";
while (scanner.hasNext()) {
String t = scanner.next();
if (t.equals("*") || t.equals("<") || t.equals(">")) {
tmp += "\n";
}
tmp += t + " ";
}
System.out.println("Content" + tmp);
Question
Is Java handling the execution differently? Because I don't see why I get a different result
Any help is appreciated.
Best
I developed a Business Network Definition with Hyperledger Composer, deployed it on a Hyperledger Fabric example-chain (running locally on a VirtualBox-installation of Ubuntu with Docker-containers) and started Composer's REST-server with composer-rest-server (and options -c [cardname] -n always -w true). Then I played a bit in the browser and all is working fine.
Now comes the problematic bit: I want to write a Java-program interacting with this REST API and somehow the API seems unable to parse my Java-sent requests. I copied the JSON-string that Java produces to the browser, ran it there and it worked fine. But if I send it programmatically I get the error (see at the end).
This is what I send through the browser
{"cId":"C_ID7","cDomain":"example.com"}
The browser tells me with CURL it should look like this
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{"cId":"C_ID7","cDomain":"example.com"}' 'http://localhost:3000/api/com.example.Company'
Now I want to send the same message through Java+JSOUP with the following code:
Response resp = Jsoup.connect(baseURL + namespace + "Company").ignoreContentType(true).method(Method.POST)
.ignoreHttpErrors(true)
.requestBody("{\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"}").execute();
The same (without the requestBody and Method.GET) works for GET-requests. ignoreContentType(true) is necessary, because JSOUP will not handle 'application/json', see here. ignoreHttpErrors(true) is necessary, to get through the Http 500 error, which conceals the true error, which I need for trouble-shooting.
So then finally what I see, when I execute the above code, is the following error:
{"error":{"statusCode":500,"name":"Error","message":"Property names containing dot(s) are not supported. Model: com_example_Company, dynamic property: {\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"}","stack":"Error: Property names containing dot(s) are not supported. Model: com_example_Company, dynamic property: {\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"}\n at com_example_Company.ModelBaseClass._initProperties
(/home/[user]
]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model.js:249:17)\n
at com_example_Company.ModelBaseClass (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model.js:60:8)\n
at com_example_Company.Model (eval at createModelClassCtor
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model-builder.js:671:21), <anonymous>:12:24)\n
at com_example_Company.PersistedModel (eval at createModelClassCtor
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model-builder.js:671:21), <anonymous>:12:24)\n
at new com_example_Company (eval at createModelClassCtor
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model-builder.js:671:21), <anonymous>:12:24)\n
at Function.DataAccessObject.create (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/dao.js:359:13)\n
at SharedMethod.invoke
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/lib/shared-method.js:270:25)\n
at HttpContext.invoke (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/lib/http-context.js:297:12)\n
at phaseInvoke (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/lib/remote-objects.js:676:9)\n at runHandler
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/lib/phase.js:135:5)\n
at iterate (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:146:13)\n
at Object.async.eachSeries
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:162:9)\n
at runHandlers (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/lib/phase.js:144:13)\n
at iterate
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:146:13)\n
at /home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:157:25\n
at /home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:154:25"}}
where obviously [user] is my username. So I had a look at the loopback-datasource-juggler sources and found that in model-builder.js (source on Github) instead of parsing the different properties of the string, it is given the complete string ("{\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"). In line 269 the builder checks whether there are dot-characters in the property-name. Since in our case the property name is the complete JSON-string, there are dots and the program fails.
Unfortunately XML does not seem to be supported at this point.
Now: How can this happen? My only guess is an encoding thing done by Java, because the same JSON works in the browser. Any ideas what could have caused this?
And one smaller issue: The error message in the code is ''Property names containing dot(s) are not supported. ' + 'Model: %s, property: %s'', but in the error I receive it says something about "dynamic property". Am I at the wrong point for searching what causes the error?
Since you have already specified 'Content-Type: application/json', you needn't have double quotes in the requestBody. The following should work:
Response resp = Jsoup.connect(baseURL + namespace + "Company").ignoreContentType(true).method(Method.POST)
.ignoreHttpErrors(true)
.requestBody({\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"}).execute();
the curl example is what the REST APIs (rather than merely the browser) know about the business network REST API endpoints.
for your requestBody, you will need the fully qualified class (ie meaning asset/participant/transaction class with leading namespace) - an example is :
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \
"$class": "org.example.biznet.SampleAsset", \
"assetId": "1", \
"value": "103300" \
}' 'http://localhost:3000/api/SampleAsset'
So yours will be something like
Response resp = Jsoup.connect(baseURL + namespace + "Company").ignoreContentType(true).method(Method.POST)
.ignoreHttpErrors(true)
.requestBody("{\"\$class\": \"org.example.biznet.SampleAsset\", \"cId\":\"C_ID7\", \"cDomain\":\"example.com\"}").execute();
I believe you also needed at least one other double-quotes (total above now : 14) and a closing curly bracket in addition.
I found this example of a API request. Unfortunately I didn't find any other example how to upload an image to the API.
As I'm not familiar with Python I'm trying to understand how to do the same in a cURL command.
import requests
auth_headers = {
'app_id': 'your_app_id',
'app_key': 'your_app_key'
}
url = 'https://XXXXXXX'
files = {
'source': open('media/test.jpg')
}
data = {
'timeout': 60
}
response = requests.post(url, files=files, data=data, headers=auth_headers)
I tried to convert it by trying out a cURL to python converter, but I don't know how to build it with the files.
In the end I want to do the request in JAVA, but I think if I would know the request in cURL I can figure it out.
Hope anyone can help me with that.
This will do it:
#!/bin/bash
args=(
-H 'app_id: your_app_id'
-H 'app_key: your_app_key'
-F 'source=#/path/to/file'
-F 'timeout=60'
'http://httpbin.org/post'
)
curl "${args[#]}"
or, as a one-liner:
curl -H 'app_id: your_app_id' -H 'app_key: your_app_key' -F 'source=#/path/to/file' -F 'timeout=60' 'http://httpbin.org/post'
Use -H to specify header fields (repeat for every field) and -F to specify form fields - either as key=value pairs, or filename=#path pairs. When -F is used, POST method is the default, and Content-Type is multipart/form-data (but that too can be overridden).
I have been successfully able to perform CURL commands from the CMD in my Windows PC by installing curl for Windows. Similarly, I have been able to get them working in my JAVA application by using ProcessBuilder and Process to create Operating System process. In particular, I need to execute the REST API end point commands used in KissFlow given here: https://support.kissflow.com/support/solutions/articles/179582-understanding-the-rest-api-end-points
Question: I have been able to able to execute the commands with the GET method like so.
ProcessBuilder pb = new ProcessBuilder("curl","-H","api_key:<XXXX>","-X","GET","http://<XXXX>.appspot.com/api/1/Employee/list/p1/50
However, when using the commands with POST like
ProcessBuilder pb = new ProcessBuilder("curl","-H","api_key:<XXXX>","-X ","POST","--data-urlencode","First Name=XXXX","http://<XXXX>.appspot.com/api/1/Employee/submit");, I get an error:
curl: (6) Could not resolve host: POST
with the input stream of the process returning
<html><title>Error 400 (Bad Request)!!1</title></html>
This in fact works perfectly when executed from CMD.
I have tried suggestions of all related questions here. Any help is appreciated. Thanks.
EDIT: Any alternate method from CURL to do the same will be acceptable as well.
According #GyroGearless's idea, try to use the sample code below to retrieve responses from URLs through methods GET and POST using Apache's HttpClient class. I think that with HttpClient you'll have much more "power" than with CURL.
You'll need commons-httpclient.jar and its dependencies: commons-codec and commons-logging. You'll find these jars at http://commons.apache.org/downloads/
(...)
String url = "http://<XXXX>.appspot.com/api/1/Employee/list/p1/50";
HttpClient client = new HttpClient();
GetMethod get = new GetMethod(url);
client.executeMethod(get);
System.out.println(new String(get.getResponseBody()));
get.releaseConnection();
url = "http://<XXXX>.appspot.com/api/1/Employee/submit";
PostMethod post = new PostMethod(url);
post.addParameter("id", "10");
client.executeMethod(post);
System.out.println(new String(post.getResponseBody()));
post.releaseConnection();
(...)
As you can see, in the PostMethod part we're sending parameters within request. Maybe you don't need this....
You can also use Visual studio, we also created a post method where we reject requests in kissflow. Just letting you know that you can also do that in visual studio.