Skip to content

Commit

Permalink
only allow users to specify prefix, specify / to allow all paths (e…
Browse files Browse the repository at this point in the history
  • Loading branch information
renaynay committed Jan 25, 2021
1 parent 5c6b70b commit 8309550
Show file tree
Hide file tree
Showing 10 changed files with 309 additions and 103 deletions.
4 changes: 2 additions & 2 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ var (
utils.GraphQLCORSDomainFlag,
utils.GraphQLVirtualHostsFlag,
utils.HTTPApiFlag,
utils.HTTPPathFlag,
utils.HTTPPathPrefixFlag,
utils.LegacyRPCApiFlag,
utils.WSEnabledFlag,
utils.WSListenAddrFlag,
Expand All @@ -189,7 +189,7 @@ var (
utils.WSApiFlag,
utils.LegacyWSApiFlag,
utils.WSAllowedOriginsFlag,
utils.WSPathFlag,
utils.WSPathPrefixFlag,
utils.LegacyWSAllowedOriginsFlag,
utils.IPCDisabledFlag,
utils.IPCPathFlag,
Expand Down
4 changes: 2 additions & 2 deletions cmd/geth/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,14 @@ var AppHelpFlagGroups = []flags.FlagGroup{
utils.HTTPListenAddrFlag,
utils.HTTPPortFlag,
utils.HTTPApiFlag,
utils.HTTPPathFlag,
utils.HTTPPathPrefixFlag,
utils.HTTPCORSDomainFlag,
utils.HTTPVirtualHostsFlag,
utils.WSEnabledFlag,
utils.WSListenAddrFlag,
utils.WSPortFlag,
utils.WSApiFlag,
utils.WSPathFlag,
utils.WSPathPrefixFlag,
utils.WSAllowedOriginsFlag,
utils.GraphQLEnabledFlag,
utils.GraphQLCORSDomainFlag,
Expand Down
28 changes: 14 additions & 14 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,10 +532,10 @@ var (
Usage: "API's offered over the HTTP-RPC interface",
Value: "",
}
HTTPPathFlag = cli.StringFlag{
Name: "http.path",
Usage: "Path on which to mount the http server. Default value is root",
Value: "/",
HTTPPathPrefixFlag = cli.StringFlag{
Name: "http.prefix",
Usage: "Specify a path prefix on which to mount the http-rpc server. Specify '/' to allow any path.",
Value: "",
}
GraphQLEnabledFlag = cli.BoolFlag{
Name: "graphql",
Expand Down Expand Up @@ -575,10 +575,10 @@ var (
Usage: "Origins from which to accept websockets requests",
Value: "",
}
WSPathFlag = cli.StringFlag{
Name: "ws.path",
Usage: "Path on which to mount the ws server. Default value is root",
Value: "/",
WSPathPrefixFlag = cli.StringFlag{
Name: "ws.prefix",
Usage: "Specify a path prefix on which to mount the ws-rpc server. Specify '/' to allow any path.",
Value: "",
}
ExecFlag = cli.StringFlag{
Name: "exec",
Expand Down Expand Up @@ -966,10 +966,10 @@ func setHTTP(ctx *cli.Context, cfg *node.Config) {
cfg.HTTPVirtualHosts = SplitAndTrim(ctx.GlobalString(HTTPVirtualHostsFlag.Name))
}

if ctx.GlobalIsSet(HTTPPathFlag.Name) {
cfg.HTTPPath = ctx.GlobalString(HTTPPathFlag.Name)
if ctx.GlobalIsSet(HTTPPathPrefixFlag.Name) {
cfg.HTTPPathPrefix = ctx.GlobalString(HTTPPathPrefixFlag.Name)
} else {
cfg.HTTPPath = HTTPPathFlag.Value
cfg.HTTPPathPrefix = HTTPPathPrefixFlag.Value
}
}

Expand Down Expand Up @@ -1021,10 +1021,10 @@ func setWS(ctx *cli.Context, cfg *node.Config) {
cfg.WSModules = SplitAndTrim(ctx.GlobalString(WSApiFlag.Name))
}

if ctx.GlobalIsSet(WSPathFlag.Name) {
cfg.WSPath = ctx.GlobalString(WSPathFlag.Name)
if ctx.GlobalIsSet(WSPathPrefixFlag.Name) {
cfg.WSPathPrefix = ctx.GlobalString(WSPathPrefixFlag.Name)
} else {
cfg.WSPath = WSPathFlag.Value
cfg.WSPathPrefix = WSPathPrefixFlag.Value
}
}

Expand Down
20 changes: 10 additions & 10 deletions node/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,11 @@ func (api *privateAdminAPI) StartRPC(host *string, port *int, path *string, cors
port = &api.node.config.HTTPPort
}

// Check if path set on which to mount http handler
// Check if prefix set on which to mount http handler
if path == nil {
p := "/"
if api.node.config.HTTPPath != "" {
p = api.node.config.HTTPPath
p := ""
if api.node.config.HTTPPathPrefix != "" {
p = api.node.config.HTTPPathPrefix
}
path = &p
}
Expand All @@ -193,7 +193,7 @@ func (api *privateAdminAPI) StartRPC(host *string, port *int, path *string, cors
CorsAllowedOrigins: api.node.config.HTTPCors,
Vhosts: api.node.config.HTTPVirtualHosts,
Modules: api.node.config.HTTPModules,
path: *path,
prefix: prettyPath(*path),
}
if cors != nil {
config.CorsAllowedOrigins = nil
Expand Down Expand Up @@ -249,11 +249,11 @@ func (api *privateAdminAPI) StartWS(host *string, port *int, path *string, allow
port = &api.node.config.WSPort
}

// Check if path set on which to mount ws handler
// Check if prefix set on which to mount ws handler
if path == nil {
p := "/"
if api.node.config.WSPath != "" {
p = api.node.config.WSPath
p := ""
if api.node.config.WSPathPrefix != "" {
p = api.node.config.WSPathPrefix
}
path = &p
}
Expand All @@ -262,7 +262,7 @@ func (api *privateAdminAPI) StartWS(host *string, port *int, path *string, allow
config := wsConfig{
Modules: api.node.config.WSModules,
Origins: api.node.config.WSOrigins,
path: *path,
prefix: prettyPath(*path),
// ExposeAll: api.node.config.WSExposeAll,
}
if apis != nil {
Expand Down
8 changes: 4 additions & 4 deletions node/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ func TestStartRPC(t *testing.T) {
}
}

// TestRPC_OnPath tests whether RPC will be handled on a custom path.
// TestRPC_OnPath tests whether RPC will be handled on a custom path prefix.
func TestRPC_OnPath(t *testing.T) {
// Create Node.
stack, err := New(&Config{
Expand All @@ -314,7 +314,7 @@ func TestRPC_OnPath(t *testing.T) {

api := &privateAdminAPI{stack}

paths := []string{"/test", "/testtesttest", "/t", "/"}
paths := []string{"/test", "/testtesttest", "/t", ""}

for _, path := range paths {
_, err := api.StartRPC(sp("127.0.0.1"), ip(0), sp(path), nil, nil, nil)
Expand All @@ -330,7 +330,7 @@ func TestRPC_OnPath(t *testing.T) {
}
}

// TestWS_OnPath tests whether RPC will be handled on a custom path.
// TestWS_OnPath tests whether WS-RPC will be handled on a custom path prefix.
func TestWS_OnPath(t *testing.T) {
// Create Node.
stack, err := New(&Config{
Expand All @@ -350,7 +350,7 @@ func TestWS_OnPath(t *testing.T) {

api := &privateAdminAPI{stack}

paths := []string{"/test", "/testtesttest", "/t", "/"}
paths := []string{"/test", "/testtesttest", "/t", ""}

for _, path := range paths {
_, err := api.StartWS(sp("127.0.0.1"), ip(0), sp(path), nil, nil)
Expand Down
10 changes: 4 additions & 6 deletions node/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,8 @@ type Config struct {
// interface.
HTTPTimeouts rpc.HTTPTimeouts

// HTTPPath specifies a path on which http-rpc is to be served. The default is the
// root path.
HTTPPath string `toml:",omitempty"`
// HTTPPathPrefix specifies a path prefix on which http-rpc is to be served.
HTTPPathPrefix string `toml:",omitempty"`

// WSHost is the host interface on which to start the websocket RPC server. If
// this field is empty, no websocket API endpoint will be started.
Expand All @@ -152,9 +151,8 @@ type Config struct {
// ephemeral nodes).
WSPort int `toml:",omitempty"`

// WSPath specifies a path on which ws-rpc is to be served. The default is the
// root path.
WSPath string `toml:",omitempty"`
// WSPathPrefix specifies a path prefix on which ws-rpc is to be served.
WSPathPrefix string `toml:",omitempty"`

// WSOrigins is the list of domain to accept websocket requests from. Please be
// aware that the server can only act upon the HTTP request the client sends and
Expand Down
18 changes: 8 additions & 10 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,15 +342,14 @@ func (n *Node) startRPC() error {

// Configure HTTP.
if n.config.HTTPHost != "" {
// set the path on which to mount the handler
if n.config.HTTPPath == "" {
n.config.HTTPPath = "/"
}
// make sure the prefix on which to mount the handler is acceptable
prefix := prettyPath(n.config.HTTPPathPrefix)

config := httpConfig{
CorsAllowedOrigins: n.config.HTTPCors,
Vhosts: n.config.HTTPVirtualHosts,
Modules: n.config.HTTPModules,
path: n.config.HTTPPath,
prefix: prefix,
}
if err := n.http.setListenAddr(n.config.HTTPHost, n.config.HTTPPort); err != nil {
return err
Expand All @@ -363,14 +362,13 @@ func (n *Node) startRPC() error {
// Configure WebSocket.
if n.config.WSHost != "" {
server := n.wsServerForPort(n.config.WSPort)
// set the path on which to mount the handler
if n.config.WSPath == "" {
n.config.WSPath = "/"
}
// make sure the prefix on which to mount the handler is acceptable
prefix := prettyPath(n.config.WSPathPrefix)

config := wsConfig{
Modules: n.config.WSModules,
Origins: n.config.WSOrigins,
path: n.config.WSPath,
prefix: prefix,
}
if err := server.setListenAddr(n.config.WSHost, n.config.WSPort); err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion node/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ func TestLifecycleTerminationGuarantee(t *testing.T) {
}

// Tests whether a handler can be successfully mounted on the canonical HTTP server
// on the given path
// on the given prefix
func TestRegisterHandler_Successful(t *testing.T) {
node := createNode(t, 7878, 7979)

Expand Down
40 changes: 25 additions & 15 deletions node/rpcstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ type httpConfig struct {
Modules []string
CorsAllowedOrigins []string
Vhosts []string
path string // path on which to mount http handler
prefix string // path prefix on which to mount http handler
}

// wsConfig is the JSON-RPC/Websocket configuration
type wsConfig struct {
Origins []string
Modules []string
path string // path on which to mount ws handler
prefix string // path prefix on which to mount ws handler
}

type rpcHandler struct {
Expand Down Expand Up @@ -176,18 +176,15 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// check if ws request and serve if ws enabled
ws := h.wsHandler.Load().(*rpcHandler)
if ws != nil && isWebsocket(r) {
if checkPath(r, h.wsConfig.path) {
if checkPath(r, h.wsConfig.prefix) {
ws.ServeHTTP(w, r)
return
}
return
}
// if http-rpc is enabled, try to serve request
rpc := h.httpHandler.Load().(*rpcHandler)
if rpc != nil {
if checkPath(r, h.httpConfig.path) {
rpc.ServeHTTP(w, r)
return
}
// First try to route in the mux.
// Requests to a path below root are handled by the mux,
// which has all the handlers registered via Node.RegisterHandler.
// These are made available when RPC is enabled.
Expand All @@ -196,18 +193,31 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
muxHandler.ServeHTTP(w, r)
return
}

if checkPath(r, h.httpConfig.prefix) {
rpc.ServeHTTP(w, r)
return
}
}
w.WriteHeader(404)
w.WriteHeader(http.StatusNotFound)
}

// checkPath checks whether a request path matches a given path or path prefix.
// checkPath checks whether a given request URL matches a given path prefix.
func checkPath(r *http.Request, path string) bool {
// if the path is root and the request URI is below root,
// return false and fall through to mux
if path == "/" {
return r.RequestURI == "/"
// if no prefix has been specified, request URL must be on root
if path == "" {
return r.URL.Path == "/"
}
// otherwise, check to make sure prefix matches
return len(r.URL.Path) >= len(path) && r.URL.Path[:len(path)] == path
}

// prettyPath returns an acceptable path prefix on which to mount an rpc handler.
func prettyPath(path string) string {
if path != "" && strings.Split(path, "")[0] != "/" {
return "/" + path
}
return len(r.RequestURI) >= len(path) && r.RequestURI[:len(path)] == path
return path
}

// stop shuts down the HTTP server.
Expand Down
Loading

0 comments on commit 8309550

Please sign in to comment.