How to set a GET request header in Golang

Asked

Viewed 184 times

2

I’m trying to make Golang my first mid-high level language, but I’m having some problems. I can’t set a header for an external GET request at all, I searched the documentation, forums and the only thing I could find was to set a response header (for API creation). In my case, I need to set a header for a GET request for a certain API.

In the documentation of this API, it says that authentication is done through the header

Authentication: "TOKEN"

I tried several ways. Currently my code is like this, some good translator or language expert to explain to me how this header?

func get() {
    API := "www.google.com"
    TOKEN := "abcdefg"

    resp, err := http.Get(API)
    resp.Header.Set("Authentication", TOKEN)

    if err != nil {
        log.Fatalln(err)
    }

    defer resp.Body.Close()
    bodyBytes, _ := ioutil.ReadAll(resp.Body)

    bodyString := string(bodyBytes)
    fmt.Printf("%+v\n", bodyString)

}

func main() {
    get()
}

4 answers

4

resp, err := http.Get(API)

No way to change the header with Get, he makes the request immediately and uses the values default package http.


What you need to create is a custom request, using the function NewRequest.

req, err := http.NewRequest(http.MethodGet, API, nil)
if err != nil {
    log.Fatal(err)
}

Then we change the header of req, and we file the requisition with Do

req.Header.Set("Authorization", "Token " + TOKEN)

resp, err := http.DefaultClient.Do(req)
if err != nil {
    log.Fatal(err)
}

func get() {
    API := "https://www.google.com" // Você tem que colocar o protocol scheme da URL 
    TOKEN := "abcdefg"

    req, err := http.NewRequest(http.MethodGet, API, nil)
    if err != nil {
        log.Fatal(err)
    }
    req.Header.Set("Authorization", "Token " + TOKEN)

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        log.Fatal(err)
    }

    defer resp.Body.Close()
    bodyBytes, _ := ioutil.ReadAll(resp.Body)

    bodyString := string(bodyBytes)
    fmt.Printf("%+v\n", bodyString)
}

OBS.: http.DefaultClient is the package’s default HTTP client, but it does not define a timeout for the requisitions. If the API server, for example, is out of the air or with other problems your application may be stuck waiting for the answer. So it is recommended to create your own http.Client's.

Read more about:

  • I understood that GET is not "parametravel", but even editing the code is still giving authentication error. I’m sure it’s in relation to the Request Headers because in JS is working and receiving the data from the API correctly, with the same token, same API, etcetera.

  • 1

    Could you post the API doc link? And the error message too.

  • {"message":"Authentication credentials have not been provided or are invalid. This error message is from the API, as I tested it in JS/php/Curl using the right/wrong token. It is the 403 return of the api.

  • @Dashadelas try to set the header this way: req.Header.Set("Authorization", "Token " + TOKEN) .

1

You must set the header before making the request.

Follow an example:

API_URL := "https://www.google.com"
request, _ := http.NewRequest(http.MethodGet, API_URL, nil)

request.Header.Set("X-APPLICATION-TOKEN", "Abc_213")

REQUEST_TIMEOUT := 30
client := &http.Client{
    Timeout:   time.Duration(REQUEST_TIMEOUT) * time.Second,
}
response, err := client.Do(request)
if err != nil {
    log.Fatalln(err)
}

defer response.Body.Close()
//fazer leitura do body da requisição

In my example I am using the function NewRequest of the package http.


In your application if you use self-signed certificates, there may be problems making the request.

To solve this problem, you should create an http. Transport and remove the verification of trusted certificates using the option InsecureSkipVerify setting the value true.

Follow an example:

import (
"crypto/tls"
//...
)

tr := &http.Transport{
    TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
// depois utilizar na instanciação do http.Client
client := &http.Client{
    Transport: tr,
    Timeout:   time.Duration(REQUEST_TIMEOUT) * time.Second,
}
  • Still giving error, I am 90% sure it is in the Headers, because the API requires that the Header Authentication is the Token generated by the site. I tested with Node and PHP and both ran smooth!

  • There may be some header missing, like application/json. It could show how you are doing using curl, if you successfully request?

  • Another problem I’ve been through is if you’re using https with self-signed certificate, I’ll edit to contain the information.

  • I published a new omental, with updated explanations on.

0

Well, I am making the same request with Nodejs + Node-fetch and is returning 200 with the API data, using the following code:

const headers = {
  method: 'get',
  headers: {
    Authorization: `Token ${token}`,
  }
}

fetch(url, headers)

As I did not declare any other header other than Authorization (yes, I had wrong this part, I was using Authentication, but even correcting, it gives 403.

My code in GO

req, err := http.NewRequest("GET", URL, nil)
    if err != nil {
        log.Fatal(err)
    }
    req.Header.Set("Authorization", TOKEN)
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        log.Fatal(err)
    }

    defer resp.Body.Close()
    bodyBytes, _ := ioutil.ReadAll(resp.Body)

    // Convert response body to string
    bodyString := string(bodyBytes)
    fmt.Print(bodyString)

Being:

TOKEN: correto! O mesmo do JS (ctrl + ctrl v milhões de vezes)
URL: Usada com o protocolo e correta, pois entra diretamente acessada pelo browser, requerida pelo cURL, PHP, NODE...
  • 2

    Here does not show how your token is set, in golang it should be: req.Header.Set("Authorization", "Token "+TOKEN),

  • 1

    My God, I can’t believe it! IT WORKED

  • 1

    hehehe, solved.

0

As the two answers helped me, I leave here the solution to my problem, in case someone is looking for the same,

First of all, I was using the wrong HTTP method because GET doesn’t have settable headers. So instead of http.Get had to use http.NewRequest, as explained user Suriyel.

Then, after that, the problem still continued, and the solution given by the user Danizavtz was to use:

req.Header.Set("Authorization", "Token "+TOKEN)

instead of

req.Header.Set("Authorization", TOKEN)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.