Add route for querying signing_info for all validators (#3952)

Also remove duplicate pagination:
- move function to extract query params into types/rest
- adjust pagination values locally until available in tendermint for validators

Code cleanup:
- helper function in test
- fix pagination description in swagger.yaml
- uint instead of int when possible

Closes: #3226
Closes: #3991
This commit is contained in:
Karoly Albert Szabo
2019-03-28 18:43:33 +00:00
committed by Alessio Treglia
parent e5897d8d91
commit 5bb6090e38
10 changed files with 321 additions and 90 deletions
+58
View File
@@ -3,9 +3,12 @@
package rest
import (
"errors"
"fmt"
"github.com/tendermint/tendermint/types"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
@@ -13,6 +16,11 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
const (
DefaultPage = 1
DefaultLimit = 30 // should be consistent with tendermint/tendermint/rpc/core/pipe.go:19
)
// GasEstimateResponse defines a response definition for tx gas estimation.
type GasEstimateResponse struct {
GasEstimate uint64 `json:"gas_estimate"`
@@ -211,3 +219,53 @@ func PostProcessResponse(w http.ResponseWriter, cdc *codec.Codec, response inter
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write(output)
}
// ParseHTTPArgs parses the request's URL and returns a slice containing all arguments pairs.
// It separates page and limit used for pagination
func ParseHTTPArgs(r *http.Request) (tags []string, page, limit int, err error) {
tags = make([]string, 0, len(r.Form))
for key, values := range r.Form {
if key == "page" || key == "limit" {
continue
}
var value string
value, err = url.QueryUnescape(values[0])
if err != nil {
return tags, page, limit, err
}
var tag string
if key == types.TxHeightKey {
tag = fmt.Sprintf("%s=%s", key, value)
} else {
tag = fmt.Sprintf("%s='%s'", key, value)
}
tags = append(tags, tag)
}
pageStr := r.FormValue("page")
if pageStr == "" {
page = DefaultPage
} else {
page, err = strconv.Atoi(pageStr)
if err != nil {
return tags, page, limit, err
} else if page <= 0 {
return tags, page, limit, errors.New("page must greater than 0")
}
}
limitStr := r.FormValue("limit")
if limitStr == "" {
limit = DefaultLimit
} else {
limit, err = strconv.Atoi(limitStr)
if err != nil {
return tags, page, limit, err
} else if limit <= 0 {
return tags, page, limit, errors.New("limit must greater than 0")
}
}
return tags, page, limit, nil
}
+53
View File
@@ -3,6 +3,7 @@
package rest
import (
"io"
"net/http"
"net/http/httptest"
"testing"
@@ -55,3 +56,55 @@ func TestBaseReqValidateBasic(t *testing.T) {
})
}
}
func TestParseHTTPArgs(t *testing.T) {
req0 := mustNewRequest(t, "", "/", nil)
req1 := mustNewRequest(t, "", "/?limit=5", nil)
req2 := mustNewRequest(t, "", "/?page=5", nil)
req3 := mustNewRequest(t, "", "/?page=5&limit=5", nil)
reqE1 := mustNewRequest(t, "", "/?page=-1", nil)
reqE2 := mustNewRequest(t, "", "/?limit=-1", nil)
req4 := mustNewRequest(t, "", "/?foo=faa", nil)
tests := []struct {
name string
req *http.Request
w http.ResponseWriter
tags []string
page int
limit int
err bool
}{
{"no params", req0, httptest.NewRecorder(), []string{}, DefaultPage, DefaultLimit, false},
{"Limit", req1, httptest.NewRecorder(), []string{}, DefaultPage, 5, false},
{"Page", req2, httptest.NewRecorder(), []string{}, 5, DefaultLimit, false},
{"Page and limit", req3, httptest.NewRecorder(), []string{}, 5, 5, false},
{"error page 0", reqE1, httptest.NewRecorder(), []string{}, DefaultPage, DefaultLimit, true},
{"error limit 0", reqE2, httptest.NewRecorder(), []string{}, DefaultPage, DefaultLimit, true},
{"tags", req4, httptest.NewRecorder(), []string{"foo='faa'"}, DefaultPage, DefaultLimit, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tags, page, limit, err := ParseHTTPArgs(tt.req)
if tt.err {
require.NotNil(t, err)
} else {
require.Nil(t, err)
require.Equal(t, tt.tags, tags)
require.Equal(t, tt.page, page)
require.Equal(t, tt.limit, limit)
}
})
}
}
func mustNewRequest(t *testing.T, method, url string, body io.Reader) *http.Request {
req, err := http.NewRequest(method, url, body)
require.NoError(t, err)
err = req.ParseForm()
require.NoError(t, err)
return req
}