Skip to content

Commit 26e9a37

Browse files
fenollpcodyaray
andauthored
Confluentinc middleware (#228)
Co-authored-by: Cody A. Ray <cody@confluent.io>
1 parent a78d0f6 commit 26e9a37

2 files changed

Lines changed: 78 additions & 6 deletions

File tree

openapi3filter/validation_error_test.go

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ func (e *mockErrorEncoder) Encode(ctx context.Context, err error, w http.Respons
547547
e.W = w
548548
}
549549

550-
func runTest(t *testing.T, handler http.Handler, encoder ErrorEncoder, req *http.Request) *http.Response {
550+
func runTest_ServeHTTP(t *testing.T, handler http.Handler, encoder ErrorEncoder, req *http.Request) *http.Response {
551551
h := &ValidationHandler{
552552
Handler: handler,
553553
ErrorEncoder: encoder,
@@ -560,6 +560,18 @@ func runTest(t *testing.T, handler http.Handler, encoder ErrorEncoder, req *http
560560
return w.Result()
561561
}
562562

563+
func runTest_Middleware(t *testing.T, handler http.Handler, encoder ErrorEncoder, req *http.Request) *http.Response {
564+
h := &ValidationHandler{
565+
ErrorEncoder: encoder,
566+
SwaggerFile: "fixtures/petstore.json",
567+
}
568+
err := h.Load()
569+
require.NoError(t, err)
570+
w := httptest.NewRecorder()
571+
h.Middleware(handler).ServeHTTP(w, req)
572+
return w.Result()
573+
}
574+
563575
func TestValidationHandler_ServeHTTP(t *testing.T) {
564576
t.Run("errors on invalid requests", func(t *testing.T) {
565577
httpCtx := context.WithValue(context.Background(), "pig", "tails")
@@ -569,7 +581,49 @@ func TestValidationHandler_ServeHTTP(t *testing.T) {
569581

570582
handler := &testHandler{}
571583
encoder := &mockErrorEncoder{}
572-
runTest(t, handler, encoder.Encode, r)
584+
runTest_ServeHTTP(t, handler, encoder.Encode, r)
585+
586+
require.False(t, handler.Called)
587+
require.True(t, encoder.Called)
588+
require.Equal(t, httpCtx, encoder.Ctx)
589+
require.NotNil(t, encoder.Err)
590+
})
591+
592+
t.Run("passes valid requests through", func(t *testing.T) {
593+
r := newPetstoreRequest(t, http.MethodGet, "/pet/findByStatus?status=sold", nil)
594+
595+
handler := &testHandler{}
596+
encoder := &mockErrorEncoder{}
597+
runTest_ServeHTTP(t, handler, encoder.Encode, r)
598+
599+
require.True(t, handler.Called)
600+
require.False(t, encoder.Called)
601+
})
602+
603+
t.Run("uses error encoder", func(t *testing.T) {
604+
r := newPetstoreRequest(t, http.MethodPost, "/pet", bytes.NewBufferString(`{"name":"Bahama","photoUrls":"http://cat"}`))
605+
606+
handler := &testHandler{}
607+
encoder := &ValidationErrorEncoder{Encoder: (ErrorEncoder)(DefaultErrorEncoder)}
608+
resp := runTest_ServeHTTP(t, handler, encoder.Encode, r)
609+
610+
body, err := ioutil.ReadAll(resp.Body)
611+
require.NoError(t, err)
612+
require.Equal(t, http.StatusUnprocessableEntity, resp.StatusCode)
613+
require.Equal(t, "[422][][] Field must be set to array or not be present [source pointer=/photoUrls]", string(body))
614+
})
615+
}
616+
617+
func TestValidationHandler_Middleware(t *testing.T) {
618+
t.Run("errors on invalid requests", func(t *testing.T) {
619+
httpCtx := context.WithValue(context.Background(), "pig", "tails")
620+
r, err := http.NewRequest(http.MethodGet, "http://unknown-host.com/v2/pet", nil)
621+
require.NoError(t, err)
622+
r = r.WithContext(httpCtx)
623+
624+
handler := &testHandler{}
625+
encoder := &mockErrorEncoder{}
626+
runTest_Middleware(t, handler, encoder.Encode, r)
573627

574628
require.False(t, handler.Called)
575629
require.True(t, encoder.Called)
@@ -582,7 +636,7 @@ func TestValidationHandler_ServeHTTP(t *testing.T) {
582636

583637
handler := &testHandler{}
584638
encoder := &mockErrorEncoder{}
585-
runTest(t, handler, encoder.Encode, r)
639+
runTest_Middleware(t, handler, encoder.Encode, r)
586640

587641
require.True(t, handler.Called)
588642
require.False(t, encoder.Called)
@@ -593,7 +647,7 @@ func TestValidationHandler_ServeHTTP(t *testing.T) {
593647

594648
handler := &testHandler{}
595649
encoder := &ValidationErrorEncoder{Encoder: (ErrorEncoder)(DefaultErrorEncoder)}
596-
resp := runTest(t, handler, encoder.Encode, r)
650+
resp := runTest_Middleware(t, handler, encoder.Encode, r)
597651

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

openapi3filter/validation_handler.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,32 @@ func (h *ValidationHandler) Load() error {
4141
}
4242

4343
func (h *ValidationHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
44-
if err := h.validateRequest(r); err != nil {
45-
h.ErrorEncoder(r.Context(), err, w)
44+
if handled := h.before(w, r); handled {
4645
return
4746
}
4847
// TODO: validateResponse
4948
h.Handler.ServeHTTP(w, r)
5049
}
5150

51+
// Middleware implements gorilla/mux MiddlewareFunc
52+
func (h *ValidationHandler) Middleware(next http.Handler) http.Handler {
53+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
54+
if handled := h.before(w, r); handled {
55+
return
56+
}
57+
// TODO: validateResponse
58+
next.ServeHTTP(w, r)
59+
})
60+
}
61+
62+
func (h *ValidationHandler) before(w http.ResponseWriter, r *http.Request) (handled bool) {
63+
if err := h.validateRequest(r); err != nil {
64+
h.ErrorEncoder(r.Context(), err, w)
65+
return true
66+
}
67+
return false
68+
}
69+
5270
func (h *ValidationHandler) validateRequest(r *http.Request) error {
5371
// Find route
5472
route, pathParams, err := h.router.FindRoute(r.Method, r.URL)

0 commit comments

Comments
 (0)