cmd/geth, cmd/utils: geth attach with custom headers (#25829)

This PR makes it possible to set custom headers, in particular for two scenarios: 

- geth attach
- geth commands which can use --remotedb, e..g geth db inspect

The ability to use custom headers is typically useful for connecting to cloud-apis, e.g. providing an infura- or alchemy key, or for that matter access-keys for environments behind cloudflare.  

Co-authored-by: Felix Lange <fjl@twurst.com>
This commit is contained in:
Martin Holst Swende
2022-09-30 13:50:25 +02:00
committed by GitHub
co-authored by Felix Lange
parent 07e0704ca9
commit ea26fc8a6c
4 changed files with 128 additions and 42 deletions
+41 -2
View File
@@ -18,10 +18,13 @@
package utils
import (
"context"
"crypto/ecdsa"
"errors"
"fmt"
"math"
"math/big"
"net/http"
"os"
"path/filepath"
godebug "runtime/debug"
@@ -976,6 +979,13 @@ var (
Value: metrics.DefaultConfig.InfluxDBOrganization,
Category: flags.MetricsCategory,
}
HttpHeaderFlag = &cli.StringSliceFlag{
Name: "header",
Aliases: []string{"H"},
Usage: "Pass custom headers to the RPC server wheng using --" + RemoteDBFlag.Name + " or the geth attach console.",
Category: flags.NetworkingCategory,
}
)
var (
@@ -995,6 +1005,7 @@ var (
DataDirFlag,
AncientFlag,
RemoteDBFlag,
HttpHeaderFlag,
}
)
@@ -2125,8 +2136,12 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.
)
switch {
case ctx.IsSet(RemoteDBFlag.Name):
log.Info("Using remote db", "url", ctx.String(RemoteDBFlag.Name))
chainDb, err = remotedb.New(ctx.String(RemoteDBFlag.Name))
log.Info("Using remote db", "url", ctx.String(RemoteDBFlag.Name), "headers", len(ctx.StringSlice(HttpHeaderFlag.Name)))
client, err := DialRPCWithHeaders(ctx.String(RemoteDBFlag.Name), ctx.StringSlice(HttpHeaderFlag.Name))
if err != nil {
break
}
chainDb = remotedb.New(client)
case ctx.String(SyncModeFlag.Name) == "light":
chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly)
default:
@@ -2148,6 +2163,30 @@ func IsNetworkPreset(ctx *cli.Context) bool {
return false
}
func DialRPCWithHeaders(endpoint string, headers []string) (*rpc.Client, error) {
if endpoint == "" {
return nil, errors.New("endpoint must be specified")
}
if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") {
// Backwards compatibility with geth < 1.5 which required
// these prefixes.
endpoint = endpoint[4:]
}
var opts []rpc.ClientOption
if len(headers) > 0 {
var customHeaders = make(http.Header)
for _, h := range headers {
kv := strings.Split(h, ":")
if len(kv) != 2 {
return nil, fmt.Errorf("invalid http header directive: %q", h)
}
customHeaders.Add(kv[0], kv[1])
}
opts = append(opts, rpc.WithHeaders(customHeaders))
}
return rpc.DialOptions(context.Background(), endpoint, opts...)
}
func MakeGenesis(ctx *cli.Context) *core.Genesis {
var genesis *core.Genesis
switch {