From 03d19506749d3a38377d9ad36a34681ce0f407b8 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 13 Jun 2015 17:50:00 -0400 Subject: [PATCH] rpc endpoint / lists available endpoints --- rpc/server/handlers.go | 58 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/rpc/server/handlers.go b/rpc/server/handlers.go index b408a3f71..2180a06b1 100644 --- a/rpc/server/handlers.go +++ b/rpc/server/handlers.go @@ -5,15 +5,17 @@ import ( "encoding/json" "errors" "fmt" - "github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/gorilla/websocket" - "github.com/tendermint/tendermint/binary" - "github.com/tendermint/tendermint/events" - . "github.com/tendermint/tendermint/rpc/types" "io/ioutil" "net/http" "reflect" + "sort" "sync/atomic" "time" + + "github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/gorilla/websocket" + "github.com/tendermint/tendermint/binary" + "github.com/tendermint/tendermint/events" + . "github.com/tendermint/tendermint/rpc/types" ) func RegisterRPCFuncs(mux *http.ServeMux, funcMap map[string]*RPCFunc) { @@ -87,6 +89,14 @@ func makeJSONRPCHandler(funcMap map[string]*RPCFunc) http.HandlerFunc { return } b, _ := ioutil.ReadAll(r.Body) + + // if its an empty request (like from a browser), + // just display a list of functions + if len(b) == 0 { + writeListOfEndpoints(w, r, funcMap) + return + } + var request RPCRequest err := json.Unmarshal(b, &request) if err != nil { @@ -393,3 +403,43 @@ func unreflectResponse(returns []reflect.Value) (interface{}, error) { } return returns[0].Interface(), nil } + +// writes a list of available rpc endpoints as an html page +func writeListOfEndpoints(w http.ResponseWriter, r *http.Request, funcMap map[string]*RPCFunc) { + noArgNames := []string{} + argNames := []string{} + for name, funcData := range funcMap { + if len(funcData.args) == 0 { + noArgNames = append(noArgNames, name) + } else { + argNames = append(argNames, name) + } + } + sort.Strings(noArgNames) + sort.Strings(argNames) + buf := new(bytes.Buffer) + buf.WriteString("") + buf.WriteString("
Available endpoints:
") + + for _, name := range noArgNames { + link := fmt.Sprintf("http://%s/%s", r.Host, name) + buf.WriteString(fmt.Sprintf("%s
", link, link)) + } + + buf.WriteString("
Endpoints that require arguments:
") + for _, name := range argNames { + link := fmt.Sprintf("http://%s/%s?", r.Host, name) + funcData := funcMap[name] + for i, argName := range funcData.argNames { + link += argName + "=_" + if i < len(funcData.argNames)-1 { + link += "&" + } + } + buf.WriteString(fmt.Sprintf("%s
", link, link)) + } + buf.WriteString("") + w.Header().Set("Content-Type", "text/html") + w.WriteHeader(200) + w.Write(buf.Bytes()) +}