How can I call async API using Go http

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
)

type Token struct {
	TokenType    string `json:"token_type"`
	Scope        string `json:"scope"`
	ExpiresIn    uint   `json:"expires_in"`
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	IdToken      string `json:"id_token"`
}

func main() {

	tenant := "https://example.com/adfs"
	url := tenant + "/oauth2/token"
	
	payload := strings.NewReader("grant_type=client_credentials&tenant_id=adxxxa2e&client_secret=45xxxN9&resource=https://ax.d365ffo.onprem.xxx.com")

	// payload := strings.NewReader("grant_type=password&client_id=a1xxxa2e&scope=user.read openid profile offline_access&client_secret=45xxxN9&username=xxx%40xxx.com&password=xxx")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	var data Token
	json.Unmarshal(body, &data)
	token := fmt.Sprintf("%v %v\n", data.TokenType, data.AccessToken)

	Employees(token)
}

func Employees(token string) {

	fmt.Println(token)

	url := "https://ax.d365ffo.onprem.xxx.com/namespaces/AXSF/data/Employees"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Accept", "*/*")
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", token)

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close() // Getting error at  this
	body, _ := ioutil.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))
}

The output I get is:

PS D:\goD365> go run token.go
bearer eyJ0eX*******************************************PZs4guAQ

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x40 pc=0x36df4d]

goroutine 1 [running]:
main.Employees({0xc000162e00, 0x373})
        D:/goD365/token.go:67 +0x34d  // => defer res.Body.Close() // line# 4 from bottom
main.main()
        D:/goD365/token.go:42 +0x2f4  // => Employees(token)
exit status 2
PS D:\goD365> 

The output I’m getting using postman is:

{
  "@odata.context": "https://ax.d365ffo.onprem.xxx.com/namespaces/AXSF/data/$metadata#Employees",
  "value": [
    {
      "@odata.etag": "W/\"JzEyxxxxJw==\"",
      "PersonnelNumber": "xxxx",
      "EmploymentStartDate": "2018-12-31T21:00:00Z",
      "LastName": "xx",
      "NativeLanguageId": "EN",
      "FirstName": "xx",
    },
    {
      "@odata.etag": "W/\"JzEyxxxxJw==\"",
      "PersonnelNumber": "xxxx",
      "EmploymentStartDate": "2018-12-31T21:00:00Z",
      "LastName": "xx",
      "NativeLanguageId": "EN",
      "FirstName": "xx",
    },
}

As the response is in the form of OData, I assume the API type is async, and this is why my fail (but not sure about my understandingm it may be an XY problem).

Any help!

Please check the returned error. res is probably nil, and that shouldn’t happen unless err is non-nil.

1 Like