Skip to content

Commit

Permalink
pkg/httpserver: allow rules to exclude parameters (#59)
Browse files Browse the repository at this point in the history
  • Loading branch information
efd6 authored Oct 13, 2023
1 parent e56c6e8 commit abe9f37
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 2 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Removed

## [0.11.0]

### Added

- Added ability to specify disallowed parameters: [#59](https://github.com/elastic/stream/pull/59)

## [0.10.0]

### Added
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ The rules will be defined in order, and will only match if all criteria is true
- `path`: the path to match. It can use [gorilla/mux](https://pkg.go.dev/github.com/gorilla/mux#pkg-overview) parameters patterns.
- `methods`: a list of methods to match with the rule.
- `user` and `password`: username and password for basic auth matching.
- `query_params`: Key-Value definitions of the query parameters to match. It can use [gorilla/mux](https://pkg.go.dev/github.com/gorilla/mux#Route.Queries) parameters patterns for the values. Web form params will also be added and compared against this for simplicity.
- `query_params`: Key-Value definitions of the query parameters to match. It can use [gorilla/mux](https://pkg.go.dev/github.com/gorilla/mux#Route.Queries) parameters patterns for the values. Web form params will also be added and compared against this for simplicity. If a key is given an empty value, requests with this parameter will not satisfy the rule.
- `request_headers`: Key-Value definitions of the headers to match. Any headers outside of this list will be ignored. The matches can be defined [as regular expressions](https://pkg.go.dev/github.com/gorilla/mux#Route.HeadersRegexp).
- `request_body`: a string defining the expected body to match for the request. If the string is quoted with slashes, the leading and trailing slash are stripped and the resulting string is interpreted as a regular expression.
- `responses`: a list of zero or more responses to return on matches. If more than one are set, they will be returned in rolling sequence.
Expand Down Expand Up @@ -127,4 +127,4 @@ The emulator does not require authentication.

- `gcs-bucket`: The name of the GCS bucket that should be created, should not already exist.
- `gcs-object`: The name of the GCS object that will be populated with the collected data, using the configured GCS bucket.
- `gcs-projectid`: The related projectID used when creating the bucket, this is required to be changed from the default value when not using an emulator.
- `gcs-projectid`: The related projectID used when creating the bucket, this is required to be changed from the default value when not using an emulator.
13 changes: 13 additions & 0 deletions pkg/httpserver/httpserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,24 @@ func newHandlerFromConfig(config *config, logger *zap.SugaredLogger) (http.Handl

route.Methods(rule.Methods...)

exclude := make(map[string]bool)
for key, vals := range rule.QueryParams {
if len(vals) == 0 { // Cannot use nil since ucfg interprets null as an empty slice instead of nil.
exclude[key] = true
continue
}
for _, v := range vals {
route.Queries(key, v)
}
}
route.MatcherFunc(func(r *http.Request, rm *mux.RouteMatch) bool {
for key := range exclude {
if r.URL.Query().Has(key) {
return false
}
}
return true
})

for key, vals := range rule.RequestHeaders {
for _, v := range vals {
Expand Down
18 changes: 18 additions & 0 deletions pkg/httpserver/httpserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func TestHTTPServer(t *testing.T) {
password: passwd
query_params:
p1: ["v1"]
p2: null
request_headers:
accept: ["application/json"]
Expand Down Expand Up @@ -124,4 +125,21 @@ func TestHTTPServer(t *testing.T) {
assert.JSONEq(t, "2", string(body))
assert.Equal(t, "text/plain", resp.Header.Get("content-type"))
})

t.Run("request has rejected parameter", func(t *testing.T) {
req, err := http.NewRequest("GET", "http://"+addr+"/path1/test?p1=v1&p2=bad", nil)
require.NoError(t, err)

resp, err := http.DefaultClient.Do(req)
require.NoError(t, err)
resp.Body.Close()

assert.Equal(t, 404, resp.StatusCode) // must fail because p2 is present

body, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
resp.Body.Close()

assert.Equal(t, []byte{}, body)
})
}

0 comments on commit abe9f37

Please sign in to comment.