How can I call async APIs using Go HTTP – Code Review – Go Forum?

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 am 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",
    },
}

Since the response is in the form of OData, I assume the API type is async, and that’s why my failure (but not sure about my understanding that it might be an XY problem).

any help!

Leave a Comment