github.com/bloxroute-labs/bor@v0.1.4/consensus/bor/rest.go (about)

     1  package bor
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"net/http"
     8  	"net/url"
     9  	"path"
    10  	"time"
    11  
    12  	"github.com/maticnetwork/bor/log"
    13  )
    14  
    15  // ResponseWithHeight defines a response object type that wraps an original
    16  // response with a height.
    17  type ResponseWithHeight struct {
    18  	Height string          `json:"height"`
    19  	Result json.RawMessage `json:"result"`
    20  }
    21  
    22  // internal fetch method
    23  func internalFetch(client http.Client, u *url.URL) (*ResponseWithHeight, error) {
    24  	res, err := client.Get(u.String())
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  	defer res.Body.Close()
    29  
    30  	// check status code
    31  	if res.StatusCode != 200 {
    32  		return nil, fmt.Errorf("Error while fetching data from Heimdall")
    33  	}
    34  
    35  	// get response
    36  	body, err := ioutil.ReadAll(res.Body)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	// unmarshall data from buffer
    42  	var response ResponseWithHeight
    43  	if err := json.Unmarshal(body, &response); err != nil {
    44  		return nil, err
    45  	}
    46  
    47  	return &response, nil
    48  }
    49  
    50  // FetchFromHeimdallWithRetry returns data from heimdall with retry
    51  func FetchFromHeimdallWithRetry(client http.Client, urlString string, paths ...string) (*ResponseWithHeight, error) {
    52  	u, err := url.Parse(urlString)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  
    57  	for _, e := range paths {
    58  		if e != "" {
    59  			u.Path = path.Join(u.Path, e)
    60  		}
    61  	}
    62  
    63  	for {
    64  		res, err := internalFetch(client, u)
    65  		if err == nil && res != nil {
    66  			return res, nil
    67  		}
    68  		log.Info("Retrying again in 5 seconds for next Heimdall span", "path", u.Path)
    69  		time.Sleep(5 * time.Second)
    70  	}
    71  }
    72  
    73  // FetchFromHeimdall returns data from heimdall
    74  func FetchFromHeimdall(client http.Client, urlString string, paths ...string) (*ResponseWithHeight, error) {
    75  	u, err := url.Parse(urlString)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	for _, e := range paths {
    81  		if e != "" {
    82  			u.Path = path.Join(u.Path, e)
    83  		}
    84  	}
    85  
    86  	return internalFetch(client, u)
    87  }