diff --git a/ctl/export.go b/ctl/export.go index fa6277f16..295e10039 100644 --- a/ctl/export.go +++ b/ctl/export.go @@ -31,7 +31,7 @@ type ExportCommand struct { // Name of the index & frame to export from. Index string Frame string - View string + View string // Filename to export to. Path string diff --git a/handler.go b/handler.go index c4a98d04c..c4a2c2a06 100644 --- a/handler.go +++ b/handler.go @@ -42,6 +42,7 @@ import ( _ "github.com/pilosa/pilosa/statik" "github.com/rakyll/statik/fs" + "unicode" ) // Handler represents an HTTP handler. @@ -843,6 +844,12 @@ func (h *Handler) readProtobufQueryRequest(r *http.Request) (*QueryRequest, erro // readURLQueryRequest parses query parameters from URL parameters from r. func (h *Handler) readURLQueryRequest(r *http.Request) (*QueryRequest, error) { q := r.URL.Query() + validQuery := validOptions(QueryRequest{}) + for key, _ := range q { + if _, ok := validQuery[key]; !ok { + return nil, errors.New("invalid query params") + } + } // Parse query string. buf, err := ioutil.ReadAll(r.Body) @@ -875,6 +882,21 @@ func (h *Handler) readURLQueryRequest(r *http.Request) (*QueryRequest, error) { }, nil } +// validOptions return all attributes of an interface with lower first character. +func validOptions(v interface{}) map[string]bool { + validQuery := make(map[string]bool) + argsType := reflect.ValueOf(v).Type() + + for i := 0; i < argsType.NumField(); i++ { + fieldName := argsType.Field(i).Name + chars := []rune(fieldName) + chars[0] = unicode.ToLower(chars[0]) + fieldName = string(chars) + validQuery[fieldName] = true + } + return validQuery +} + // writeQueryResponse writes the response from the executor to w. func (h *Handler) writeQueryResponse(w http.ResponseWriter, r *http.Request, resp *QueryResponse) error { if strings.Contains(r.Header.Get("Accept"), "application/x-protobuf") { diff --git a/handler_test.go b/handler_test.go index 6744e74ea..427ad043e 100644 --- a/handler_test.go +++ b/handler_test.go @@ -209,6 +209,16 @@ func TestHandler_Query_Args_Err(t *testing.T) { t.Fatalf("unexpected body: %q", body) } } +func TestHandler_Query_Params_Err(t *testing.T) { + w := httptest.NewRecorder() + NewHandler().ServeHTTP(w, MustNewHTTPRequest("POST", "/index/idx0/query?slices=0,1&db=sample", strings.NewReader("Bitmap(id=100)"))) + if w.Code != http.StatusBadRequest { + t.Fatalf("unexpected status code: %d", w.Code) + } else if body := w.Body.String(); body != `{"error":"invalid query params"}`+"\n" { + t.Fatalf("unexpected body: %q", body) + } + +} // Ensure the handler can execute a query with a uint64 response as JSON. func TestHandler_Query_Uint64_JSON(t *testing.T) {