Skip to content

Commit

Permalink
Merge pull request #129 from cmars/fix/disallow-future-version
Browse files Browse the repository at this point in the history
fix: disallow requesting API version dates in the future
  • Loading branch information
cmars committed Jan 21, 2022
2 parents 578991f + d4319e3 commit 5743bd3
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 0 deletions.
6 changes: 6 additions & 0 deletions versionware/export_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
package versionware

import "time"

var DefaultValidatorConfig = defaultValidatorConfig

func (v *Validator) SetToday(today func() time.Time) {
v.today = today
}
13 changes: 13 additions & 0 deletions versionware/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"net/http"
"net/url"
"sort"
"time"

"github.com/getkin/kin-openapi/openapi3"
"github.com/getkin/kin-openapi/openapi3filter"
Expand All @@ -19,6 +20,7 @@ type Validator struct {
versions vervet.VersionSlice
validators []*openapi3filter.Validator
errFunc VersionErrorHandler
today func() time.Time
}

// ValidatorConfig defines how a new Validator may be configured.
Expand Down Expand Up @@ -54,6 +56,11 @@ var defaultValidatorConfig = ValidatorConfig{
},
}

func today() time.Time {
now := time.Now().UTC()
return time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC)
}

// NewValidator returns a new validation middleware, which validates versioned
// requests according to the given OpenAPI spec versions. For configuration
// defaults, a nil config may be used.
Expand Down Expand Up @@ -84,6 +91,7 @@ func NewValidator(config *ValidatorConfig, docs ...*openapi3.T) (*Validator, err
versions: make([]vervet.Version, len(docs)),
validators: make([]*openapi3filter.Validator, len(docs)),
errFunc: config.VersionError,
today: today,
}
validatorVersions := map[string]*openapi3filter.Validator{}
for i := range docs {
Expand Down Expand Up @@ -130,6 +138,11 @@ func (v *Validator) Middleware(h http.Handler) http.Handler {
v.errFunc(w, req, http.StatusBadRequest, err)
return
}
if t := v.today(); requested.Date.After(t) {
v.errFunc(w, req, http.StatusBadRequest,
fmt.Errorf("requested version newer than present date %s", t))
return
}
resolvedIndex, err := v.versions.ResolveIndex(*requested)
if err != nil {
v.errFunc(w, req, http.StatusNotFound, err)
Expand Down
15 changes: 15 additions & 0 deletions versionware/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"net/http/httptest"
"regexp"
"testing"
"time"

qt "github.com/frankban/quicktest"
"github.com/getkin/kin-openapi/openapi3"
Expand Down Expand Up @@ -414,6 +415,17 @@ func TestValidator(t *testing.T) {
body: `{"id": "42", "contents": {"name": "foo", "expected": 9, "actual": 10}, "extra": true}`,
},
strict: false,
}, {
name: "invalid GET for API in the future",
handler: validatorTestHandler{}.withDefaults(),
request: testRequest{
method: "GET",
path: "/test/42?version=2023-09-17",
},
response: testResponse{
400, "Bad Request\n",
},
strict: true,
}}
for i, test := range tests {
c.Run(fmt.Sprintf("%d %s", i, test.name), func(c *qt.C) {
Expand All @@ -429,6 +441,9 @@ func TestValidator(t *testing.T) {
config.Options = append(config.Options, append(test.options, openapi3filter.Strict(test.strict))...)
v, err := versionware.NewValidator(&config, docs...)
c.Assert(err, qt.IsNil)
v.SetToday(func() time.Time {
return time.Date(2022, time.January, 21, 0, 0, 0, 0, time.UTC)
})
h = v.Middleware(&test.handler)

// Test: make a client request
Expand Down

0 comments on commit 5743bd3

Please sign in to comment.