Sending curl like request in golang - json

I try send request like this in golang but with no result:
curl -s -i -H "Accept: application/json" "http://192.168.1.183:8080/json.htm?type=command&c=getauth&param=udevice&idx=9&nvalue=0&svalue=10;43;2"
How to do that?
I want to send data do Domoticz Home Automation System.
Anser I got:
{
"status" : "ERR"
}
but should be:
{
"status" : "OK",
"title" : "Update Device"
}
I try this code:
b := bytes.NewBufferString("type=command&c=getauth&param=udevice&idx=9&nvalue=0&svalue=10;43;2")
res, _ := http.Post("http://192.168.1.183:8080/json.htm", "Accept: application/json", b)

Note that in your initial curl command, you missed the -X POST parameter.
The generated code would then be:
// Generated by curl-to-Go: https://mholt.github.io/curl-to-go
req, err := http.NewRequest("POST", "http://192.168.1.183:8080/json.htm?type=command&c=getauth&param=udevice&idx=9&nvalue=0&svalue=10;43;2", nil)
if err != nil {
// handle err
}
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
// handle err
}
defer resp.Body.Close()

Your curl command and Go code are almost completely unalike.
Your Go sends a POST request, and curl a GET request.
Your curl command sets an Accept header, your Go code doesn't.
Your Go command sends a body, your curl command doesn't.
Your curl command sends URL parameters, your Go code doesn't.
Your go code does the curl equivalent of:
curl -s -i -X POST -H "Accept: application/json" "http://192.168.1.183:8080/json.htm" -d "type=command&c=getauth&param=udevice&idx=9&nvalue=0&svalue=10;43;2"
The simplest way to emulate your curl command in Go is:
req, err := http.NewRequest("GET", "http://192.168.1.183:8080/json.htm?type=command&c=getauth&param=udevice&idx=9&nvalue=0&svalue=10;43;2", nil)
if err != nil {
panic(err)
}
req.Header.Add("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)

This works for me:
b := bytes.NewBufferString(" ")
res, _ := http.Post("http://192.168.1.183:8080/json.htm?type=command&c=getauth&param=udevice&idx=9&nvalue=0&svalue=10;43;2", "Accept: application/json", b)
but I think it is not best way to do that.

Related

Swagger How to describe JSON body parameter

I am trying to add documentation to my Rest API (Gin framework) and I stepped in some problems while trying to structure a JSON body parameter.
Currently, I have the following API description operations:
// #Summary logins a user
// #ID login-user
// #Accept json
// #Produce json
// #Param email formData string true "user email"
// #Param password formData string true "user password"
// #Success 200 {object} gin.H "login response"
// #Failure 400 {object} gin.H "error response"
// #Router /login [post]
func (server *Server) handleLoginUser() gin.HandlerFunc {
return func(ctx *gin.Context) {
var req loginUserRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
ctx.JSON(http.StatusBadRequest, utils.ErrorResponse(err))
return
}
// some code
ctx.JSON(http.StatusOK, response)
}
}
When I submit the data through Swagger UI I get the following error:
{
"error": "invalid character 'e' looking for beginning of value"
}
Also, this is the generated cURL:
curl -X 'POST' \
'http://localhost:8080/api/login' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d 'email=my%40email.com&password=password'
It's worth to mention that whenever I submit the same data in Postman with body Raw JSON it works. This is what a usual JSON looks like (also, loginUserRequest):
{
"email": "my#mail.com",
"password": "password"
}
Since I am new to Swagger, I am pretty sure it's something related to the email & password param type defined on the Swagger's [attribute documentation].
So, how should I describe better the loginRequest JSON body?
It was pretty easy, but I guess they omitted that in the documentation. I just changed the parameter as following:
// #Param loginUserRequest body loginUserRequest true "user password"
And then, when running swag init --parseDependency --parseInternal --parseDepth 1 it works.

gcloud functions call throwing invalid JSON error

I'm following this tutorial on how to set up a local gcloud functions environment. I have this script set up and deployed:
exports.helloGET = (req, res) => {
console.log(req.body);
// Example input: {“name”: “Junior”}
if (req.body.name === undefined) {
// This is an error case, as “name” is required.
res.status(400).send('No name defined!');
} else {
console.log(req.body.name);
res.status(200).send('Hello ' + req.body.name);
}
};
I tried testing this function on the Cloud GUI (the website) and it works when you test it with {"name": "Junior"}. It returns Hello Junior as expected.
I now want to be able to run the test locally from the command line, so referring to the docs, they give the example:
gcloud functions call helloWorld --data='{"message": "Hello World!"}'
However, when I try to run the following:
gcloud functions call helloGET --data='{"name": "Junior"}' --region=northamerica-northeast1
I keep getting
ERROR: (gcloud.functions.call) Invalid value for [--data]: Is not a valid JSON: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
Why is this happening? I'm doing exactly what the docs & the tutorial are doing.
I am unable to repro your issue (on Linux).
I wonder whether you're:
using a non-Linux OS and this an incompatibility
inadvertently including non-standard ' or "
Deployed:
gcloud functions deploy hello \
--entry-point=hello \
--runtime=nodejs12 \
--trigger-http \
--allow-unauthenticated \
--region=${REGION} \
--project=${PROJECT}
Then:
gcloud functions call hello \
--data='{"name":"Freddie"}' \
--region=${REGION} \
--project=${PROJECT}
executionId: 7igxh5sfvjvk
result: Hello Freddie
And:
gcloud functions call hello \
--data='{"name":"Freddie"}' \
--region=${REGION} \
--project=${PROJECT} \
--log-http
=======================
==== request start ====
uri: https://cloudfunctions.googleapis.com/v1/projects/.../functions/hello:call?alt=json
method: POST
== headers start ==
b'Authorization': --- Token Redacted ---
b'accept': b'application/json'
b'accept-encoding': b'gzip, deflate'
b'content-length': b'34'
b'content-type': b'application/json'
== headers end ==
== body start ==
{"data": "{\"name\":\"Freddie\"}"}
== body end ==
==== request end ====
---- response start ----
status: 200
-- headers start --
...
-- body start --
{
"executionId": "7igx3sfj3ate",
"result": "Hello Freddie"
}
-- body end --
total round trip time (request+response): 0.289 secs
---- response end ----
----------------------
executionId: 7igx3sfj3ate
result: Hello Freddie
NOTE curl encodes the value of data as "{\"name\":\"Freddie\"}
And:
ENDPOINT=$(\
gcloud functions describe hello \
--project=${PROJECT} \
--format="value(httpsTrigger.url)")
TOKEN=$(gcloud auth print-access-token)
curl \
--request POST \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${TOKEN}" \
--data '{"name":"Freddie"}' \
${ENDPOINT}
Hello Freddie

exec.Command Escaping Variables with JSON Payload

Thank you in advance as I have spent 2 days on this. Here is a working curl command.
curl -ku login:pass -X POST -H 'Content-Type: application/json'-d'{"type":"page","title":"Testpage","space":{"key":"ITDept"},"body":{"storage":{"value":"<p>Blank Page.</p>","representation":"storage"}}}' https://confluence/rest/api/content
I need to get this to execute with exec.Command.
Given that now in Go I have tried escaping and all sorts of other means to get this to work. The issue is more than likely this ridiculous JSON string that is required. I have the JSON string saved into a var now to try it that way.
jsonPayload := '{"type":"page","title":"Testpage","space":{"key":"ITDept"},"body":{"storage":{"value":"<p>Blank Page.</p>","representation":"storage"}}}'
execCmd := "bash", "-c", "curl -ku login:pass -X POST -H 'Content-Type: application/json' -d" jsonPayload "https://confluence/rest/api/content"
So the jsonPayload is the argument to -d. I have tried this using the Marshal json/encoding and the net/http package and it goes through but something about how that stdlib is sending it causes the API to state it is the wrong format.
I also have tried this with this and the curl copied out of the println works but when actually ran in golang it fails with incorrect format.
env := os.Environ()
curlCmd, err := exec.LookPath("curl")
if err != nil {
fmt.Println("Path not found to binary!")
panic(err)
}
args := []string{"curl", "-ku", "login:pass", "-X", "POST", "-H", "'Content-Type: application/json'", "-d", payloadJson, "https://confluence/rest/api/content"}
execErr := syscall.Exec(curlcmd, args, env)
if execErr != nil {
panic(execErr)
}
fmt.Println(curlCmd)
When the curlCmd from that last line there prints it can be copied and pasted into the terminal and it works however when going through golang it comes with a format not supported. Any help would be greatly appreciated.
Try this:
payload := `{"type":"page","title":"Testpage","space":{"key":"ITDept"},"body":{"storage":{"value":"<p>Blank Page.</p>","representation":"storage"}}}`
cmd := exec.Command("curl", "-ku", "login:pass", "-X", "POST", "-H", "Content-Type: application/json", "-d", payload, "http://localhost:8080/confluence/rest/api/content")
p, err := cmd.CombinedOutput()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", p)
Important change from code in the question:
Run command directly instead of using bash.
Specify host name in URL.
Properly quote the string.
BTW, you can also an interpreted string literal:
payload := "{\"type\":\"page\",\"title\":\"Testpage\",\"space\":{\"key\":\"ITDept\"},\"body\":{\"storage\":{\"value\":\"<p>Blank Page.</p>\",\"representation\":\"storage\"}}}"

Error using Octave 4.0.2 to submit Coursera assignments

This is the error:
curl: (1) Protocol "https" not supported or disabled in libcurl
!! Submission failed: unexpected error: input file does not exist
!! Please try again later.
I am using Windows 10.
I see a possibly relevant answer here, but I don't know where this code would be added within Octave.
The URL is changed. Use the new one in submissionUrl() function in lib/submitWithConfiguration.m file.
function submissionUrl = submissionUrl()
%submissionUrl = 'https://www-origin.coursera.org/api/onDemandProgrammingImmediateFormSubmissions.v1';
submissionUrl = 'https://www.coursera.org/api/onDemandProgrammingImmediateFormSubmissions.v1';
end
For check URL you can use curl in terminal.
curl -k 'https://www.coursera.org/api/onDemandProgrammingImmediateFormSubmissions.v1'
You must get something like {"message":"","statusCode":404}
With wrong URL you dose't get anything.
Try to use the patch that changes following lines in the response function of submitWithConfiguration.m:
params = {'jsonBody', body};
%responseBody = urlread(submissionUrl, 'post', params); OLD CODE
[code, responseBody] = system(sprintf('echo jsonBody=%s | curl -k -X POST -d #- %s', body, submissionUrl));
d #- takes data in a file on the current stdin (the echo fills in).
-k allows curl to perform "insecure" SSL
(see curl --help)
HTH
==================
your code is the one i have, but i'm W7.
Do another try by setting quotes around the url in :
function submissionUrl = submissionUrl()
submissionUrl =
'"https://www-origin.coursera.org/api/onDemandProgrammingImmediateFormSubmissions.v1"';
end
(caution use : ' " and " ' that will quote the "https://.." on the command line.)
If it doesn't work, do a direct call to coursera with a command line (cmd) :
curl -k "https://www-origin.coursera.org/api/onDemandProgrammingImmediateFormSubmissions.v1"
This will call coursera and, as there is no sent form , the site will respond with an html page with near the end ... Action not found ....
if this works, the pb is probably not inside curl, but somewhere else. let us know.
There was a typo in Answer #1, which was corrected in Answer #2.
The change is:
In the function,
function response = submitParts(conf, email, token, parts) Apply the following changes
Comment the line responseBody = urlread(submissionUrl, 'post', params);
Type the following in place of it,
[code, responseBody] = system(sprintf('echo jsonBody=%s | curl -k -XPOST -d #- %s', body, submissionUrl));
So the final code of the function looks like
function response = submitParts(conf, email, token, parts)
body = makePostBody(conf, email, token, parts);
submissionUrl = submissionUrl();
params = {'jsonBody', body};
#responseBody = urlread(submissionUrl, 'post', params);
[code, responseBody] = system(sprintf('echo jsonBody=%s | curl -k -XPOST -d #- %s', body, submissionUrl));
response = loadjson(responseBody);
end
Change the following in submitWithConfiguration.m:
curl -k -X POST
to
curl -k -XPOST
and try again.
I just ran into this issue on Windows 10 today. In my case the request was performing correctly but the curl command was outputting timing information by default which was throwing off the validation logic in the submission script.
The submission was succeeding, but if I printed the response string, it looked something like this:
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 1562 100 548 100 1014 548 1014 0:00:01 --:--:-- 0:00:01 2082
100 1562 100 548 100 1014 548 1014 0:00:01 --:--:-- 0:00:01 2082
{"id":"Blablablabla","courseId":"Blablabla","itemId":"Blabla",...}
I noticed that it was using the curl command to make the request, so I added the --silent flag to the code that creates the curl command to execute in submitWithConfiguration.m (in my case on line 134).
% use urlread or curl to send submit results to the grader and get a response
function response = getResponse(url, body)
% try using urlread() and a secure connection
params = {'jsonBody', body};
[response, success] = urlread(url, 'post', params);
if (success == 0)
% urlread didn't work, try curl & the peer certificate patch
if ispc
% testing note: use 'jsonBody =' for a test case
json_command = sprintf('echo jsonBody=%s | curl --silent -k -X POST -d #- %s', body, url);
% ^^^^^^^^ this right here!!
else
% it's linux/OS X, so use the other form
json_command = sprintf('echo ''jsonBody=%s'' | curl --silent -k -X POST -d #- %s', body, url);
end
% get the response body for the peer certificate patch method
[code, response] = system(json_command);
% test the success code
if (code ~= 0)
fprintf('[error] submission with curl() was not successful\n');
end
end
end
Now the response looked like a more reasonable:
{"id":"Blablablabla","courseId":"Blablabla","itemId":"Blabla",...}
And the submittion completed successfully.
I was having the same problem. All I did to overcome this problem is, I changed the path to ex2 folder and it worked for me.

Grails command object and 404 when space inside JSON from CURL

I have inherited a controller.
When a post request is made, with a well structured JSON document everything is fine.
When the JSON contains a space in a feld, 404 is returned.
However, when the same request is made from mozilla restclient extension everything works.
The CURL request specifically is:
curl --include \
--request POST \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data-binary "{
"planCode" : "My Test App-standard"
}" \
"https://localhost/signupApi/v2/signup"
URLMapping:
"/signupApi/v2/$action"{
parseRequest = true // parse json, and assign to params
controller = "signupApiSignup"
}
So, why would a space in curl cause problems in the request body that grails receives?
Thanks
You are not quoting your strings there properly in your shell. Use ' for your parameters, if you plan to use "sensitive" chars like " there. Or use \" inside. Also curl can read a filename if you prefix it with # instead of the actual data.
Yet in this case maybe quoting with ' is easiest. E.g.:
...
--data-binary '{
"planCode" : "My Test App-standard"
}'
...