Reuse Go http client - go

I want to make a get request for each param in an params array. The url is static. Is there a way to reuse my custom http client for each iteration? I don't want to reset the header for each request. Ideally, I'd like to do something like client.Do(param) for each iteration.
client := &http.Client{}
for _, param := range params {
uri := url + param
req, err := http.NewRequest(http.MethodGet, uri, nil)
req.Header.Add("Cookie", cookie)
resp, _ := client.Do(req)
defer resp.Body.Close()
// do something...
}

I think you are wanting to just keep your cookies, and not have to set it on each request? If that's the case you can do:
import (
"net/http"
"net/http/cookiejar"
"golang.org/x/net/publicsuffix"
)
// All users of cookiejar should import "golang.org/x/net/publicsuffix"
cookieJar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
if err != nil {
panic(err)
}
var cookies []*http.Cookie
cookies = append(cookies, cookie)
u, err := url.Parse("http://whateversite.com")
if err != nil {
panic(err)
}
jar.SetCookies(u, cookies)
client := &http.Client{
Jar: cookieJar,
}

Related

How to read from array json response in Go

I have an API request that returns a refresh_token inside array, which looks something like this:
[
{
"refresh_token" : "C61551CEA183EDB767AA506926F423B339D78E2E2537B4AC7F8FEC0C29988819"
}
]
I need to access this refresh_token's value, and use it to query another API.
To do this, I'm attempting to first 'ReadAll' the response body, and then access the key inside of it by calling 'refreshToken'.
However, it's not working. Does anyone know how to resolve this as I can't figure it out?
Here's my code:
func Refresh(w http.ResponseWriter, r *http.Request) {
client := &http.Client{}
// q := url.Values{}
fetchUrl := "https://greatapiurl.com"
req, err := http.NewRequest("GET", fetchUrl, nil)
if err != nil {
fmt.Println("Errorrrrrrrrr")
os.Exit(1)
}
req.Header.Add("apikey", os.Getenv("ENV"))
req.Header.Add("Authorization", "Bearer "+os.Getenv("ENV"))
resp, err := client.Do(req)
if err != nil {
fmt.Println("Ahhhhhhhhhhhhh")
os.Exit(1)
}
respBody, _ := ioutil.ReadAll(resp.Body)
fmt.Println(respBody["refresh_token"])
w.WriteHeader(resp.StatusCode)
w.Write(respBody)
}
If you do not need it as custom type you can cast it as []map[string]string
respBody, _ := ioutil.ReadAll(resp.Body)
var body []map[string]string
json.Unmarshal(respBody, &body)
fmt.Println(body[0]["refresh_token"])

How to GET Request with Cookie After login

I tried to get some resp.Body of jadwalURL. jadwalURL can be access after login, so I add the Cookie header to the request. But Sadly the response is not quite that I want (response is home page). I tried this similiar flow with Postman. and I got the jadwalURL body as i wanted. Is there anything wrong with my code? I still dont get the solution after 3 hours searching.
func main() {
data := url.Values{}
data.Set("username", username)
data.Set("password", password)
client := &http.Client{}
r, _ := http.NewRequest(http.MethodPost, loginURL, strings.NewReader(data.Encode()))
r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, _ := client.Do(r)
cookie := resp.Cookies()
fmt.Println(cookie)
fmt.Println(resp.Status)
req, err := http.NewRequest(http.MethodGet, jadwalURL, nil)
if err != nil {
panic(err)
}
req.AddCookie(&http.Cookie{
Name: cookie[0].Name,
Value: cookie[0].Value,
Domain: domainURL,
Path: "/",
})
jadwalResp, err := http.DefaultClient.Do(req)
if err != nil {
panic(nil)
}
body, _ := ioutil.ReadAll(jadwalReq.Body)
jadwalResp.Body.Close()
fmt.Println(string(body))
}
Hi If you have this problem I just change create a newClient the problem is i tried to make request with client.
newClient := &http.Client{}
// then
jadwalResp, err := newClient.Do(req)

Consume a DELETE endpoint from Go

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))
}

Post request with data in go

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

Basic HTTP Auth in Go

I'm trying to do basic HTTP auth with the code below, but it is throwing out the following error:
2013/05/21 10:22:58 Get mydomain.example: unsupported protocol scheme ""
exit status 1
func basicAuth() string {
var username string = "foo"
var passwd string = "bar"
client := &http.Client{}
req, err := http.NewRequest("GET", "mydomain.example", nil)
req.SetBasicAuth(username, passwd)
resp, err := client.Do(req)
if err != nil{
log.Fatal(err)
}
bodyText, err := ioutil.ReadAll(resp.Body)
s := string(bodyText)
return s
}
Any idea what I may be doing wrong?
the potential 'gotcha' is if your website does any redirects... Go-lang will drop your specified headers on the redirects. (I had to do wireshark to see this! You can quicky find out in chrome by right-clicking then "inspect element" and click network tab)
you'll want to define a redirect function that adds the header back in.
func basicAuth(username, password string) string {
auth := username + ":" + password
return base64.StdEncoding.EncodeToString([]byte(auth))
}
func redirectPolicyFunc(req *http.Request, via []*http.Request) error{
req.Header.Add("Authorization","Basic " + basicAuth("username1","password123"))
return nil
}
func main() {
client := &http.Client{
Jar: cookieJar,
CheckRedirect: redirectPolicyFunc,
}
req, err := http.NewRequest("GET", "http://localhost/", nil)
req.Header.Add("Authorization","Basic " + basicAuth("username1","password123"))
resp, err := client.Do(req)
}
You need to specify the protocol for NewRequest, e.g. "http://", see here.
req, err := http.NewRequest("GET", "http://mydomain.example", nil)

Resources