diff --git a/cmd/XDC/main.go b/cmd/XDC/main.go index 4cf2cb6cfd..2117ddd5ce 100644 --- a/cmd/XDC/main.go +++ b/cmd/XDC/main.go @@ -138,6 +138,7 @@ var ( utils.RPCEnabledFlag, utils.RPCListenAddrFlag, utils.RPCPortFlag, + utils.RPCHttpWriteTimeoutFlag, utils.RPCApiFlag, utils.WSEnabledFlag, utils.WSListenAddrFlag, diff --git a/cmd/XDC/usage.go b/cmd/XDC/usage.go index 5390dd65c9..e6b2fc961f 100644 --- a/cmd/XDC/usage.go +++ b/cmd/XDC/usage.go @@ -145,6 +145,7 @@ var AppHelpFlagGroups = []flagGroup{ utils.RPCEnabledFlag, utils.RPCListenAddrFlag, utils.RPCPortFlag, + utils.RPCHttpWriteTimeoutFlag, utils.RPCApiFlag, utils.WSEnabledFlag, utils.WSListenAddrFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index e3d14b6fcf..aa90af9ae7 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -406,6 +406,11 @@ var ( Usage: "HTTP-RPC server listening port", Value: node.DefaultHTTPPort, } + RPCHttpWriteTimeoutFlag = cli.DurationFlag{ + Name: "rpcwritetimeout", + Usage: "HTTP-RPC server write timeout (default = 10s)", + Value: node.DefaultHTTPWriteTimeOut, + } RPCCORSDomainFlag = cli.StringFlag{ Name: "rpccorsdomain", Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", @@ -735,6 +740,9 @@ func setHTTP(ctx *cli.Context, cfg *node.Config) { if ctx.GlobalIsSet(RPCPortFlag.Name) { cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name) } + if ctx.GlobalIsSet(RPCHttpWriteTimeoutFlag.Name) { + cfg.HTTPWriteTimeout = ctx.GlobalDuration(RPCHttpWriteTimeoutFlag.Name) + } if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) { cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name)) } diff --git a/node/config.go b/node/config.go index ecda8ac9d9..5700b832bf 100644 --- a/node/config.go +++ b/node/config.go @@ -24,6 +24,7 @@ import ( "path/filepath" "runtime" "strings" + "time" "github.com/XinFinOrg/XDPoSChain/accounts" "github.com/XinFinOrg/XDPoSChain/accounts/keystore" @@ -100,6 +101,9 @@ type Config struct { // for ephemeral nodes). HTTPPort int `toml:",omitempty"` + // HTTPWriteTimeout is the write timeout for the HTTP RPC server. + HTTPWriteTimeout time.Duration `toml:",omitempty"` + // HTTPCors is the Cross-Origin Resource Sharing header to send to requesting // clients. Please be aware that CORS is a browser enforced security, it's fully // useless for custom HTTP clients. diff --git a/node/defaults.go b/node/defaults.go index e42b266fba..f9f4f8f268 100644 --- a/node/defaults.go +++ b/node/defaults.go @@ -21,22 +21,25 @@ import ( "os/user" "path/filepath" "runtime" + "time" "github.com/XinFinOrg/XDPoSChain/p2p" "github.com/XinFinOrg/XDPoSChain/p2p/nat" ) const ( - DefaultHTTPHost = "localhost" // Default host interface for the HTTP RPC server - DefaultHTTPPort = 8545 // Default TCP port for the HTTP RPC server - DefaultWSHost = "localhost" // Default host interface for the websocket RPC server - DefaultWSPort = 8546 // Default TCP port for the websocket RPC server + DefaultHTTPHost = "localhost" // Default host interface for the HTTP RPC server + DefaultHTTPPort = 8545 // Default TCP port for the HTTP RPC server + DefaultHTTPWriteTimeOut = 10 * time.Second // Default write timeout for the HTTP RPC server + DefaultWSHost = "localhost" // Default host interface for the websocket RPC server + DefaultWSPort = 8546 // Default TCP port for the websocket RPC server ) // DefaultConfig contains reasonable default settings. var DefaultConfig = Config{ DataDir: DefaultDataDir(), HTTPPort: DefaultHTTPPort, + HTTPWriteTimeout: DefaultHTTPWriteTimeOut, HTTPModules: []string{"net", "web3"}, HTTPVirtualHosts: []string{"localhost"}, WSPort: DefaultWSPort, diff --git a/node/node.go b/node/node.go index 08d8be3450..c543289137 100644 --- a/node/node.go +++ b/node/node.go @@ -26,9 +26,8 @@ import ( "strings" "sync" - "github.com/XinFinOrg/XDPoSChain/core/rawdb" - "github.com/XinFinOrg/XDPoSChain/accounts" + "github.com/XinFinOrg/XDPoSChain/core/rawdb" "github.com/XinFinOrg/XDPoSChain/ethdb" "github.com/XinFinOrg/XDPoSChain/event" "github.com/XinFinOrg/XDPoSChain/internal/debug" @@ -396,7 +395,7 @@ func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors if listener, err = net.Listen("tcp", endpoint); err != nil { return err } - go rpc.NewHTTPServer(cors, vhosts, handler).Serve(listener) + go rpc.NewHTTPServer(cors, vhosts, handler, n.config.HTTPWriteTimeout).Serve(listener) n.log.Info("HTTP endpoint opened", "url", fmt.Sprintf("http://%s", endpoint), "cors", strings.Join(cors, ","), "vhosts", strings.Join(vhosts, ",")) // All listeners booted successfully n.httpEndpoint = endpoint diff --git a/rpc/http.go b/rpc/http.go index a68b4dfe85..de988c2211 100644 --- a/rpc/http.go +++ b/rpc/http.go @@ -32,6 +32,7 @@ import ( "sync" "time" + "github.com/XinFinOrg/XDPoSChain/log" "github.com/rs/cors" ) @@ -230,14 +231,15 @@ func (t *httpServerConn) SetWriteDeadline(time.Time) error { return nil } // NewHTTPServer creates a new HTTP RPC server around an API provider. // // Deprecated: Server implements http.Handler -func NewHTTPServer(cors []string, vhosts []string, srv *Server) *http.Server { +func NewHTTPServer(cors []string, vhosts []string, srv *Server, writeTimeout time.Duration) *http.Server { // Wrap the CORS-handler within a host-handler handler := newCorsHandler(srv, cors) handler = newVHostHandler(vhosts, handler) + log.Info("NewHTTPServer", "writeTimeout", writeTimeout) return &http.Server{ Handler: handler, ReadTimeout: 5 * time.Second, - WriteTimeout: 10 * time.Second, + WriteTimeout: writeTimeout, IdleTimeout: 120 * time.Second, } }