Skip to content

Commit 3bc7983

Browse files
authored
Fetched API key from env file (#1048)
* Added dot env file utils * Fetched API key from .env file when required * updated dependencies * Changed API key regex * Added name field in customJob struct * Replaced content-type field with headers in dataSourceURLStruct * Updated post request creation * picked API Regex from constants.go * Removed unwanted field from header * returned error as well from GetkeywordAndAPIKey * replaces regexp.Match() with strings.Contains() * support for headers in GET requests * Refactored GetDataFromAPI * Added processRequest retry constants
1 parent b3cf02d commit 3bc7983

File tree

12 files changed

+212
-94
lines changed

12 files changed

+212
-94
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,10 @@ Shown below is an example of how your `assets.json` file should be -
873873
"body": {},
874874
"content-type": ""
875875
},
876+
"name:" "eth_lunarCrush",
877+
"selector": "[`data`][`0`][`price`]",
878+
"power": 3,
879+
"weight": 2
876880
]
877881
}
878882
}

core/constants.go

+9
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ var AssetsDataFile = "assets.json"
4747
var ConfigFile = "razor.yaml"
4848
var LogFileDirectory = "logs"
4949
var DefaultPathName = ".razor"
50+
var DotENVFileName = ".env"
5051

5152
//BlockNumberInterval is the interval in seconds after which blockNumber needs to be calculated again
5253
var BlockNumberInterval = 5
54+
55+
//APIKeyRegex will be used as a regular expression to be matched in job Urls
56+
var APIKeyRegex = `$`
57+
58+
// Following are the constants which defines retry attempts and retry delay if there is an error in processing request
59+
60+
var ProcessRequestRetryAttempts uint = 2
61+
var ProcessRequestRetryDelay = 2

core/types/assets.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,15 @@ type AssignedAsset struct {
5151

5252
type CustomJob struct {
5353
URL string `json:"URL"`
54+
Name string `json:"name"`
5455
Selector string `json:"selector"`
5556
Power int8 `json:"power"`
5657
Weight uint8 `json:"weight"`
5758
}
5859

5960
type DataSourceURL struct {
60-
Type string `json:"type"`
61-
URL string `json:"url"`
62-
Body map[string]interface{} `json:"body"`
63-
ContentType string `json:"content-type"`
61+
Type string `json:"type"`
62+
URL string `json:"url"`
63+
Body map[string]interface{} `json:"body"`
64+
Header map[string]string `json:"header"`
6465
}

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ require (
4949
github.com/gorilla/websocket v1.4.2 // indirect
5050
github.com/hashicorp/hcl v1.0.0 // indirect
5151
github.com/inconshreveable/mousetrap v1.0.0 // indirect
52+
github.com/joho/godotenv v1.4.0 // indirect
5253
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect
5354
github.com/kennygrant/sanitize v1.2.4 // indirect
5455
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a // indirect

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,8 @@ github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1C
344344
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
345345
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
346346
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
347+
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
348+
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
347349
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
348350
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
349351
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=

path/mocks/path_interface.go

+21
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

path/path.go

+10
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,13 @@ func (PathUtils) GetDisputeDataFileName(address string) (string, error) {
113113
}
114114
return filepath.Join(dataFileDir, address+core.DisputeDataFile), nil
115115
}
116+
117+
//This function returns the job file path
118+
func (PathUtils) GetDotENVFilePath() (string, error) {
119+
razorPath, err := PathUtilsInterface.GetDefaultPath()
120+
if err != nil {
121+
return "", err
122+
}
123+
filePath := filepath.Join(razorPath, core.DotENVFileName)
124+
return filePath, nil
125+
}

path/pathUtils.go

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type PathInterface interface {
2020
GetCommitDataFileName(address string) (string, error)
2121
GetProposeDataFileName(address string) (string, error)
2222
GetDisputeDataFileName(address string) (string, error)
23+
GetDotENVFilePath() (string, error)
2324
}
2425

2526
type OSInterface interface {

utils/api.go

+65-31
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ import (
44
"bytes"
55
"encoding/json"
66
"errors"
7+
"io"
78
"net/http"
89
"razor/cache"
910
"razor/core"
11+
"strings"
1012
"time"
1113

12-
"io/ioutil"
1314
"razor/core/types"
1415

1516
"github.com/PaesslerAG/jsonpath"
@@ -23,62 +24,51 @@ func (*UtilsStruct) GetDataFromAPI(dataSourceURLStruct types.DataSourceURL, loca
2324
}
2425
cachedData, cachedErr := localCache.Read(dataSourceURLStruct.URL)
2526
if cachedErr != nil {
26-
var body []byte
27-
if dataSourceURLStruct.Type == "GET" {
27+
var response []byte
28+
switch dataSourceURLStruct.Type {
29+
case "GET":
2830
err := retry.Do(
2931
func() error {
30-
response, err := client.Get(dataSourceURLStruct.URL)
31-
if err != nil {
32-
return err
33-
}
34-
defer response.Body.Close()
35-
if response.StatusCode != 200 {
36-
log.Errorf("API: %s responded with status code %d", dataSourceURLStruct.URL, response.StatusCode)
37-
return errors.New("unable to reach API")
38-
}
39-
body, err = IOInterface.ReadAll(response.Body)
32+
responseBody, err := ProcessRequest(client, dataSourceURLStruct, nil)
4033
if err != nil {
34+
log.Error("Error in processing GET request: ", err)
4135
return err
4236
}
37+
response = responseBody
4338
return nil
44-
}, retry.Attempts(2), retry.Delay(time.Second*2))
39+
}, retry.Attempts(core.ProcessRequestRetryAttempts), retry.Delay(time.Second*time.Duration(core.ProcessRequestRetryDelay)))
4540
if err != nil {
4641
return nil, err
4742
}
48-
}
49-
if dataSourceURLStruct.Type == "POST" {
43+
case "POST":
5044
postBody, err := json.Marshal(dataSourceURLStruct.Body)
5145
if err != nil {
5246
log.Errorf("Error in marshalling body of a POST request URL %s: %v", dataSourceURLStruct.URL, err)
47+
return nil, err
5348
}
54-
responseBody := bytes.NewBuffer(postBody)
49+
requestBody := bytes.NewBuffer(postBody)
5550
err = retry.Do(
5651
func() error {
57-
response, err := client.Post(dataSourceURLStruct.URL, dataSourceURLStruct.ContentType, responseBody)
58-
if err != nil {
59-
log.Errorf("Error sending POST request URL %s: %v", dataSourceURLStruct.URL, err)
60-
return err
61-
}
62-
defer response.Body.Close()
63-
if response.StatusCode != 200 {
64-
log.Errorf("URL: %s responded with status code %d", dataSourceURLStruct.URL, response.StatusCode)
65-
return errors.New("unable to reach API")
66-
}
67-
body, err = ioutil.ReadAll(response.Body)
52+
responseBody, err := ProcessRequest(client, dataSourceURLStruct, requestBody)
6853
if err != nil {
54+
log.Error("Error in processing POST request: ", err)
6955
return err
7056
}
57+
response = responseBody
7158
return nil
72-
}, retry.Attempts(2), retry.Delay(time.Second*2))
59+
}, retry.Attempts(core.ProcessRequestRetryAttempts), retry.Delay(time.Second*time.Duration(core.ProcessRequestRetryDelay)))
7360
if err != nil {
7461
return nil, err
7562
}
63+
default:
64+
return nil, errors.New("invalid request type")
7665
}
66+
7767
dataToCache := cache.Data{
78-
Result: body,
68+
Result: response,
7969
}
8070
localCache.Update(dataToCache, dataSourceURLStruct.URL, time.Now().Add(time.Second*time.Duration(core.StateLength)).Unix())
81-
return body, nil
71+
return response, nil
8272
}
8373
log.Debugf("Getting Data for URL %s from local cache...", dataSourceURLStruct.URL)
8474
return cachedData.Result, nil
@@ -105,3 +95,47 @@ func (*UtilsStruct) GetDataFromXHTML(dataSourceURLStruct types.DataSourceURL, se
10595
}
10696
return priceData, nil
10797
}
98+
99+
func AddHeaderToRequest(request *http.Request, headerMap map[string]string) (*http.Request, error) {
100+
for key, value := range headerMap {
101+
// If core.APIKeyRegex = `$` and if value starts with '$' then we need to fetch the respective value from env file
102+
if strings.HasPrefix(value, core.APIKeyRegex) {
103+
_, APIKey, err := GetKeyWordAndAPIKeyFromENVFile(value)
104+
if err != nil {
105+
log.Error("Error in getting value from env file: ", err)
106+
return nil, err
107+
}
108+
value = APIKey
109+
}
110+
log.Debugf("Adding key: %s, value: %s pair to header", key, value)
111+
request.Header.Add(key, value)
112+
}
113+
return request, nil
114+
}
115+
116+
func ProcessRequest(client http.Client, dataSourceURLStruct types.DataSourceURL, requestBody io.Reader) ([]byte, error) {
117+
request, err := http.NewRequest(dataSourceURLStruct.Type, dataSourceURLStruct.URL, requestBody)
118+
if err != nil {
119+
return nil, err
120+
}
121+
requestWithHeader, err := AddHeaderToRequest(request, dataSourceURLStruct.Header)
122+
if err != nil {
123+
log.Errorf("Error in adding header to %s request: %v", dataSourceURLStruct.Type, err)
124+
return nil, err
125+
}
126+
response, err := client.Do(requestWithHeader)
127+
if err != nil {
128+
log.Errorf("Error sending %s request URL %s: %v", dataSourceURLStruct.Type, dataSourceURLStruct.URL, err)
129+
return nil, err
130+
}
131+
defer response.Body.Close()
132+
if response.StatusCode != 200 {
133+
log.Errorf("API: %s responded with status code %d", dataSourceURLStruct.URL, response.StatusCode)
134+
return nil, errors.New("unable to reach API")
135+
}
136+
responseBody, err := io.ReadAll(response.Body)
137+
if err != nil {
138+
return nil, err
139+
}
140+
return responseBody, nil
141+
}

0 commit comments

Comments
 (0)