Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cors: add a flag for cors #5671

Merged
merged 8 commits into from
Feb 21, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions client/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ const (
FlagKeyringBackend = "keyring-backend"
FlagPage = "page"
FlagLimit = "limit"
FlagUnsafeCORS = "unsafe-cors"
)

// LineBreak can be included in a command list to provide a blank line
Expand Down Expand Up @@ -141,6 +142,7 @@ func RegisterRestServerFlags(cmd *cobra.Command) *cobra.Command {
cmd.Flags().Uint(FlagMaxOpenConnections, 1000, "The number of maximum open connections")
cmd.Flags().Uint(FlagRPCReadTimeout, 10, "The RPC read timeout (in seconds)")
cmd.Flags().Uint(FlagRPCWriteTimeout, 10, "The RPC write timeout (in seconds)")
cmd.Flags().Bool(FlagUnsafeCORS, false, "The RPC cors are disabled by default")
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved

return cmd
}
Expand Down
12 changes: 10 additions & 2 deletions client/lcd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"time"

"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/rakyll/statik/fs"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -46,7 +47,7 @@ func NewRestServer(cdc *codec.Codec) *RestServer {
}

// Start starts the rest server
func (rs *RestServer) Start(listenAddr string, maxOpen int, readTimeout, writeTimeout uint) (err error) {
func (rs *RestServer) Start(listenAddr string, maxOpen int, readTimeout, writeTimeout uint, cors bool) (err error) {
server.TrapSignal(func() {
err := rs.listener.Close()
rs.log.Error("error closing listener", "err", err)
Expand All @@ -68,7 +69,12 @@ func (rs *RestServer) Start(listenAddr string, maxOpen int, readTimeout, writeTi
),
)

return rpcserver.StartHTTPServer(rs.listener, rs.Mux, rs.log, cfg)
var h http.Handler = rs.Mux
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
var h http.Handler = rs.Mux
h := rs.Mux

if cors {
h = handlers.CORS()(h)
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved
}

return rpcserver.StartHTTPServer(rs.listener, h, rs.log, cfg)
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved
}

// ServeCommand will start the application REST service as a blocking process. It
Expand All @@ -90,12 +96,14 @@ func ServeCommand(cdc *codec.Codec, registerRoutesFn func(*RestServer)) *cobra.C
viper.GetInt(flags.FlagMaxOpenConnections),
uint(viper.GetInt(flags.FlagRPCReadTimeout)),
uint(viper.GetInt(flags.FlagRPCWriteTimeout)),
viper.GetBool(flags.FlagUnsafeCORS),
)

return err
},
}

cmd.Flags().Bool(flags.FlagUnsafeCORS, false, "Allows CORS requests from all domains")
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved
return flags.RegisterRestServerFlags(cmd)
}

Expand Down
33 changes: 22 additions & 11 deletions docs/interfaces/rest.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ synopsis: "This document describes how to create a REST interface for an SDK **a

## Prerequisites {hide}

* [Query Lifecycle](./query-lifecycle.md) {prereq}
* [Application CLI](./cli.md) {prereq}
- [Query Lifecycle](./query-lifecycle.md) {prereq}
- [Application CLI](./cli.md) {prereq}

## Application REST Interface
## Application REST Interface

Building the REST Interface for an application is done by [aggregating REST Routes](#registering-routes) defined in the application's modules. This interface is served by a REST Server [REST server](#rest-server), which route requests and output responses in the application itself. The SDK comes with its own REST Server by default. To enable it, the `rest.ServeCommand` command needs to be added as a subcommand of the `rootCmd` in the `main()` function of the [CLI interface](./cli.md):

Expand All @@ -24,27 +24,27 @@ Users will then be able to use the application CLI to start a new REST server, a
appcli rest-server --chain-id <chainID> --trust-node
```

Note that if `trust-node` is set to `false`, the REST server will verify the query proof against the merkle root (contained in the block header).
Note that if `trust-node` is set to `false`, the REST server will verify the query proof against the merkle root (contained in the block header).

## REST Server

A REST Server is used to receive and route HTTP Requests, obtain the results from the application, and return a response to the user. The REST Server defined by the SDK `rest` package contains the following:

* **Router:** A router for HTTP requests. A new router can be instantiated for an application and used to match routes based on path, request method, headers, etc. The SDK uses the [Gorilla Mux Router](https://github.com/gorilla/mux).
* **CLIContext:** A [`CLIContext`](./query-lifecycle.md#clicontext) created for a user interaction.
* **Keybase:** A [Keybase](../basics/accounts.md#keybase) is a key manager.
* **Logger:** A logger from Tendermint `Log`, a log package structured around key-value pairs that allows logging level to be set differently for different keys. The logger takes `Debug()`, `Info()`, and `Error()`s.
* **Listener:** A [listener](https://golang.org/pkg/net/#Listener) from the net package.
- **Router:** A router for HTTP requests. A new router can be instantiated for an application and used to match routes based on path, request method, headers, etc. The SDK uses the [Gorilla Mux Router](https://github.com/gorilla/mux).
- **CLIContext:** A [`CLIContext`](./query-lifecycle.md#clicontext) created for a user interaction.
- **Keybase:** A [Keybase](../basics/accounts.md#keybase) is a key manager.
- **Logger:** A logger from Tendermint `Log`, a log package structured around key-value pairs that allows logging level to be set differently for different keys. The logger takes `Debug()`, `Info()`, and `Error()`s.
- **Listener:** A [listener](https://golang.org/pkg/net/#Listener) from the net package.

Of the five, the only attribute that application developers need interact with is the `router`: they need to add routes to it so that the REST server can properly handle queries. See the next section for more information on registering routes.
Of the five, the only attribute that application developers need interact with is the `router`: they need to add routes to it so that the REST server can properly handle queries. See the next section for more information on registering routes.

In order to enable the REST Server in an SDK application, the `rest.ServeCommand` needs to be added to the application's command-line interface. See the [above section](#application-rest-interface) for more information.

## Registering Routes

To include routes for each module in an application, the CLI must have some kind of function to register routes in its REST Server. This function is called `RegisterRoutes()`, and is utilized by the `ServeCommand` and must include routes for each of the application's modules. Since each module used by an SDK application implements a [`RegisterRESTRoutes`](../building-modules/module-interfaces.md#rest) function, application developers simply use the [Module Manager](../building-modules/module-manager.md) to call this function for each module (this is done in the [application's constructor](../basics/app-anatomy.md#constructor-function)).

At the bare minimum, a `RegisterRoutes()` function should use the SDK client package `RegisterRoutes()` function to be able to route RPC calls, and instruct the application Module Manager to call `RegisterRESTRoutes()` for all of its modules. This is done in the `main.go` file of the CLI (typically located in `./cmd/appcli/main.go`).
At the bare minimum, a `RegisterRoutes()` function should use the SDK client package `RegisterRoutes()` function to be able to route RPC calls, and instruct the application Module Manager to call `RegisterRESTRoutes()` for all of its modules. This is done in the `main.go` file of the CLI (typically located in `./cmd/appcli/main.go`).

```go
func registerRoutes(rs *rest.RestServer) {
Expand All @@ -58,3 +58,14 @@ This function is specific to the application and passed in to the `ServeCommand`
```go
rootCmd.AddCommand(rest.ServeCommand(cdc, registerRoutes))
```

## Cors
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved

Cors are not enabled by default to help with security. If you would like to use the rest-server in a public environment we recommend you provide a reverse proxy, this can be done with [nginx](https://www.nginx.com/). For testing and development purposes there is an `unsafe_cors` flag that can be passed to the cmd to enable accepting cors from everyone.
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved

```sh
gaiacli rest-server --chain-id=test \
--laddr=tcp://localhost:1317 \
--node tcp://localhost:26657 \
--trust-node=true --unsafe_cors
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved
```
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/gogo/protobuf v1.3.1
github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129
github.com/golang/protobuf v1.3.3
github.com/gorilla/handlers v1.4.2
github.com/gorilla/mux v1.7.4
github.com/hashicorp/golang-lru v0.5.4
github.com/mattn/go-isatty v0.0.12
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
Expand Down