How to GET Request with Cookie After login - go

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)

Related

Include client multi part form file in new POST request

Think I might be missing something obvious here. I'm attempting to grab the file from a client request hitting my server and forwarding that to an external API for processing by creating a new multipart request and copying the file over. In this case, the API is looking for a FormFile under the "files" key. The receiving API keeps telling me the file has invalid mime type application/octet-stream
API Call Documentation
func forwardFile(r *http.Request) (string, error) {
file, fileHandler, err := r.FormFile("image")
if err != nil {
return "", err
}
defer file.Close()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("files", fileHandler.Filename)
if err != nil {
return "", err
}
if _, err := io.Copy(part, file); err != nil {
return "", err
}
writer.Close()
req, _ := http.NewRequest("POST", newUploadUrl, body)
req.Header.Add("Content-Type", writer.FormDataContentType())
client := &http.Client{}
response, err := client.Do(req)
}
Thank you for your time.
I guess you need to change your content type to multipart/form-data
Solved it by creating a MIMEHeader and populating the disposition and content type myself, see below:
partHeader := textproto.MIMEHeader{}
disposition := fmt.Sprintf("form-data; name=\"files\"; filename=\"%s\"", fileHandler.Filename)
partHeader.Add("Content-Disposition", disposition)
partHeader.Add("Content-Type", "image/png")
part, err := writer.CreatePart(partHeader)
if _, err := io.Copy(part, file); err != nil {
log.Print("Error copying")
return "", err
}

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 return a body from another request

req, err := http.NewRequest("GET", "https://api.github.com/repos/octocat/Hello-World/pulls/1347", nil)
req.Header.Set("Accept", "application/vnd.github.v3.patch")
if err != nil {
check(err)
}
body, err := ioutil.ReadAll(req.Body)
ctxt.JSON(http.StatusOK, body)
Here I need to send api response from body of github api. But here I'm getting the following error:
"runtime error: invalid memory address or nil pointer dereference"
You're creating a new GET request with a nil body. See the function signature for http.NewRequest
func NewRequest(method, url string, body io.Reader) (*Request, error)
so when you access resp.Body, of course it's going to be nil.
Also, http.NewRequest just returns a request, it doesn't actually perform it.
To actually make the GET request with your request, you need to pass it to a http client's Do method. Like so:
response, err := http.DefaultClient.Do(resp)
EDIT: I would also add that naming your request as resp is confusing. I would recommend renaming the variable to req or request
this code will solve your issues.
client := &http.Client{}
apiURL := "https://api.github.com/repos/octocat/Hello-World/pulls/1347"
req, err := http.NewRequest("GET", apiURL, nil)
if err != nil {
check(err)
}
req.Header.Add("Accept", "application/vnd.github.v3.patch")
response, err := client.Do(req)
if err != nil {
check(err)
}
defer response.Body.Close()
contents, err := ioutil.ReadAll(response.Body)
if err != nil {
check(err)
}
ctxt.JSON(http.StatusOK, string(contents))

Sending octet stream

I have two go programs - one running as a server daemon, the other being executed manually. I want to be able to send a request to the server from the other program, sending some binary data there via post request. How can I do this?
I know I can send a string like this:
data := url.Values{}
data.Set("req", buf)
u, _ := url.ParseRequestURI(domain)
u.Path = path
urlStr := fmt.Sprintf("%v", u)
client := &http.Client{}
r, _ := http.NewRequest("POST", urlStr, bytes.NewBufferString(data.Encode()))
r.Header.Add("Authorization", "auth_token=\"XXXXXXX\"")
r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
r.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
resp, _ := client.Do(r)
return resp.Status
But I want to send an octet-stream which I can then read from ioutil.ReadAll(r.Body).
The following show how to send data inside the request body to a server, and read it on the server side. The client part is as follow:
c := http.Client{}
data := []byte("This is a content that will be sent in the body")
r, err := http.NewRequest("POST", "http://localhost:8080", bytes.NewBuffer(data))
// You should never ignore the error returned by a call.
if err != nil {
panic(err)
}
c.Do(r)
And in your http.Handler function:
d, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
}
fmt.Println("Request content : ", string(d))
This is the easiest way.

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