exec.Command Escaping Variables with JSON Payload - json

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\"}}}"

Related

extra backward slash along with quotes on jsonencode a json array object

In terraform,I am trying to make a PUT call via curl command using null_resource and executing the command in local_exec provisioner. The body of the request is json array.
The command expects the data to be in string format. I have the data as tuple in locals. I am using jsonencode to serialize the tupple to a string and pass to curl. But on jsonencode, the string formed has an additional \ prefixed before each " in json string.
eg. expected json string is:
"[{"key-1" : "value-1", "key-2": "value-2"}]"
But after jsonencode, the formatted string is as follows:
"[{\"key-1\" : \"value-1\", \"key-2\": \"value-2\"}]"
additional backslash is added along with quotes.
Because of the malformed request body, the API returns Bad Request response.
How can we correctly serialize the tupple/list to correct json string in Terraform and pass to curl command?
This is my null_resource:
resource "null_resource" "call_API" {
for_each = { for x in local.array: x.name => {
name = x.name
vars = jsonencode(x.vars)
} }
provisioner "local-exec" {
command = <<EOF
curl -X PUT ${var.url} -d ${each.value.vars} -H 'Content-Type:application/json' -H 'Authorization:${local.bearer_token}'
EOF
}
I think I understand that you want to pass this variable
"[{"key-1" : "value-1", "key-2": "value-2"}]"
You tried to use EOF?
You can do something like that
variable "body" {
type = "string"
}
variable = <<EOF
"[{"key-1" : "value-1", "key-2": "value-2"}]"
EOF
Or with EOT, honestly I don't remember which one work
EDIT:
If the json is not static and you receive it from other module or others, you can try to expand the variable inside the EOFs
body = <<EOF
${var.json}
EOF

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.

Sending curl like request in golang

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.

Error while Passing Json string in scala using Curl

I am trying to post a json string using curl in scala. My curl command works fine if executed from linux box but throes an error(("message": "Must provide query string.",) always from scala.
my working curl command in linux:
curl http://laptpad1811:5000/graphql -H "Content-Type: application/json"
-X POST -d '{"query":"mutation
CreateFileReceivedEvent($createFileReceivedEventInput:
CreateFleReceivedEventInput!) { createFileReceivedEvent(input:
$createFileReceivedEventInput) { clientMutationId }}","variables":
{"createFileReceivedEventInput":
{"clientMutationId":"Test","fileReceivedEvent":{"file":
{"fileTrackingId":"83a86c44-66a5-4de0-9b7f-
c6995877279d","name":"textfile_2017-08-21T15:58:45Z","fileType":
{"code":"textfile"}},"eventTimestamp":"2017-08-
21T15:59:30Z"}}},"operationName":"CreateFileReceivedEvent"}'
My scala code:
step1: copying the entire json string(pay load) to txt file
'{"query":"mutation CreateFileReceivedEvent($createFileReceivedEventInput:
CreateFleReceivedEventInput!) { createFileReceivedEvent(input:
$createFileReceivedEventInput) { clientMutationId }}","variables":
{"createFileReceivedEventInput":
{"clientMutationId":"Test","fileReceivedEvent":{"file":
{"fileTrackingId":"83a86c44-66a5-4de0-9b7f-
c6995877279d","name":"textfile_2017-08-21T15:58:45Z","fileType":
{"code":"textfile"}},"eventTimestamp":"2017-08-
21T15:59:30Z"}}},"operationName":"CreateFileReceivedEvent"}'
step2:
val data=fromFile("/usr/test/data.txt").getLines.mkString
step3:
val cmd = Seq("curl", "http://laptpad1811:5000/graphql", "-H",
"'Content-Type:application/json'" ,"-X", "POST", "-d" , data)
step4:
cmd.!!
I get the below error
String =
"{
"errors": [
{
"message": "Must provide query string.",
"stack": "BadRequestError: Must provide query string.\n
I have tried to change " to ' and mutiple combinations of the json string but I always get the same error.
I suspect that your issue is that sys.process doesn't pass commands through the shell (e.g. bash), so quotes that are necessary in the shell become unnecessary in Scala (and get passed through to the command which in the case of Unix-style utilities will probably result in unexpected behavior).
So try:
val cmd = Seq("curl", "http://laptpad1811:5000/graphql", "-H", "Content-Type: application/json", "-X", "POST", "-d", data)
Likewise remove the single quote wrapping from your text file.
I would however, counsel against spawning a curl in Scala and advise using one of the existing http client libraries (I personally like Gigahorse).

Simple JSON request with cURL to Mochiweb

I have a very simple 'hello world' Mochiweb server (I just started my introduction into it), which takes a JSON request and sends it back:
'POST' ->
case Path of
"dummy" ->
Data = Req:parse_post(),
Json = proplists:get_value("json", Data),
Struct = mochijson2:decode(Json),
Action_value = struct:get_value(<<"action">>, Struct),
Action = list_to_atom(binary_to_list(A)),
Result = [got_json_request, Action],
DataOut = mochijson2:encode(Result),
Req:ok({"application/json",[],[Result]});
The thing is that when I try to make a request to it with cURL it fails:
curl -i -H "Content-Type: application/json" -H "Accept: application/json" -X POST -d '{"action":"dummy"}' http://localhost:8080/dummy
The Mochiweb log is quite difficult to read, but as I understand the error happens at this line:
Json = proplists:get_value("json", Data)
I have put a couple of io:formats in the code and found out that both Data and Json variables are [] after I make a request with cURL.
On the other hand, when I do a very simple request with cURL:
curl -d '{"action":"dummy"}' http://localhost:8080/dummy
both Data and Json are [{"{\"action\":\"dummy\"}",[]}], but in that case the line Struct = mochijson2:decode(Json) fails.
For some strange reason Mochiweb does not see the JSON data in the POST request in case the header has the "application/json" value.
So, the question is: How do I make a correct POST request with JSON data to a Mochiweb server?
EDIT: Json variable has the undefined value.
Try something along the lines of
Data = Req:recv_body(),
Json = mochijson2:decode(Data),
...
You should at least ensure method post and the content type ahead of this.
This is not about POST nor get.
It's about how you post your data to send to your server
When you send a json data to server, you need to make it as key=value
curl -d "key=value" "http://your.domain.com/path"
Therefore, if you want to post json as '{"action":"dummy"}', for GET request
curl -d "json='{\"action\":\"dummy\"}'" http://localhost:8080/dummy
For POST request as a file,
curl -F "json=#filename.json" http://localhost:8080/dummy
of course, when you send as a file, you need to read the posted file from the server side.