1
0
Fork 0
This repository has been archived on 2024-07-04. You can view files and clone it, but cannot push or open issues or pull requests.
helium-blockchain-exporter/heliumapi/query.go

141 lines
3.7 KiB
Go
Raw Normal View History

2021-09-13 03:25:47 +00:00
package heliumapi
import (
"context"
2021-09-25 01:30:22 +00:00
"encoding/json"
2021-09-13 03:25:47 +00:00
"fmt"
"io/ioutil"
"net/http"
"time"
2021-09-13 03:25:47 +00:00
)
var (
ApiUrl = "https://api.helium.io"
ApiTimeout = time.Duration(10 * time.Second)
client = &http.Client{}
2021-09-13 03:25:47 +00:00
)
2021-09-26 04:42:34 +00:00
// createGetRequest create a GET request to the helium api
func createGetRequest(path string, params map[string]string) (*http.Request, *context.CancelFunc, error) {
ctx, ctxCancel := context.WithTimeout(context.Background(), ApiTimeout)
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s%s", ApiUrl, path), nil)
2021-09-13 03:25:47 +00:00
// setup headers
req.Header.Add("Accept", "application/json")
// setup query param if there are any
if params != nil {
query := req.URL.Query()
2021-09-25 01:30:22 +00:00
for k, v := range params {
2021-09-13 03:25:47 +00:00
query.Add(k, v)
}
if err != nil {
defer ctxCancel()
return nil, nil, err
2021-09-13 03:25:47 +00:00
}
req.URL.RawQuery = query.Encode()
}
return req, &ctxCancel, err
2021-09-25 01:30:22 +00:00
}
2021-09-26 04:42:34 +00:00
// getHeliumApi query a regular helium api endpoint
2021-09-25 01:30:22 +00:00
func getHeliumApi(path string, params *map[string]string) ([]byte, error) {
// if params is nil, set it to an empty map
if params == nil {
params = &map[string]string{}
}
req, ctxCancel, err := createGetRequest(path, *params)
2021-09-25 01:30:22 +00:00
if err != nil {
return nil, fmt.Errorf("failed to create query request %v: %v", path, err)
}
defer (*ctxCancel)()
2021-09-25 01:30:22 +00:00
2021-09-13 03:25:47 +00:00
// query the api
2021-10-12 14:37:03 +00:00
// log.Printf("querying %v", req.URL.String())
2021-09-13 03:25:47 +00:00
resp, err := client.Do(req)
if err != nil {
2021-10-12 13:19:58 +00:00
return nil, fmt.Errorf("failed to query %v: %v", req.URL.String(), err)
2021-09-13 03:25:47 +00:00
}
defer resp.Body.Close()
2021-10-03 22:02:25 +00:00
// validate the response status
if resp.StatusCode != 200 {
2021-10-12 13:19:58 +00:00
return nil, fmt.Errorf("failed to query %v: http status %v", req.URL.String(), resp.StatusCode)
2021-10-03 22:02:25 +00:00
}
2021-09-13 03:25:47 +00:00
// read the response body
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
2021-10-12 13:19:58 +00:00
return nil, fmt.Errorf("failed to read response body of %v: %v", req.URL.String(), err)
2021-09-13 03:25:47 +00:00
}
return body, nil
}
2021-09-26 04:42:34 +00:00
// getHeliumApiWithCursor query a helium api with a cursor
// It will continue to query the api until all the cursors are exhausted. Combine all the
// responses in a single object.
2021-09-25 01:30:22 +00:00
func getHeliumApiWithCursor(path string, params *map[string]string) ([][]byte, error) {
// if params is nil, set it to an empty map
if params == nil {
params = &map[string]string{}
}
type ResponseWithCursor struct {
Cursor string `json:"cursor"`
}
res := [][]byte{}
respCursor := ResponseWithCursor{}
req, ctxCancel, err := createGetRequest(path, *params)
2021-09-25 01:30:22 +00:00
if err != nil {
return nil, fmt.Errorf("failed to create query request %v: %v", path, err)
}
defer (*ctxCancel)()
2021-09-25 01:30:22 +00:00
for {
// query the api
resp, err := client.Do(req)
if err != nil {
2021-10-12 13:19:58 +00:00
return nil, fmt.Errorf("failed to query %v: %v", req.URL.String(), err)
2021-09-25 01:30:22 +00:00
}
defer resp.Body.Close()
// read the response body and add it to the result array
2021-10-12 14:37:03 +00:00
// log.Printf("querying %v", req.URL.String())
2021-09-25 01:30:22 +00:00
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
2021-10-12 13:19:58 +00:00
return nil, fmt.Errorf("failed to read response body of %v: %v", req.URL.String(), err)
2021-09-25 01:30:22 +00:00
}
res = append(res, body)
2021-10-03 22:02:25 +00:00
// validate the response status
if resp.StatusCode != 200 {
2021-10-12 13:19:58 +00:00
return nil, fmt.Errorf("failed to query %v: http status %v", req.URL.String(), resp.StatusCode)
2021-10-03 22:02:25 +00:00
}
2021-09-25 01:30:22 +00:00
// parse the response body for a cursor
respCursor.Cursor = ""
err = json.Unmarshal(body, &respCursor)
if err != nil {
2021-10-12 13:19:58 +00:00
return nil, fmt.Errorf("failed to unmarshal response from %v: %v", req.URL.String(), err)
2021-09-25 01:30:22 +00:00
}
// continue querying until there is no longer a cursor
if respCursor.Cursor != "" {
params = &map[string]string{"cursor": respCursor.Cursor}
req, ctxCancel, err = createGetRequest(path, *params)
2021-09-25 01:30:22 +00:00
if err != nil {
2021-10-12 13:19:58 +00:00
return nil, fmt.Errorf("failed to create query request %v: %v", req.URL.String(), err)
2021-09-25 01:30:22 +00:00
}
defer (*ctxCancel)()
2021-09-25 01:30:22 +00:00
} else {
break
}
}
return res, nil
2021-09-13 03:25:47 +00:00
}