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

cmd/baseserver, */rest: allow baseserver to choose which handlers to use #207

Merged
merged 1 commit into from
Aug 3, 2017
Merged
Show file tree
Hide file tree
Changes from all 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
47 changes: 0 additions & 47 deletions client/rest/cmd.go

This file was deleted.

59 changes: 39 additions & 20 deletions client/rest/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ func DefaultKeysManager() keys.Manager {
return keysutils.GetKeyManager()
}

func NewDefaultKeysManager(algo string) *Keys {
return New(DefaultKeysManager(), algo)
}

func New(manager keys.Manager, algo string) *Keys {
return &Keys{
algo: algo,
Expand Down Expand Up @@ -121,26 +125,6 @@ func (k *Keys) DeleteKey(w http.ResponseWriter, r *http.Request) {
common.WriteSuccess(w, resp)
}

func (k *Keys) Register(r *mux.Router) {
r.HandleFunc("/keys", k.GenerateKey).Methods("POST")
r.HandleFunc("/keys", k.ListKeys).Methods("GET")
r.HandleFunc("/keys/{name}", k.GetKey).Methods("GET")
r.HandleFunc("/keys/{name}", k.UpdateKey).Methods("POST", "PUT")
r.HandleFunc("/keys/{name}", k.DeleteKey).Methods("DELETE")
}

type Context struct {
Keys *Keys
}

func (ctx *Context) RegisterHandlers(r *mux.Router) error {
ctx.Keys.Register(r)
r.HandleFunc("/sign", doSign).Methods("POST")
r.HandleFunc("/tx", doPostTx).Methods("POST")

return nil
}

func doPostTx(w http.ResponseWriter, r *http.Request) {
tx := new(basecoin.Tx)
if err := common.ParseRequestAndValidateJSON(r, tx); err != nil {
Expand Down Expand Up @@ -170,3 +154,38 @@ func doSign(w http.ResponseWriter, r *http.Request) {
}
common.WriteSuccess(w, tx)
}

// mux.Router registrars

// RegisterPostTx is a mux.Router handler that exposes POST
// method access to post a transaction to the blockchain.
func RegisterPostTx(r *mux.Router) error {
r.HandleFunc("/tx", doPostTx).Methods("POST")
return nil
}

// RegisterAllCRUD is a convenience method to register all
// CRUD for keys to allow access by methods and routes:
// POST: /keys
// GET: /keys
// GET: /keys/{name}
// POST, PUT: /keys/{name}
// DELETE: /keys/{name}
func (k *Keys) RegisterAllCRUD(r *mux.Router) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice job pulling out these regsiter functions.

r.HandleFunc("/keys", k.GenerateKey).Methods("POST")
r.HandleFunc("/keys", k.ListKeys).Methods("GET")
r.HandleFunc("/keys/{name}", k.GetKey).Methods("GET")
r.HandleFunc("/keys/{name}", k.UpdateKey).Methods("POST", "PUT")
r.HandleFunc("/keys/{name}", k.DeleteKey).Methods("DELETE")

return nil
}

// RegisterSignTx is a mux.Router handler that
// exposes POST method access to sign a transaction.
func RegisterSignTx(r *mux.Router) error {
r.HandleFunc("/sign", doSign).Methods("POST")
return nil
}

// End of mux.Router registrars
54 changes: 53 additions & 1 deletion cmd/baseserver/main.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package main

import (
"fmt"
"log"
"net/http"
"os"

"github.com/gorilla/mux"
"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/tendermint/basecoin/client/commands"
rest "github.com/tendermint/basecoin/client/rest"
coinrest "github.com/tendermint/basecoin/modules/coin/rest"
"github.com/tendermint/tmlibs/cli"
)

Expand All @@ -17,12 +22,59 @@ var srvCli = &cobra.Command{
Long: `Baseserver presents a nice (not raw hex) interface to the basecoin blockchain structure.`,
}

var serveCmd = &cobra.Command{
Use: "serve",
Short: "Serve the light REST client for tendermint",
Long: "Access basecoin via REST",
RunE: serve,
}

const (
envPortFlag = "port"
defaultAlgo = "ed25519"
)

func init() {
_ = serveCmd.PersistentFlags().Int(envPortFlag, 8998, "the port to run the server on")
}

func serve(cmd *cobra.Command, args []string) error {
router := mux.NewRouter()

routeRegistrars := []func(*mux.Router) error{
Copy link
Contributor

Choose a reason for hiding this comment

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

I like the flexibility of this function very much. But still don't want to have to add all this code in every app. The only thing that changes between apps is routeRegistrars.

For DRY, I would prefer adding some global way to set the routeRegistrars from main.go (calling a function, directly setting a public variable, ...) but have the rest of this file back in client/rest

// rest.Keys handlers
rest.NewDefaultKeysManager(defaultAlgo).RegisterAllCRUD,

// Coin send handler
coinrest.RegisterCoinSend,
// Coin query account handler
coinrest.RegisterQueryAccount,

// Basecoin sign transactions handler
rest.RegisterSignTx,
// Basecoin post transaction handler
rest.RegisterPostTx,
}

for _, routeRegistrar := range routeRegistrars {
if err := routeRegistrar(router); err != nil {
log.Fatal(err)
}
}

port := viper.GetInt(envPortFlag)
addr := fmt.Sprintf(":%d", port)

log.Printf("Serving on %q", addr)
return http.ListenAndServe(addr, router)
}

func main() {
commands.AddBasicFlags(srvCli)

srvCli.AddCommand(
commands.InitCmd,
rest.ServeCmd,
serveCmd,
)

// TODO: Decide whether to use $HOME/.basecli for compatibility
Expand Down
41 changes: 35 additions & 6 deletions modules/coin/rest/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@ type SendInput struct {
Amount coin.Coins `json:"amount"`
}

func RegisterHandlers(r *mux.Router) error {
r.HandleFunc("/build/send", doSend).Methods("POST")
r.HandleFunc("/query/account/{signature}", doQueryAccount).Methods("GET")
return nil
}

// doQueryAccount is the HTTP handlerfunc to query an account
// It expects a query string with
func doQueryAccount(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -121,3 +115,38 @@ func doSend(w http.ResponseWriter, r *http.Request) {
tx := PrepareSendTx(si)
common.WriteSuccess(w, tx)
}

// mux.Router registrars

// RegisterCoinSend is a mux.Router handler that exposes
// POST method access on route /build/send to create a
// transaction for sending money from one account to another.
func RegisterCoinSend(r *mux.Router) error {
r.HandleFunc("/build/send", doSend).Methods("POST")
return nil
}

// RegisterQueryAccount is a mux.Router handler that exposes GET
// method access on route /query/account/{signature} to query accounts
func RegisterQueryAccount(r *mux.Router) error {
r.HandleFunc("/query/account/{signature}", doQueryAccount).Methods("GET")
return nil
}

// RegisterAll is a convenience function to
// register all the handlers in this package.
func RegisterAll(r *mux.Router) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

A bit verbose having the three functions, but very, very awesome for enabling remixing in the different applications.
I like it.

funcs := []func(*mux.Router) error{
RegisterCoinSend,
RegisterQueryAccount,
}

for _, fn := range funcs {
if err := fn(r); err != nil {
return err
}
}
return nil
}

// End of mux.Router registrars