This commit is contained in:
a 2024-03-24 12:57:27 -05:00
parent 15e5e6176b
commit 63a060d8ed
No known key found for this signature in database
GPG key ID: 374BC539FE795AF0
11 changed files with 65 additions and 40 deletions

View file

@ -743,7 +743,7 @@ func signer(c *cli.Context) error {
// start http server // start http server
httpEndpoint := fmt.Sprintf("%s:%d", c.String(utils.HTTPListenAddrFlag.Name), port) httpEndpoint := fmt.Sprintf("%s:%d", c.String(utils.HTTPListenAddrFlag.Name), port)
httpServer, addr, err := node.StartHTTPEndpoint(httpEndpoint, rpc.DefaultHTTPTimeouts, handler) httpServer, addr, err := node.StartHTTPEndpoint(httpEndpoint, c.String(utils.HTTPListenProtocolFlag.Name), rpc.DefaultHTTPTimeouts, handler)
if err != nil { if err != nil {
utils.Fatalf("Could not start RPC api: %v", err) utils.Fatalf("Could not start RPC api: %v", err)
} }

View file

@ -155,6 +155,7 @@ var (
rpcFlags = []cli.Flag{ rpcFlags = []cli.Flag{
utils.HTTPEnabledFlag, utils.HTTPEnabledFlag,
utils.HTTPListenAddrFlag, utils.HTTPListenAddrFlag,
utils.HTTPListenProtocolFlag,
utils.HTTPPortFlag, utils.HTTPPortFlag,
utils.HTTPCORSDomainFlag, utils.HTTPCORSDomainFlag,
utils.AuthListenFlag, utils.AuthListenFlag,

View file

@ -28,6 +28,7 @@ import (
"math/big" "math/big"
"net/http" "net/http"
"os" "os"
"path"
"path/filepath" "path/filepath"
godebug "runtime/debug" godebug "runtime/debug"
"strconv" "strconv"
@ -689,6 +690,12 @@ var (
Value: node.DefaultHTTPHost, Value: node.DefaultHTTPHost,
Category: flags.APICategory, Category: flags.APICategory,
} }
HTTPListenProtocolFlag = &cli.StringFlag{
Name: "http.proto",
Usage: "HTTP-RPC server listening protocol (tcp,unix)",
Value: node.DefaultHTTPProtocol,
Category: flags.APICategory,
}
HTTPPortFlag = &cli.IntFlag{ HTTPPortFlag = &cli.IntFlag{
Name: "http.port", Name: "http.port",
Usage: "HTTP-RPC server listening port", Usage: "HTTP-RPC server listening port",
@ -1169,12 +1176,23 @@ func SplitAndTrim(input string) (ret []string) {
// command line flags, returning empty if the HTTP endpoint is disabled. // command line flags, returning empty if the HTTP endpoint is disabled.
func setHTTP(ctx *cli.Context, cfg *node.Config) { func setHTTP(ctx *cli.Context, cfg *node.Config) {
if ctx.Bool(HTTPEnabledFlag.Name) && cfg.HTTPHost == "" { if ctx.Bool(HTTPEnabledFlag.Name) && cfg.HTTPHost == "" {
cfg.HTTPHost = "127.0.0.1"
if ctx.IsSet(HTTPListenAddrFlag.Name) { if HTTPListenProtocolFlag.Name == "unix" {
cfg.HTTPHost = ctx.String(HTTPListenAddrFlag.Name) cfg.HTTPHost = path.Join(os.TempDir(), "geth.http.sock")
} else {
cfg.HTTPHost = "127.0.0.1"
if ctx.IsSet(HTTPListenAddrFlag.Name) {
cfg.HTTPHost = ctx.String(HTTPListenAddrFlag.Name)
}
} }
} }
if ctx.IsSet(HTTPListenProtocolFlag.Name) {
cfg.HTTPProto = ctx.String(HTTPListenProtocolFlag.Name)
} else {
cfg.HTTPProto = "tcp"
}
if ctx.IsSet(HTTPPortFlag.Name) { if ctx.IsSet(HTTPPortFlag.Name) {
cfg.HTTPPort = ctx.Int(HTTPPortFlag.Name) cfg.HTTPPort = ctx.Int(HTTPPortFlag.Name)
} }

View file

@ -155,7 +155,7 @@ func (api *adminAPI) PeerEvents(ctx context.Context) (*rpc.Subscription, error)
} }
// StartHTTP starts the HTTP RPC API server. // StartHTTP starts the HTTP RPC API server.
func (api *adminAPI) StartHTTP(host *string, port *int, cors *string, apis *string, vhosts *string) (bool, error) { func (api *adminAPI) StartHTTP(proto *string, host *string, port *int, cors *string, apis *string, vhosts *string) (bool, error) {
api.node.lock.Lock() api.node.lock.Lock()
defer api.node.lock.Unlock() defer api.node.lock.Unlock()
@ -196,7 +196,7 @@ func (api *adminAPI) StartHTTP(host *string, port *int, cors *string, apis *stri
} }
} }
if err := api.node.http.setListenAddr(*host, *port); err != nil { if err := api.node.http.setListenAddr(*proto, *host, *port); err != nil {
return false, err return false, err
} }
if err := api.node.http.enableRPC(api.node.rpcAPIs, config); err != nil { if err := api.node.http.enableRPC(api.node.rpcAPIs, config); err != nil {
@ -210,9 +210,9 @@ func (api *adminAPI) StartHTTP(host *string, port *int, cors *string, apis *stri
// StartRPC starts the HTTP RPC API server. // StartRPC starts the HTTP RPC API server.
// Deprecated: use StartHTTP instead. // Deprecated: use StartHTTP instead.
func (api *adminAPI) StartRPC(host *string, port *int, cors *string, apis *string, vhosts *string) (bool, error) { func (api *adminAPI) StartRPC(proto *string, host *string, port *int, cors *string, apis *string, vhosts *string) (bool, error) {
log.Warn("Deprecation warning", "method", "admin.StartRPC", "use-instead", "admin.StartHTTP") log.Warn("Deprecation warning", "method", "admin.StartRPC", "use-instead", "admin.StartHTTP")
return api.StartHTTP(host, port, cors, apis, vhosts) return api.StartHTTP(proto, host, port, cors, apis, vhosts)
} }
// StopHTTP shuts down the HTTP server. // StopHTTP shuts down the HTTP server.
@ -229,7 +229,7 @@ func (api *adminAPI) StopRPC() (bool, error) {
} }
// StartWS starts the websocket RPC API server. // StartWS starts the websocket RPC API server.
func (api *adminAPI) StartWS(host *string, port *int, allowedOrigins *string, apis *string) (bool, error) { func (api *adminAPI) StartWS(proto *string, host *string, port *int, allowedOrigins *string, apis *string) (bool, error) {
api.node.lock.Lock() api.node.lock.Lock()
defer api.node.lock.Unlock() defer api.node.lock.Unlock()
@ -266,7 +266,7 @@ func (api *adminAPI) StartWS(host *string, port *int, allowedOrigins *string, ap
// Enable WebSocket on the server. // Enable WebSocket on the server.
server := api.node.wsServerForPort(*port, false) server := api.node.wsServerForPort(*port, false)
if err := server.setListenAddr(*host, *port); err != nil { if err := server.setListenAddr(*proto, *host, *port); err != nil {
return false, err return false, err
} }
openApis, _ := api.node.getAPIs() openApis, _ := api.node.getAPIs()

View file

@ -69,7 +69,7 @@ func TestStartRPC(t *testing.T) {
name: "rpc enabled through API", name: "rpc enabled through API",
cfg: Config{}, cfg: Config{},
fn: func(t *testing.T, n *Node, api *adminAPI) { fn: func(t *testing.T, n *Node, api *adminAPI) {
_, err := api.StartHTTP(sp("127.0.0.1"), ip(0), nil, nil, nil) _, err := api.StartHTTP(sp("tcp"), sp("127.0.0.1"), ip(0), nil, nil, nil)
assert.NoError(t, err) assert.NoError(t, err)
}, },
wantReachable: true, wantReachable: true,
@ -90,14 +90,14 @@ func TestStartRPC(t *testing.T) {
port := listener.Addr().(*net.TCPAddr).Port port := listener.Addr().(*net.TCPAddr).Port
// Now try to start RPC on that port. This should fail. // Now try to start RPC on that port. This should fail.
_, err = api.StartHTTP(sp("127.0.0.1"), ip(port), nil, nil, nil) _, err = api.StartHTTP(sp("tcp"), sp("127.0.0.1"), ip(port), nil, nil, nil)
if err == nil { if err == nil {
t.Fatal("StartHTTP should have failed on port", port) t.Fatal("StartHTTP should have failed on port", port)
} }
// Try again after unblocking the port. It should work this time. // Try again after unblocking the port. It should work this time.
listener.Close() listener.Close()
_, err = api.StartHTTP(sp("127.0.0.1"), ip(port), nil, nil, nil) _, err = api.StartHTTP(sp("tcp"), sp("127.0.0.1"), ip(port), nil, nil, nil)
assert.NoError(t, err) assert.NoError(t, err)
}, },
wantReachable: true, wantReachable: true,
@ -144,7 +144,7 @@ func TestStartRPC(t *testing.T) {
name: "ws enabled through API", name: "ws enabled through API",
cfg: Config{}, cfg: Config{},
fn: func(t *testing.T, n *Node, api *adminAPI) { fn: func(t *testing.T, n *Node, api *adminAPI) {
_, err := api.StartWS(sp("127.0.0.1"), ip(0), nil, nil) _, err := api.StartWS(sp("tcp"), sp("127.0.0.1"), ip(0), nil, nil)
assert.NoError(t, err) assert.NoError(t, err)
}, },
wantReachable: true, wantReachable: true,
@ -184,7 +184,7 @@ func TestStartRPC(t *testing.T) {
cfg: Config{HTTPHost: "127.0.0.1"}, cfg: Config{HTTPHost: "127.0.0.1"},
fn: func(t *testing.T, n *Node, api *adminAPI) { fn: func(t *testing.T, n *Node, api *adminAPI) {
wsport := n.http.port wsport := n.http.port
_, err := api.StartWS(sp("127.0.0.1"), ip(wsport), nil, nil) _, err := api.StartWS(sp("tcp"), sp("127.0.0.1"), ip(wsport), nil, nil)
assert.NoError(t, err) assert.NoError(t, err)
}, },
wantReachable: true, wantReachable: true,
@ -197,7 +197,7 @@ func TestStartRPC(t *testing.T) {
cfg: Config{HTTPHost: "127.0.0.1"}, cfg: Config{HTTPHost: "127.0.0.1"},
fn: func(t *testing.T, n *Node, api *adminAPI) { fn: func(t *testing.T, n *Node, api *adminAPI) {
wsport := n.http.port wsport := n.http.port
_, err := api.StartWS(sp("127.0.0.1"), ip(wsport), nil, nil) _, err := api.StartWS(sp("tcp"), sp("127.0.0.1"), ip(wsport), nil, nil)
assert.NoError(t, err) assert.NoError(t, err)
_, err = api.StopWS() _, err = api.StopWS()
@ -211,11 +211,11 @@ func TestStartRPC(t *testing.T) {
{ {
name: "rpc stopped with ws enabled", name: "rpc stopped with ws enabled",
fn: func(t *testing.T, n *Node, api *adminAPI) { fn: func(t *testing.T, n *Node, api *adminAPI) {
_, err := api.StartHTTP(sp("127.0.0.1"), ip(0), nil, nil, nil) _, err := api.StartHTTP(sp("tcp"), sp("127.0.0.1"), ip(0), nil, nil, nil)
assert.NoError(t, err) assert.NoError(t, err)
wsport := n.http.port wsport := n.http.port
_, err = api.StartWS(sp("127.0.0.1"), ip(wsport), nil, nil) _, err = api.StartWS(sp("tcp"), sp("127.0.0.1"), ip(wsport), nil, nil)
assert.NoError(t, err) assert.NoError(t, err)
_, err = api.StopHTTP() _, err = api.StopHTTP()
@ -229,11 +229,11 @@ func TestStartRPC(t *testing.T) {
{ {
name: "rpc enabled after ws", name: "rpc enabled after ws",
fn: func(t *testing.T, n *Node, api *adminAPI) { fn: func(t *testing.T, n *Node, api *adminAPI) {
_, err := api.StartWS(sp("127.0.0.1"), ip(0), nil, nil) _, err := api.StartWS(sp("tcp"), sp("127.0.0.1"), ip(0), nil, nil)
assert.NoError(t, err) assert.NoError(t, err)
wsport := n.http.port wsport := n.http.port
_, err = api.StartHTTP(sp("127.0.0.1"), ip(wsport), nil, nil, nil) _, err = api.StartHTTP(sp("tcp"), sp("127.0.0.1"), ip(wsport), nil, nil, nil)
assert.NoError(t, err) assert.NoError(t, err)
}, },
wantReachable: true, wantReachable: true,

View file

@ -105,6 +105,10 @@ type Config struct {
// field is empty, no HTTP API endpoint will be started. // field is empty, no HTTP API endpoint will be started.
HTTPHost string HTTPHost string
// HTTPProto is the protocol on which the HTTP RPC server will bind.
// Supported values are tcp, unix. HTTPPort is ignored if HTTPProto == unix
HTTPProto string
// HTTPPort is the TCP port number on which to start the HTTP RPC server. The // HTTPPort is the TCP port number on which to start the HTTP RPC server. The
// default zero value is/ valid and will pick a port number randomly (useful // default zero value is/ valid and will pick a port number randomly (useful
// for ephemeral nodes). // for ephemeral nodes).

View file

@ -28,14 +28,15 @@ import (
) )
const ( const (
DefaultHTTPHost = "localhost" // Default host interface for the HTTP RPC server DefaultHTTPProtocol = "tcp" // Default protocol for the HTTP RPC SERVER
DefaultHTTPPort = 8545 // Default TCP port for the HTTP RPC server DefaultHTTPHost = "localhost" // Default host interface for the HTTP RPC server
DefaultWSHost = "localhost" // Default host interface for the websocket RPC server DefaultHTTPPort = 8545 // Default TCP port for the HTTP RPC server
DefaultWSPort = 8546 // Default TCP port for the websocket RPC server DefaultWSHost = "localhost" // Default host interface for the websocket RPC server
DefaultGraphQLHost = "localhost" // Default host interface for the GraphQL server DefaultWSPort = 8546 // Default TCP port for the websocket RPC server
DefaultGraphQLPort = 8547 // Default TCP port for the GraphQL server DefaultGraphQLHost = "localhost" // Default host interface for the GraphQL server
DefaultAuthHost = "localhost" // Default host interface for the authenticated apis DefaultGraphQLPort = 8547 // Default TCP port for the GraphQL server
DefaultAuthPort = 8551 // Default port for the authenticated apis DefaultAuthHost = "localhost" // Default host interface for the authenticated apis
DefaultAuthPort = 8551 // Default port for the authenticated apis
) )
var ( var (

View file

@ -26,13 +26,13 @@ import (
) )
// StartHTTPEndpoint starts the HTTP RPC endpoint. // StartHTTPEndpoint starts the HTTP RPC endpoint.
func StartHTTPEndpoint(endpoint string, timeouts rpc.HTTPTimeouts, handler http.Handler) (*http.Server, net.Addr, error) { func StartHTTPEndpoint(endpoint string, protocol string, timeouts rpc.HTTPTimeouts, handler http.Handler) (*http.Server, net.Addr, error) {
// start the HTTP listener // start the HTTP listener
var ( var (
listener net.Listener listener net.Listener
err error err error
) )
if listener, err = net.Listen("tcp", endpoint); err != nil { if listener, err = net.Listen(protocol, endpoint); err != nil {
return nil, nil, err return nil, nil, err
} }
// make sure timeout values are meaningful // make sure timeout values are meaningful

View file

@ -404,7 +404,7 @@ func (n *Node) startRPC() error {
) )
initHttp := func(server *httpServer, port int) error { initHttp := func(server *httpServer, port int) error {
if err := server.setListenAddr(n.config.HTTPHost, port); err != nil { if err := server.setListenAddr(n.config.HTTPProto, n.config.HTTPHost, port); err != nil {
return err return err
} }
if err := server.enableRPC(openAPIs, httpConfig{ if err := server.enableRPC(openAPIs, httpConfig{
@ -421,7 +421,7 @@ func (n *Node) startRPC() error {
initWS := func(port int) error { initWS := func(port int) error {
server := n.wsServerForPort(port, false) server := n.wsServerForPort(port, false)
if err := server.setListenAddr(n.config.WSHost, port); err != nil { if err := server.setListenAddr(n.config.HTTPProto, n.config.WSHost, port); err != nil {
return err return err
} }
if err := server.enableWS(openAPIs, wsConfig{ if err := server.enableWS(openAPIs, wsConfig{
@ -438,7 +438,7 @@ func (n *Node) startRPC() error {
initAuth := func(port int, secret []byte) error { initAuth := func(port int, secret []byte) error {
// Enable auth via HTTP // Enable auth via HTTP
server := n.httpAuth server := n.httpAuth
if err := server.setListenAddr(n.config.AuthAddr, port); err != nil { if err := server.setListenAddr(n.config.HTTPProto, n.config.AuthAddr, port); err != nil {
return err return err
} }
if err := server.enableRPC(allAPIs, httpConfig{ if err := server.enableRPC(allAPIs, httpConfig{
@ -453,7 +453,7 @@ func (n *Node) startRPC() error {
servers = append(servers, server) servers = append(servers, server)
// Enable auth via WS // Enable auth via WS
server = n.wsServerForPort(port, true) server = n.wsServerForPort(port, true)
if err := server.setListenAddr(n.config.AuthAddr, port); err != nil { if err := server.setListenAddr(n.config.HTTPProto, n.config.AuthAddr, port); err != nil {
return err return err
} }
if err := server.enableWS(allAPIs, wsConfig{ if err := server.enableWS(allAPIs, wsConfig{

View file

@ -77,6 +77,7 @@ type httpServer struct {
// These are set by setListenAddr. // These are set by setListenAddr.
endpoint string endpoint string
proto string
host string host string
port int port int
@ -97,15 +98,15 @@ func newHTTPServer(log log.Logger, timeouts rpc.HTTPTimeouts) *httpServer {
// setListenAddr configures the listening address of the server. // setListenAddr configures the listening address of the server.
// The address can only be set while the server isn't running. // The address can only be set while the server isn't running.
func (h *httpServer) setListenAddr(host string, port int) error { func (h *httpServer) setListenAddr(proto string, host string, port int) error {
h.mu.Lock() h.mu.Lock()
defer h.mu.Unlock() defer h.mu.Unlock()
if h.listener != nil && (host != h.host || port != h.port) { if h.listener != nil && (host != h.host || port != h.port || proto != h.proto) {
return fmt.Errorf("HTTP server already running on %s", h.endpoint) return fmt.Errorf("HTTP server already running on %s", h.endpoint)
} }
h.host, h.port = host, port h.proto, h.host, h.port = proto, host, port
h.endpoint = fmt.Sprintf("%s:%d", host, port) h.endpoint = fmt.Sprintf("%s:%d", host, port)
return nil return nil
} }
@ -141,7 +142,7 @@ func (h *httpServer) start() error {
} }
// Start the server. // Start the server.
listener, err := net.Listen("tcp", h.endpoint) listener, err := net.Listen(h.proto, h.endpoint)
if err != nil { if err != nil {
// If the server fails to start, we need to clear out the RPC and WS // If the server fails to start, we need to clear out the RPC and WS
// configuration so they can be configured another time. // configuration so they can be configured another time.

View file

@ -246,7 +246,7 @@ func createAndStartServer(t *testing.T, conf *httpConfig, ws bool, wsConf *wsCon
if ws { if ws {
assert.NoError(t, srv.enableWS(nil, *wsConf)) assert.NoError(t, srv.enableWS(nil, *wsConf))
} }
assert.NoError(t, srv.setListenAddr("localhost", 0)) assert.NoError(t, srv.setListenAddr("tcp", "localhost", 0))
assert.NoError(t, srv.start()) assert.NoError(t, srv.start())
return srv return srv
} }