fix: `stale` querystring parameter value as boolean (#15605)

* Add changes to make stale querystring param boolean

Signed-off-by: dttung2905 <ttdao.2015@accountancy.smu.edu.sg>

* Make error message more consistent

Signed-off-by: dttung2905 <ttdao.2015@accountancy.smu.edu.sg>

* Changes from code review + Adding CHANGELOG file

Signed-off-by: dttung2905 <ttdao.2015@accountancy.smu.edu.sg>

* Changes from code review to use github.com/shoenig/test package

Signed-off-by: dttung2905 <ttdao.2015@accountancy.smu.edu.sg>

* Change must.Nil() to must.NoError()

Signed-off-by: dttung2905 <ttdao.2015@accountancy.smu.edu.sg>

* Minor fix on the import order

Signed-off-by: dttung2905 <ttdao.2015@accountancy.smu.edu.sg>

* Fix existing code format too

Signed-off-by: dttung2905 <ttdao.2015@accountancy.smu.edu.sg>

* Minor changes addressing code review feedbacks

Signed-off-by: dttung2905 <ttdao.2015@accountancy.smu.edu.sg>

* swap must.EqOp() order of param provided

Signed-off-by: dttung2905 <ttdao.2015@accountancy.smu.edu.sg>

Signed-off-by: dttung2905 <ttdao.2015@accountancy.smu.edu.sg>
This commit is contained in:
Dao Thanh Tung 2023-01-02 03:04:14 +08:00 committed by GitHub
parent cd75858f4a
commit 53cd1b4871
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 21 deletions

3
.changelog/15605.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
api: Fix stale querystring parameter value as boolean
```

View File

@ -783,10 +783,16 @@ func parseWait(resp http.ResponseWriter, req *http.Request, b *structs.QueryOpti
} }
// parseConsistency is used to parse the ?stale query params. // parseConsistency is used to parse the ?stale query params.
func parseConsistency(req *http.Request, b *structs.QueryOptions) { func parseConsistency(resp http.ResponseWriter, req *http.Request, b *structs.QueryOptions) {
query := req.URL.Query() query := req.URL.Query()
if _, ok := query["stale"]; ok { if staleVal, ok := query["stale"]; ok {
b.AllowStale = true staleQuery, err := strconv.ParseBool(staleVal[0])
if err != nil {
resp.WriteHeader(400)
resp.Write([]byte(fmt.Sprintf("Expect `true` or `false` for `stale` query string parameter, got %s", staleVal[0])))
}
b.AllowStale = staleQuery || staleVal[0] == ""
} }
} }
@ -884,7 +890,7 @@ func (s *HTTPServer) parseToken(req *http.Request, token *string) {
func (s *HTTPServer) parse(resp http.ResponseWriter, req *http.Request, r *string, b *structs.QueryOptions) bool { func (s *HTTPServer) parse(resp http.ResponseWriter, req *http.Request, r *string, b *structs.QueryOptions) bool {
s.parseRegion(req, r) s.parseRegion(req, r)
s.parseToken(req, &b.AuthToken) s.parseToken(req, &b.AuthToken)
parseConsistency(req, b) parseConsistency(resp, req, b)
parsePrefix(req, b) parsePrefix(req, b)
parseNamespace(req, &b.Namespace) parseNamespace(req, &b.Namespace)
parsePagination(req, b) parsePagination(req, b)

View File

@ -29,6 +29,7 @@ import (
"github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/nomad/structs/config" "github.com/hashicorp/nomad/nomad/structs/config"
"github.com/hashicorp/nomad/testutil" "github.com/hashicorp/nomad/testutil"
"github.com/shoenig/test/must"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -476,29 +477,37 @@ func TestParseWait_InvalidIndex(t *testing.T) {
func TestParseConsistency(t *testing.T) { func TestParseConsistency(t *testing.T) {
ci.Parallel(t) ci.Parallel(t)
var b structs.QueryOptions var b structs.QueryOptions
var resp *httptest.ResponseRecorder
req, err := http.NewRequest("GET", testCases := [2]string{"/v1/catalog/nodes?stale", "/v1/catalog/nodes?stale=true"}
"/v1/catalog/nodes?stale", nil) for _, urlPath := range testCases {
if err != nil { req, err := http.NewRequest("GET", urlPath, nil)
t.Fatalf("err: %v", err) must.NoError(t, err)
resp = httptest.NewRecorder()
parseConsistency(resp, req, &b)
must.True(t, b.AllowStale)
} }
parseConsistency(req, &b) req, err := http.NewRequest("GET", "/v1/catalog/nodes?stale=false", nil)
if !b.AllowStale { must.NoError(t, err)
t.Fatalf("Bad: %v", b) resp = httptest.NewRecorder()
} parseConsistency(resp, req, &b)
must.False(t, b.AllowStale)
req, err = http.NewRequest("GET", "/v1/catalog/nodes?stale=random", nil)
must.NoError(t, err)
resp = httptest.NewRecorder()
parseConsistency(resp, req, &b)
must.False(t, b.AllowStale)
must.EqOp(t, 400, resp.Code)
b = structs.QueryOptions{} b = structs.QueryOptions{}
req, err = http.NewRequest("GET", req, err = http.NewRequest("GET", "/v1/catalog/nodes?consistent", nil)
"/v1/catalog/nodes?consistent", nil) must.NoError(t, err)
if err != nil {
t.Fatalf("err: %v", err)
}
parseConsistency(req, &b) resp = httptest.NewRecorder()
if b.AllowStale { parseConsistency(resp, req, &b)
t.Fatalf("Bad: %v", b) must.False(t, b.AllowStale)
}
} }
func TestParseRegion(t *testing.T) { func TestParseRegion(t *testing.T) {