-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Allow custom headers in validator client HTTP requests #15884
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package client | ||
|
||
import "net/http" | ||
|
||
// CustomHeadersTransport adds custom headers to each request | ||
type CustomHeadersTransport struct { | ||
base http.RoundTripper | ||
headers map[string][]string | ||
} | ||
|
||
func NewCustomHeadersTransport(base http.RoundTripper, headers map[string][]string) *CustomHeadersTransport { | ||
return &CustomHeadersTransport{ | ||
base: base, | ||
headers: headers, | ||
} | ||
} | ||
|
||
func (t *CustomHeadersTransport) RoundTrip(req *http.Request) (*http.Response, error) { | ||
for header, values := range t.headers { | ||
for _, value := range values { | ||
req.Header.Add(header, value) | ||
} | ||
} | ||
return t.base.RoundTrip(req) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package client | ||
|
||
import ( | ||
"net/http" | ||
"net/http/httptest" | ||
"testing" | ||
|
||
"github.com/OffchainLabs/prysm/v6/testing/assert" | ||
"github.com/OffchainLabs/prysm/v6/testing/require" | ||
) | ||
|
||
type noopTransport struct{} | ||
|
||
func (*noopTransport) RoundTrip(*http.Request) (*http.Response, error) { | ||
return nil, nil | ||
} | ||
|
||
func TestRoundTrip(t *testing.T) { | ||
tr := &CustomHeadersTransport{base: &noopTransport{}, headers: map[string][]string{"key1": []string{"value1", "value2"}, "key2": []string{"value3"}}} | ||
req := httptest.NewRequest("GET", "http://foo", nil) | ||
_, err := tr.RoundTrip(req) | ||
require.NoError(t, err) | ||
assert.DeepEqual(t, []string{"value1", "value2"}, req.Header.Values("key1")) | ||
assert.DeepEqual(t, []string{"value3"}, req.Header.Values("key2")) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
### Added | ||
|
||
- Allow custom headers in validator client HTTP requests. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ import ( | |
"strings" | ||
"time" | ||
|
||
api "github.com/OffchainLabs/prysm/v6/api/client" | ||
eventClient "github.com/OffchainLabs/prysm/v6/api/client/event" | ||
grpcutil "github.com/OffchainLabs/prysm/v6/api/grpc" | ||
"github.com/OffchainLabs/prysm/v6/async/event" | ||
|
@@ -79,6 +80,7 @@ type Config struct { | |
BeaconNodeGRPCEndpoint string | ||
BeaconNodeCert string | ||
BeaconApiEndpoint string | ||
BeaconApiHeaders map[string][]string | ||
BeaconApiTimeout time.Duration | ||
Graffiti string | ||
GraffitiStruct *graffiti.Graffiti | ||
|
@@ -142,6 +144,7 @@ func NewValidatorService(ctx context.Context, cfg *Config) (*ValidatorService, e | |
s.conn = validatorHelpers.NewNodeConnection( | ||
grpcConn, | ||
cfg.BeaconApiEndpoint, | ||
cfg.BeaconApiHeaders, | ||
cfg.BeaconApiTimeout, | ||
) | ||
|
||
|
@@ -185,8 +188,9 @@ func (v *ValidatorService) Start() { | |
return | ||
} | ||
|
||
headersTransport := api.NewCustomHeadersTransport(http.DefaultTransport, v.conn.GetBeaconApiHeaders()) | ||
restHandler := beaconApi.NewBeaconApiRestHandler( | ||
http.Client{Timeout: v.conn.GetBeaconApiTimeout(), Transport: otelhttp.NewTransport(http.DefaultTransport)}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does the |
||
http.Client{Timeout: v.conn.GetBeaconApiTimeout(), Transport: otelhttp.NewTransport(headersTransport)}, | ||
Comment on lines
192
to
+193
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if possible, we should have tests to see if the headers get added after the |
||
hosts[0], | ||
) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,13 +10,15 @@ import ( | |
type NodeConnection interface { | ||
GetGrpcClientConn() *grpc.ClientConn | ||
GetBeaconApiUrl() string | ||
GetBeaconApiHeaders() map[string][]string | ||
GetBeaconApiTimeout() time.Duration | ||
dummy() | ||
} | ||
|
||
type nodeConnection struct { | ||
grpcClientConn *grpc.ClientConn | ||
beaconApiUrl string | ||
beaconApiHeaders map[string][]string | ||
beaconApiTimeout time.Duration | ||
} | ||
|
||
|
@@ -28,16 +30,21 @@ func (c *nodeConnection) GetBeaconApiUrl() string { | |
return c.beaconApiUrl | ||
} | ||
|
||
func (c *nodeConnection) GetBeaconApiHeaders() map[string][]string { | ||
return c.beaconApiHeaders | ||
} | ||
|
||
func (c *nodeConnection) GetBeaconApiTimeout() time.Duration { | ||
return c.beaconApiTimeout | ||
} | ||
|
||
func (*nodeConnection) dummy() {} | ||
|
||
func NewNodeConnection(grpcConn *grpc.ClientConn, beaconApiUrl string, beaconApiTimeout time.Duration) NodeConnection { | ||
func NewNodeConnection(grpcConn *grpc.ClientConn, beaconApiUrl string, beaconApiHeaders map[string][]string, beaconApiTimeout time.Duration) NodeConnection { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe for stuff liek api headers and beacon api timeout we can turn those into functional parameters and add them in that way |
||
conn := &nodeConnection{} | ||
conn.grpcClientConn = grpcConn | ||
conn.beaconApiUrl = beaconApiUrl | ||
conn.beaconApiHeaders = beaconApiHeaders | ||
conn.beaconApiTimeout = beaconApiTimeout | ||
return conn | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -433,6 +433,7 @@ func (c *ValidatorClient) registerValidatorService(cliCtx *cli.Context) error { | |
BeaconNodeGRPCEndpoint: cliCtx.String(flags.BeaconRPCProviderFlag.Name), | ||
BeaconNodeCert: cliCtx.String(flags.CertFlag.Name), | ||
BeaconApiEndpoint: cliCtx.String(flags.BeaconRESTApiProviderFlag.Name), | ||
BeaconApiHeaders: parseBeaconApiHeaders(cliCtx.String(flags.BeaconRESTApiHeaders.Name)), | ||
BeaconApiTimeout: time.Second * 30, | ||
Graffiti: g.ParseHexGraffiti(cliCtx.String(flags.GraffitiFlag.Name)), | ||
GraffitiStruct: graffitiStruct, | ||
|
@@ -552,6 +553,7 @@ func (c *ValidatorClient) registerRPCService(cliCtx *cli.Context) error { | |
GRPCHeaders: strings.Split(cliCtx.String(flags.GRPCHeadersFlag.Name), ","), | ||
BeaconNodeGRPCEndpoint: cliCtx.String(flags.BeaconRPCProviderFlag.Name), | ||
BeaconApiEndpoint: cliCtx.String(flags.BeaconRESTApiProviderFlag.Name), | ||
BeaconAPIHeaders: parseBeaconApiHeaders(cliCtx.String(flags.BeaconRESTApiHeaders.Name)), | ||
BeaconApiTimeout: time.Second * 30, | ||
BeaconNodeCert: cliCtx.String(flags.CertFlag.Name), | ||
DB: c.db, | ||
|
@@ -636,3 +638,19 @@ func clearDB(ctx context.Context, dataDir string, force bool, isDatabaseMinimal | |
|
||
return nil | ||
} | ||
|
||
func parseBeaconApiHeaders(rawHeaders string) map[string][]string { | ||
result := make(map[string][]string) | ||
pairs := strings.Split(rawHeaders, ",") | ||
for _, pair := range pairs { | ||
key, value, found := strings.Cut(pair, "=") | ||
if !found { | ||
// Skip malformed pairs | ||
continue | ||
Comment on lines
+648
to
+649
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This still allows for some weird malformed data like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should add some tests for this function ( |
||
} | ||
key = strings.TrimSpace(key) | ||
value = strings.TrimSpace(value) | ||
result[key] = append(result[key], value) | ||
} | ||
return result | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ package rpc | |
import ( | ||
"net/http" | ||
|
||
api "github.com/OffchainLabs/prysm/v6/api/client" | ||
grpcutil "github.com/OffchainLabs/prysm/v6/api/grpc" | ||
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" | ||
"github.com/OffchainLabs/prysm/v6/validator/client" | ||
|
@@ -52,11 +53,13 @@ func (s *Server) registerBeaconClient() error { | |
conn := validatorHelpers.NewNodeConnection( | ||
grpcConn, | ||
s.beaconApiEndpoint, | ||
s.beaconApiHeaders, | ||
s.beaconApiTimeout, | ||
) | ||
|
||
headersTransport := api.NewCustomHeadersTransport(http.DefaultTransport, conn.GetBeaconApiHeaders()) | ||
restHandler := beaconApi.NewBeaconApiRestHandler( | ||
http.Client{Timeout: s.beaconApiTimeout, Transport: otelhttp.NewTransport(http.DefaultTransport)}, | ||
http.Client{Timeout: s.beaconApiTimeout, Transport: otelhttp.NewTransport(headersTransport)}, | ||
s.beaconApiEndpoint, | ||
Comment on lines
+60
to
63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here too, if possible, we should test if headers are being added after |
||
) | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name is a little verbose but I wanted to keep it aligned with the
--beacon-rest-api-provider
flag