-
Notifications
You must be signed in to change notification settings - Fork 521
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added new middleware to validate request query values (#3993)
* feat: added new middleware to validate request query values * remove unused test * use different regex for tests * rename middlewares and add e2e tests
- Loading branch information
1 parent
457a563
commit 8a0b0e7
Showing
11 changed files
with
129 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
50 changes: 50 additions & 0 deletions
50
modules/frontend/pipeline/async_query_validator_middleware.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package pipeline | ||
|
||
import ( | ||
"fmt" | ||
"net/url" | ||
|
||
"github.com/grafana/tempo/modules/frontend/combiner" | ||
"github.com/grafana/tempo/pkg/traceql" | ||
) | ||
|
||
type queryValidatorWare struct { | ||
next AsyncRoundTripper[combiner.PipelineResponse] | ||
} | ||
|
||
func NewQueryValidatorWare() AsyncMiddleware[combiner.PipelineResponse] { | ||
return AsyncMiddlewareFunc[combiner.PipelineResponse](func(next AsyncRoundTripper[combiner.PipelineResponse]) AsyncRoundTripper[combiner.PipelineResponse] { | ||
return &queryValidatorWare{ | ||
next: next, | ||
} | ||
}) | ||
} | ||
|
||
func (c queryValidatorWare) RoundTrip(req Request) (Responses[combiner.PipelineResponse], error) { | ||
query := req.HTTPRequest().URL.Query() | ||
err := c.validateTraceQLQuery(query) | ||
if err != nil { | ||
return NewBadRequest(err), nil | ||
} | ||
return c.next.RoundTrip(req) | ||
} | ||
|
||
func (c queryValidatorWare) validateTraceQLQuery(queryParams url.Values) error { | ||
var traceQLQuery string | ||
if queryParams.Has("q") { | ||
traceQLQuery = queryParams.Get("q") | ||
} | ||
if queryParams.Has("query") { | ||
traceQLQuery = queryParams.Get("query") | ||
} | ||
if traceQLQuery != "" { | ||
expr, err := traceql.Parse(traceQLQuery) | ||
if err == nil { | ||
err = traceql.Validate(expr) | ||
} | ||
if err != nil { | ||
return fmt.Errorf("invalid TraceQL query: %w", err) | ||
} | ||
} | ||
return nil | ||
} |
52 changes: 52 additions & 0 deletions
52
modules/frontend/pipeline/async_query_validator_middleware_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package pipeline | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"io" | ||
"net/http" | ||
"testing" | ||
|
||
"github.com/grafana/tempo/modules/frontend/combiner" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
var nextFunc = AsyncRoundTripperFunc[combiner.PipelineResponse](func(_ Request) (Responses[combiner.PipelineResponse], error) { | ||
return NewHTTPToAsyncResponse(&http.Response{ | ||
StatusCode: 200, | ||
Body: io.NopCloser(bytes.NewReader([]byte{})), | ||
}), nil | ||
}) | ||
|
||
func TestQueryValidator(t *testing.T) { | ||
roundTrip := NewQueryValidatorWare().Wrap(nextFunc) | ||
statusCode := doRequest(t, "http://localhost:8080/api/search", roundTrip) | ||
assert.Equal(t, 200, statusCode) | ||
} | ||
|
||
func TestQueryValidatorForAValidQuery(t *testing.T) { | ||
roundTrip := NewQueryValidatorWare().Wrap(nextFunc) | ||
statusCode := doRequest(t, "http://localhost:8080/api/search&q={}", roundTrip) | ||
assert.Equal(t, 200, statusCode) | ||
} | ||
|
||
func TestQueryValidatorForAnInvalidTraceQLQuery(t *testing.T) { | ||
roundTrip := NewQueryValidatorWare().Wrap(nextFunc) | ||
statusCode := doRequest(t, "http://localhost:8080/api/search?q={. hi}", roundTrip) | ||
assert.Equal(t, 400, statusCode) | ||
} | ||
|
||
func TestQueryValidatorForAnInvalidTraceQlQueryRegex(t *testing.T) { | ||
roundTrip := NewQueryValidatorWare().Wrap(nextFunc) | ||
statusCode := doRequest(t, "http://localhost:8080/api/search?query={span.a =~ \"[\"}", roundTrip) | ||
assert.Equal(t, 400, statusCode) | ||
} | ||
|
||
func doRequest(t *testing.T, url string, rt AsyncRoundTripper[combiner.PipelineResponse]) int { | ||
req, _ := http.NewRequest(http.MethodGet, url, nil) | ||
resp, _ := rt.RoundTrip(NewHTTPRequest(req)) | ||
httpResponse, _, err := resp.Next(context.Background()) | ||
require.NoError(t, err) | ||
return httpResponse.HTTPResponse().StatusCode | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package traceql | ||
|
||
func Validate(expr *RootExpr) error { | ||
return expr.validate() | ||
} |