This question already has answers here:
How do I send a JSON string in a POST request in Go
(8 answers)
Closed 8 months ago.
Can somebody help to convert my ruby code to Go. Kindly refer to my ruby code below.
query= "test"
request = Net::HTTP::Post.new(url)
request.body = query
response = Net::HTTP.new(host, post).start{|http http.request(request)}
to Go.
You seem to want to POST a query, which would be similar to this answer:
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "http://xxx/yyy"
fmt.Println("URL:>", url)
var query = []byte(`your query`)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(query))
req.Header.Set("X-Custom-Header", "myvalue")
req.Header.Set("Content-Type", "text/plain")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("response Status:", resp.Status)
fmt.Println("response Headers:", resp.Header)
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("response Body:", string(body))
}
Replace "text/plain" with "application/json" if your query is a JSON one.
Related
This question already has answers here:
How to set headers in http get request?
(4 answers)
set headers for request using http.Client and http.Transport
(1 answer)
Set UserAgent in http request
(1 answer)
Closed last year.
I'm creating a reverse proxy in Golang and I'm having trouble trying to grab online examples on how to add HTTP headers to an API call.
Here is my API call:
package handlers
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
func (s *Server) getApiCall(w http.ResponseWriter, r *http.Request) {
resp, err := http.Get("https://url.com")
if err != nil {
log.Fatalln(err)
}
//We Read the response body on the line below.
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalln(err)
}
//Convert the body to type string
sb := string(body)
log.Printf(sb)
fmt.Fprintf(w, sb)
}
Where in my function can I add an Authorization header with the a Bearer <TOKEN> as its value?
I'm new with Go, to my understanding this should be enough code, but if you need more detail about my backend just add a comment in what needs clarification.
You can't use http.Get, instead use http.NewRequest to create a request object then add the headers to it.
One example:
client := &http.Client{}
req, err := http.NewRequest("GET", "https://url.com", nil)
if err != nil {
// handle error
}
req.Header.Add("Authorization", "Bearer ...")
resp, err := client.Do(req)
if err != nil {
// handle error
}
For more details take a look at http package doc.
I am trying to implement a python code from the JIRA REST API examples:
https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-jql/#api-rest-api-3-jql-parse-post
My python code (which works as expected):
import requests
from requests.auth import HTTPBasicAuth
import json
url = "https://my-url.com/rest/api/2/search"
auth = HTTPBasicAuth("user1", "pwd1")
headers = {
"Accept": "application/json",
"Content-Type": "application/json"
}
payload = json.dumps( {
"jql": "my-query-string"
}
response = requests.request("POST", url, data=payload, headers=headers, auth=auth, verify=False)
print(json.dumps(json.loads(response.text), sort_keys=True, indent=4, separators=(",", ": ")))
I'm trying to transform this to a golang code as below:
package main
import (
"io/ioutil"
"fmt"
"log"
"time"
"net/http"
"net/url"
}
func main() {
timeout := time.Duration(500 * time.Second)
client := http.Client{
Timeout: timeout,
}
req, err := http.NewRequest("POST", "https://my-url.com/rest/api/2/search", nil)
if err != nil {
log.Fatalln(err)
}
req.SetBasicAuth("user1", "pwd1")
req.Header.Set("Content-Type", "application/json")
q := url.Values{}
q.Add("jql", "my-query-string")
req.URL.RawQuery = q.Encode()
fmt.Println(req.URL.String())
resp, err := client.Do(req)
if err != nil {
log.Fatalln(err)
}
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalln(err)
}
log.Println(string(data))
The code builds with no issues. When I run the go code, I get this error:
2021/04/17 19:36:31 {"errorMessages":["No content to map to Object due to end of input"]}
I have 2 questions :
a. How can I fix the above error ?
b. I also want to include concurrency in the same code, i.e the same POST request will actually be executed for 5 different query strings (concurrently) and fetch the results, how can i achieve that ?
For POST requests you need to send the data as json. Note that in Go setting a request's Content-Type header does not automagically convert whatever you give it to the specified type.
An example sending json.
package main
import (
"strings"
"net/http"
"io/ioutil"
"fmt"
)
func main() {
body := strings.NewReader(`{"jql": "project = HSP"}`)
req, err := http.NewRequest("POST", "https://your-domain.atlassian.com/rest/api/2/search", body)
if err != nil {
panic(err)
}
req.SetBasicAuth("email#example.com", "<api_token>")
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(out))
}
If you want to use query parameters you should use the endpoint with the GET method.
package main
import (
"net/http"
"net/url"
"io/ioutil"
"fmt"
)
func main() {
query := url.Values{"jql": {"project = HSP"}}
req, err := http.NewRequest("GET", "https://your-domain.atlassian.com/rest/api/2/search?" + query.Encode(), nil)
if err != nil {
panic(err)
}
req.SetBasicAuth("email#example.com", "<api_token>")
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(out))
}
I am working in a Go project, and I need to perform some operations over an external API: GET, PUT, POST and DELETE. Currently I am using net/http, and I created a &http.Client{} to make GET and PUT. That is working as expected.
Now I need to perform a DELETE and I cannot find anything about it. Is it supported? Basically, I need to call a URL like this:
somedomain.com/theresource/:id
Method: DELETE
How can I perform that?
Here is a small example of how to do it:
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func sendRequest() {
// Request (DELETE http://www.example.com/bucket/sample)
// Create client
client := &http.Client{}
// Create request
req, err := http.NewRequest("DELETE", "http://www.example.com/bucket/sample", nil)
if err != nil {
fmt.Println(err)
return
}
// Fetch Request
resp, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer resp.Body.Close()
// Read Response Body
respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
return
}
// Display Results
fmt.Println("response Status : ", resp.Status)
fmt.Println("response Headers : ", resp.Header)
fmt.Println("response Body : ", string(respBody))
}
I'm a new golang programmer. In java it's very easy to set with method HTTP.setEntity(). but in golang, I have test servel way to set it, but our server still missing receive entity data.
Here is code:
func bathPostDefects(){
url := "http://127.0.0.1/edit"
var jsonStr = []byte(`{"key":"abc","id":"110175653","resolve":2,"online_time":"2016-7-22","priority":1,"comment":"something.."}`)
req, err := http.NewRequest("POST",url,bytes.NewBuffer(jsonStr))
fmt.Println("ContentLength: ",len(jsonStr))
req.Header.Set("Content-Type","application/json")
req.Header.Set("Content-Length",string(len(jsonStr)))
client := &http.Client{}
resp,err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("response Status:", resp.Status)
fmt.Println("response Headers:", resp.Header)
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("response Body:", string(body))
}
problem find it, it is cause by our servlet has read the form values, not the request body, code update following:
func bathPostDefects(){
v := url.Values{}
v.Set("key", "abc")
v.Add("id", "110175653")
v.Add("resolve", "2")
v.Add("online_time", "2016-7-22")
v.Add("priority", "1")
v.Add("comment", "something..")
fmt.Println(v.Get("id"))
fmt.Println(v.Get("comment"))
resp, err := http.PostForm("http://127.0.0.1/edit",v)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("response Status:", resp.Status)
fmt.Println("response Headers:", resp.Header)
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("response Body:", string(body))
}
thank you all you guys.
I changed a bit code to use NewBufferString, and tested it together with server that prints request's body:
package main
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
)
func bathPostDefects() {
url := "http://127.0.0.1:4141/"
var jsonStr = `{"key":"abc","id":"110175653","resolve":2,"online_time":"2016-7-22","priority":1,"comment":"something.."}`
req, err := http.NewRequest("POST", url, bytes.NewBufferString(jsonStr))
fmt.Println("ContentLength: ", len(jsonStr))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Content-Length", string(len(jsonStr)))
client := &http.Client{}
_, err = client.Do(req)
if err != nil {
panic(err)
}
}
func server() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
body, _ := ioutil.ReadAll(r.Body)
fmt.Println("Body: ", string(body))
})
log.Fatal(http.ListenAndServe(":4141", nil))
}
func main() {
go server()
time.Sleep(time.Second)
bathPostDefects()
}
I'm trying to access an API like this:
package main
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
func main() {
apiUrl := "https://example.com/api/"
data := url.Values{}
data.Set("api_token", "MY_KEY")
data.Add("action", "list_projects")
req, _ := http.NewRequest("POST", apiUrl, bytes.NewBufferString(data.Encode()))
client := &http.Client{}
resp, err := client.Do(req)
defer resp.Body.Close()
if err == nil {
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(resp.Status)
fmt.Println(string(body))
}
}
But the response from an API tells me there was no data in POST request.
If I do it like this with curl, it works:
$ curl -X POST "https://example.com/api/" -d "api_token=MY_KEY" -d "action=list_projects"
You may want to use this form of request
resp, err := http.PostForm("http://example.com/form",
url.Values{"key": {"Value"}, "id": {"123"}})
or use the right mime type :
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
and encode data
strings.NewReader(data.Encode())
It's better if you test err != nil and return if necessary. This code may not work cause the request failed.
defer resp.Body.Close()
instead use this pattern:
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(resp.Status)
fmt.Println(string(body))
So you can see in the console if the request failed or not