mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 03:30:37 +00:00
Enable h2c for http handler. add https handler for http2 (#8610)
new flag examples. --https.enabled --https.addr="0.0.0.0" --https.port=443 --https.url="unix:///file.wow" --https.cert="keyfile.cert" --https.key="certfile.cert" also adds support for h2c to the http handler - http2 protocol without tls.
This commit is contained in:
parent
c90bff7e22
commit
d8d7d8d5df
@ -194,6 +194,20 @@ If the `--http.url` flag is set, then `--http.addr` and `--http.port` with both
|
||||
|
||||
note that this is NOT geth-style IPC. for that, read the next section, IPC endpoint(geth-compatible)
|
||||
|
||||
|
||||
### HTTPS, HTTP2, and H2C
|
||||
|
||||
Erigon supports HTTPS, HTTP2, and H2C out of the box. H2C is served by the default HTTP handler.
|
||||
|
||||
To enable the HTTPS+HTTP2 server, add flag `--https.enabled`, along with providing flags `-https.cert="/path/to.cert"` and `--https.key=/path/to.key`
|
||||
|
||||
By default, the HTTPS server will run on the HTTP port + 363. use flag `--https.port` to set the port
|
||||
|
||||
The HTTPS server will inherit all other configuration parameters from http, for instance, enabling the websocket server, cors domains, or enabled namespaces
|
||||
|
||||
If the `--https.url` flag is set, then `--https.addr` and `--https.port` with both be ignored.
|
||||
|
||||
|
||||
### IPC endpoint (geth compatible)
|
||||
|
||||
erigon supports the geth-style unix socket IPC. you can enable this with `--socket.enabled` flag,
|
||||
@ -266,7 +280,7 @@ The following table shows the current implementation status of Erigon's RPC daem
|
||||
| eth_getFilterChanges | Yes | |
|
||||
| eth_uninstallFilter | Yes | |
|
||||
| eth_getLogs | Yes | |
|
||||
| | | |
|
||||
| interned spe | | |
|
||||
| eth_accounts | No | deprecated |
|
||||
| eth_sendRawTransaction | Yes | `remote`. |
|
||||
| eth_sendTransaction | - | not yet implemented |
|
||||
|
@ -89,10 +89,6 @@ func RootCommand() (*cobra.Command, *httpcfg.HttpCfg) {
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.PrivateApiAddr, "private.api.addr", "127.0.0.1:9090", "Erigon's components (txpool, rpcdaemon, sentry, downloader, ...) can be deployed as independent Processes on same/another server. Then components will connect to erigon by this internal grpc API. Example: 127.0.0.1:9090")
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.DataDir, "datadir", "", "path to Erigon working directory")
|
||||
rootCmd.PersistentFlags().BoolVar(&cfg.GraphQLEnabled, "graphql", false, "enables graphql endpoint (disabled by default)")
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.HttpListenAddress, "http.addr", nodecfg.DefaultHTTPHost, "HTTP-RPC server listening interface")
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.TLSCertfile, "tls.cert", "", "certificate for client side TLS handshake")
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.TLSKeyFile, "tls.key", "", "key file for client side TLS handshake")
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.TLSCACert, "tls.cacert", "", "CA certificate for client side TLS handshake")
|
||||
rootCmd.PersistentFlags().Uint64Var(&cfg.Gascap, "rpc.gascap", 50_000_000, "Sets a cap on gas that can be used in eth_call/estimateGas")
|
||||
rootCmd.PersistentFlags().Uint64Var(&cfg.MaxTraces, "trace.maxtraces", 200, "Sets a limit on traces that can be returned in trace_filter")
|
||||
|
||||
@ -110,17 +106,29 @@ func RootCommand() (*cobra.Command, *httpcfg.HttpCfg) {
|
||||
rootCmd.PersistentFlags().IntVar(&cfg.GRPCPort, "grpc.port", nodecfg.DefaultGRPCPort, "GRPC server listening port")
|
||||
rootCmd.PersistentFlags().BoolVar(&cfg.GRPCHealthCheckEnabled, "grpc.healthcheck", false, "Enable GRPC health check")
|
||||
rootCmd.PersistentFlags().Float64Var(ðconfig.Defaults.RPCTxFeeCap, utils.RPCGlobalTxFeeCapFlag.Name, utils.RPCGlobalTxFeeCapFlag.Value, utils.RPCGlobalTxFeeCapFlag.Usage)
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.TLSCertfile, "tls.cert", "", "certificate for client side TLS handshake for GRPC")
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.TLSKeyFile, "tls.key", "", "key file for client side TLS handshake for GRPC")
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.TLSCACert, "tls.cacert", "", "CA certificate for client side TLS handshake for GRPC")
|
||||
|
||||
rootCmd.PersistentFlags().StringSliceVar(&cfg.API, "http.api", []string{"eth", "erigon"}, "API's offered over the RPC interface: eth,erigon,web3,net,debug,trace,txpool,db. Supported methods: https://github.com/ledgerwatch/erigon/tree/devel/cmd/rpcdaemon")
|
||||
|
||||
rootCmd.PersistentFlags().BoolVar(&cfg.HttpServerEnabled, "http.enabled", true, "enable http server")
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.HttpListenAddress, "http.addr", nodecfg.DefaultHTTPHost, "HTTP server listening interface")
|
||||
rootCmd.PersistentFlags().IntVar(&cfg.HttpPort, "http.port", nodecfg.DefaultHTTPPort, "HTTP server listening port")
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.HttpURL, "http.url", "", "HTTP server listening url. will OVERRIDE http.addr and http.port. will NOT respect http paths. prefix supported are tcp, unix")
|
||||
rootCmd.PersistentFlags().IntVar(&cfg.HttpPort, "http.port", nodecfg.DefaultHTTPPort, "HTTP-RPC server listening port")
|
||||
rootCmd.PersistentFlags().StringSliceVar(&cfg.HttpCORSDomain, "http.corsdomain", []string{}, "Comma separated list of domains from which to accept cross origin requests (browser enforced)")
|
||||
rootCmd.PersistentFlags().StringSliceVar(&cfg.HttpVirtualHost, "http.vhosts", nodecfg.DefaultConfig.HTTPVirtualHosts, "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.")
|
||||
rootCmd.PersistentFlags().BoolVar(&cfg.HttpCompression, "http.compression", true, "Disable http compression")
|
||||
rootCmd.PersistentFlags().StringSliceVar(&cfg.API, "http.api", []string{"eth", "erigon"}, "API's offered over the HTTP-RPC interface: eth,erigon,web3,net,debug,trace,txpool,db. Supported methods: https://github.com/ledgerwatch/erigon/tree/devel/cmd/rpcdaemon")
|
||||
rootCmd.PersistentFlags().BoolVar(&cfg.WebsocketEnabled, "ws", false, "Enable Websockets - Same port as HTTP")
|
||||
rootCmd.PersistentFlags().BoolVar(&cfg.WebsocketEnabled, "ws", false, "Enable Websockets - Same port as HTTP[S]")
|
||||
rootCmd.PersistentFlags().BoolVar(&cfg.WebsocketCompression, "ws.compression", false, "Enable Websocket compression (RFC 7692)")
|
||||
|
||||
rootCmd.PersistentFlags().BoolVar(&cfg.HttpsServerEnabled, "https.enabled", false, "enable http server")
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.HttpsListenAddress, "https.addr", nodecfg.DefaultHTTPHost, "rpc HTTPS server listening interface")
|
||||
rootCmd.PersistentFlags().IntVar(&cfg.HttpsPort, "https.port", 0, "rpc HTTPS server listening port. default to http+363 if not set")
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.HttpsURL, "https.url", "", "rpc HTTPS server listening url. will OVERRIDE https.addr and https.port. will NOT respect paths. prefix supported are tcp, unix")
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.HttpsCertfile, "https.cert", "", "certificate for rpc HTTPS server")
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.HttpsKeyFile, "https.key", "", "key file for rpc HTTPS server")
|
||||
|
||||
rootCmd.PersistentFlags().BoolVar(&cfg.SocketServerEnabled, "socket.enabled", false, "Enable IPC server")
|
||||
rootCmd.PersistentFlags().StringVar(&cfg.SocketListenUrl, "socket.url", "unix:///var/run/erigon.sock", "IPC server listening url. prefix supported are tcp, unix")
|
||||
|
||||
@ -610,24 +618,25 @@ func startRegularRpcServer(ctx context.Context, cfg httpcfg.HttpCfg, rpcAPI []rp
|
||||
logger.Info("Socket Endpoint opened", "url", socketUrl)
|
||||
}
|
||||
|
||||
if cfg.HttpServerEnabled {
|
||||
httpHandler := node.NewHTTPHandlerStack(srv, cfg.HttpCORSDomain, cfg.HttpVirtualHost, cfg.HttpCompression)
|
||||
var wsHandler http.Handler
|
||||
if cfg.WebsocketEnabled {
|
||||
wsHandler = srv.WebsocketHandler([]string{"*"}, nil, cfg.WebsocketCompression, logger)
|
||||
}
|
||||
|
||||
graphQLHandler := graphql.CreateHandler(defaultAPIList)
|
||||
|
||||
apiHandler, err := createHandler(cfg, defaultAPIList, httpHandler, wsHandler, graphQLHandler, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cfg.HttpServerEnabled {
|
||||
httpEndpoint := fmt.Sprintf("tcp://%s:%d", cfg.HttpListenAddress, cfg.HttpPort)
|
||||
if cfg.HttpURL != "" {
|
||||
httpEndpoint = cfg.HttpURL
|
||||
}
|
||||
listener, httpAddr, err := node.StartHTTPEndpoint(httpEndpoint, cfg.HTTPTimeouts, apiHandler)
|
||||
listener, httpAddr, err := node.StartHTTPEndpoint(httpEndpoint, &node.HttpEndpointConfig{
|
||||
Timeouts: cfg.HTTPTimeouts,
|
||||
}, apiHandler)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not start RPC api: %w", err)
|
||||
}
|
||||
@ -639,6 +648,34 @@ func startRegularRpcServer(ctx context.Context, cfg httpcfg.HttpCfg, rpcAPI []rp
|
||||
logger.Info("HTTP endpoint closed", "url", httpAddr)
|
||||
}()
|
||||
}
|
||||
if cfg.HttpsURL != "" {
|
||||
cfg.HttpsServerEnabled = true
|
||||
}
|
||||
if cfg.HttpsServerEnabled {
|
||||
if cfg.HttpsPort == 0 {
|
||||
cfg.HttpsPort = cfg.HttpPort + 363
|
||||
}
|
||||
httpsEndpoint := fmt.Sprintf("tcp://%s:%d", cfg.HttpsListenAddress, cfg.HttpsPort)
|
||||
if cfg.HttpsURL != "" {
|
||||
httpsEndpoint = cfg.HttpsURL
|
||||
}
|
||||
listener, httpAddr, err := node.StartHTTPEndpoint(httpsEndpoint, &node.HttpEndpointConfig{
|
||||
Timeouts: cfg.HTTPTimeouts,
|
||||
HTTPS: true,
|
||||
CertFile: cfg.HttpsCertfile,
|
||||
KeyFile: cfg.HttpsKeyFile,
|
||||
}, apiHandler)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not start RPC api: %w", err)
|
||||
}
|
||||
info = append(info, "https.url", httpAddr)
|
||||
defer func() {
|
||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
_ = listener.Shutdown(shutdownCtx)
|
||||
logger.Info("HTTPS endpoint closed", "url", httpAddr)
|
||||
}()
|
||||
}
|
||||
|
||||
var (
|
||||
healthServer *grpcHealth.Server
|
||||
@ -797,7 +834,9 @@ func createEngineListener(cfg httpcfg.HttpCfg, engineApi []rpc.API, logger log.L
|
||||
return nil, nil, "", err
|
||||
}
|
||||
|
||||
engineListener, engineAddr, err := node.StartHTTPEndpoint(engineHttpEndpoint, cfg.AuthRpcTimeouts, engineApiHandler)
|
||||
engineListener, engineAddr, err := node.StartHTTPEndpoint(engineHttpEndpoint, &node.HttpEndpointConfig{
|
||||
Timeouts: cfg.AuthRpcTimeouts,
|
||||
}, engineApiHandler)
|
||||
if err != nil {
|
||||
return nil, nil, "", fmt.Errorf("could not start RPC api: %w", err)
|
||||
}
|
||||
|
@ -30,6 +30,13 @@ type HttpCfg struct {
|
||||
AuthRpcVirtualHost []string
|
||||
HttpCompression bool
|
||||
|
||||
HttpsServerEnabled bool
|
||||
HttpsURL string
|
||||
HttpsListenAddress string
|
||||
HttpsPort int
|
||||
HttpsCertfile string
|
||||
HttpsKeyFile string
|
||||
|
||||
AuthRpcPort int
|
||||
PrivateApiAddr string
|
||||
|
||||
|
@ -305,7 +305,12 @@ var (
|
||||
}
|
||||
HTTPEnabledFlag = cli.BoolFlag{
|
||||
Name: "http",
|
||||
Usage: "HTTP-RPC server (enabled by default). Use --http=false to disable it",
|
||||
Usage: "JSON-RPC server (enabled by default). Use --http=false to disable it",
|
||||
Value: true,
|
||||
}
|
||||
HTTPServerEnabledFlag = cli.BoolFlag{
|
||||
Name: "http.enabled",
|
||||
Usage: "JSON-RPC HTTP server (enabled by default). Use --http.enabled=false to disable it",
|
||||
Value: true,
|
||||
}
|
||||
HTTPListenAddrFlag = cli.StringFlag{
|
||||
|
@ -29,10 +29,73 @@ import (
|
||||
"github.com/ledgerwatch/erigon/rpc"
|
||||
"github.com/ledgerwatch/erigon/rpc/rpccfg"
|
||||
"github.com/ledgerwatch/log/v3"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/h2c"
|
||||
)
|
||||
|
||||
type HttpEndpointConfig struct {
|
||||
Timeouts rpccfg.HTTPTimeouts
|
||||
HTTPS bool
|
||||
CertFile string
|
||||
KeyFile string
|
||||
}
|
||||
|
||||
// StartHTTPEndpoint starts the HTTP RPC endpoint.
|
||||
func StartHTTPEndpoint(urlEndpoint string, timeouts rpccfg.HTTPTimeouts, handler http.Handler) (*http.Server, net.Addr, error) {
|
||||
func StartHTTPEndpoint(urlEndpoint string, cfg *HttpEndpointConfig, handler http.Handler) (*http.Server, net.Addr, error) {
|
||||
// start the HTTP listener
|
||||
var (
|
||||
listener net.Listener
|
||||
err error
|
||||
)
|
||||
socketUrl, err := url.Parse(urlEndpoint)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("malformatted http listen url %s: %w", urlEndpoint, err)
|
||||
}
|
||||
if listener, err = net.Listen(socketUrl.Scheme, socketUrl.Host+socketUrl.EscapedPath()); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// make sure timeout values are meaningful
|
||||
CheckTimeouts(&cfg.Timeouts)
|
||||
// create the http2 server for handling h2c
|
||||
h2 := &http2.Server{}
|
||||
// enable h2c support
|
||||
handler = h2c.NewHandler(handler, h2)
|
||||
// Bundle the http server
|
||||
httpSrv := &http.Server{
|
||||
Handler: handler,
|
||||
ReadTimeout: cfg.Timeouts.ReadTimeout,
|
||||
WriteTimeout: cfg.Timeouts.WriteTimeout,
|
||||
IdleTimeout: cfg.Timeouts.IdleTimeout,
|
||||
ReadHeaderTimeout: cfg.Timeouts.ReadTimeout,
|
||||
}
|
||||
// start the HTTP server
|
||||
go func() {
|
||||
var serveErr error
|
||||
if cfg.HTTPS {
|
||||
serveErr = httpSrv.ServeTLS(listener, cfg.CertFile, cfg.KeyFile)
|
||||
if serveErr != nil && !isIgnoredHttpServerError(serveErr) {
|
||||
log.Warn("Failed to serve https endpoint", "err", serveErr)
|
||||
}
|
||||
} else {
|
||||
serveErr = httpSrv.Serve(listener)
|
||||
if serveErr != nil && !isIgnoredHttpServerError(serveErr) {
|
||||
log.Warn("Failed to serve http endpoint", "err", serveErr)
|
||||
}
|
||||
}
|
||||
}()
|
||||
return httpSrv, listener.Addr(), err
|
||||
}
|
||||
|
||||
func isIgnoredHttpServerError(serveErr error) bool {
|
||||
return (errors.Is(serveErr, context.Canceled) || errors.Is(serveErr, libcommon.ErrStopped) || errors.Is(serveErr, http.ErrServerClosed))
|
||||
|
||||
}
|
||||
|
||||
// StartHTTPEndpoint starts the HTTP RPC endpoint.
|
||||
func StartHTTPSEndpoint(urlEndpoint string,
|
||||
keyFile string, certFile string,
|
||||
timeouts rpccfg.HTTPTimeouts, handler http.Handler,
|
||||
) (*http.Server, net.Addr, error) {
|
||||
// start the HTTP listener
|
||||
var (
|
||||
listener net.Listener
|
||||
@ -47,7 +110,11 @@ func StartHTTPEndpoint(urlEndpoint string, timeouts rpccfg.HTTPTimeouts, handler
|
||||
}
|
||||
// make sure timeout values are meaningful
|
||||
CheckTimeouts(&timeouts)
|
||||
// Bundle and start the HTTP server
|
||||
// create the http2 server for handling h2c
|
||||
h2 := &http2.Server{}
|
||||
// enable h2c support
|
||||
handler = h2c.NewHandler(handler, h2)
|
||||
// Bundle the http server
|
||||
httpSrv := &http.Server{
|
||||
Handler: handler,
|
||||
ReadTimeout: timeouts.ReadTimeout,
|
||||
@ -55,8 +122,9 @@ func StartHTTPEndpoint(urlEndpoint string, timeouts rpccfg.HTTPTimeouts, handler
|
||||
IdleTimeout: timeouts.IdleTimeout,
|
||||
ReadHeaderTimeout: timeouts.ReadTimeout,
|
||||
}
|
||||
// start the HTTP server
|
||||
go func() {
|
||||
serveErr := httpSrv.Serve(listener)
|
||||
serveErr := httpSrv.ServeTLS(listener, certFile, keyFile)
|
||||
if serveErr != nil &&
|
||||
!(errors.Is(serveErr, context.Canceled) || errors.Is(serveErr, libcommon.ErrStopped) || errors.Is(serveErr, http.ErrServerClosed)) {
|
||||
log.Warn("Failed to serve http endpoint", "err", serveErr)
|
||||
|
@ -51,6 +51,7 @@ var DefaultFlags = []cli.Flag{
|
||||
&BadBlockFlag,
|
||||
|
||||
&utils.HTTPEnabledFlag,
|
||||
&utils.HTTPServerEnabledFlag,
|
||||
&utils.GraphQLEnabledFlag,
|
||||
&utils.HTTPListenAddrFlag,
|
||||
&utils.HTTPPortFlag,
|
||||
|
@ -2,9 +2,10 @@ package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ledgerwatch/erigon-lib/common/hexutil"
|
||||
"time"
|
||||
|
||||
"github.com/ledgerwatch/erigon-lib/common/hexutil"
|
||||
|
||||
"github.com/ledgerwatch/erigon-lib/txpool/txpoolcfg"
|
||||
|
||||
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
||||
@ -357,6 +358,7 @@ func setEmbeddedRpcDaemon(ctx *cli.Context, cfg *nodecfg.Config, logger log.Logg
|
||||
|
||||
c := &httpcfg.HttpCfg{
|
||||
Enabled: ctx.Bool(utils.HTTPEnabledFlag.Name),
|
||||
HttpServerEnabled: ctx.Bool(utils.HTTPServerEnabledFlag.Name),
|
||||
Dirs: cfg.Dirs,
|
||||
|
||||
TLSKeyFile: cfg.TLSKeyFile,
|
||||
|
Loading…
Reference in New Issue
Block a user