Skip to content

Commit

Permalink
Add flag for specifying an extra http header in RPC requests (#48)
Browse files Browse the repository at this point in the history
Conduit wanted to be able to specify an http header, this would allow
them to pin the indexer to a specific node.
  • Loading branch information
vegarsti authored Jul 1, 2024
1 parent ef58570 commit 5da0081
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 6 deletions.
15 changes: 11 additions & 4 deletions client/jsonrpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ const (
)

type rpcClient struct {
client *retryablehttp.Client
cfg Config
log *slog.Logger
bufPool *sync.Pool
client *retryablehttp.Client
cfg Config
log *slog.Logger
bufPool *sync.Pool
httpHeaders map[string]string
}

func NewClient(log *slog.Logger, cfg Config) (*rpcClient, error) { // revive:disable-line:unexported-return
Expand Down Expand Up @@ -61,6 +62,7 @@ func NewClient(log *slog.Logger, cfg Config) (*rpcClient, error) { // revive:dis
return new(bytes.Buffer)
},
},
httpHeaders: cfg.HTTPHeaders,
}
// lets validate RPC node is up & reachable
_, err := rpc.LatestBlockNumber()
Expand Down Expand Up @@ -112,6 +114,11 @@ func (c *rpcClient) getResponseBody(
if err != nil {
return err
}
if c.httpHeaders != nil {
for k, v := range c.httpHeaders {
req.Header.Set(k, v)
}
}
resp, err := c.client.Do(req)
if err != nil {
return fmt.Errorf("failed to send request for method %s: %w", method, err)
Expand Down
1 change: 1 addition & 0 deletions client/jsonrpc/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ import "time"
type Config struct {
URL string
PollInterval time.Duration
HTTPHeaders map[string]string
}
13 changes: 12 additions & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"log/slog"
"os"
"os/signal"
"strings"
stdsync "sync"
"syscall"
"time"
Expand Down Expand Up @@ -48,10 +49,20 @@ func main() {
var wg stdsync.WaitGroup
var rpcClient jsonrpc.BlockchainClient

rpcHTTPHeaders := make(map[string]string)
if cfg.RPCNode.ExtraHTTPHeader != "" {
pair := strings.Split(cfg.RPCNode.ExtraHTTPHeader, ",")
// We've validated this list has two elements
key := strings.Trim(pair[0], " ")
value := strings.Trim(pair[1], " ")
logger.Info("Adding extra HTTP header to RPC requests", "key", key, "value", value)
rpcHTTPHeaders[key] = value
}
switch cfg.RPCStack {
case models.OpStack:
rpcClient, err = jsonrpc.NewOpStackClient(logger, jsonrpc.Config{
URL: cfg.RPCNode.NodeURL,
URL: cfg.RPCNode.NodeURL,
HTTPHeaders: rpcHTTPHeaders,
})
default:
stdlog.Fatalf("unsupported RPC stack: %s", cfg.RPCStack)
Expand Down
11 changes: 10 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package config

import (
"errors"
"fmt"
"strings"
"time"

"github.com/duneanalytics/blockchain-ingester/models"
Expand All @@ -21,13 +23,20 @@ func (d DuneClient) HasError() error {
}

type RPCClient struct {
NodeURL string `long:"rpc-node-url" env:"RPC_NODE_URL" description:"URL for the blockchain node"`
NodeURL string `long:"rpc-node-url" env:"RPC_NODE_URL" description:"URL for the blockchain node"`
ExtraHTTPHeader string `long:"rpc-http-header" env:"RPC_HTTP_HEADER" description:"Extra HTTP header to send with RPC requests. On the form 'key,value'"` // nolint:lll
}

func (r RPCClient) HasError() error {
if r.NodeURL == "" {
return errors.New("RPC node URL is required")
}
if r.ExtraHTTPHeader != "" {
header := strings.Split(r.ExtraHTTPHeader, ",")
if len(header) != 2 {
return fmt.Errorf("invalid rpc http header: expected 'key,value', got '%s'", r.ExtraHTTPHeader)
}
}
return nil
}

Expand Down

0 comments on commit 5da0081

Please sign in to comment.