Skip to content

Commit

Permalink
Merge pull request #914 from k1LoW/fix-panic
Browse files Browse the repository at this point in the history
Fix panics caused by ResponseContentTypeNotFound in the case of a response with a range status code.
  • Loading branch information
k1LoW committed May 6, 2024
2 parents 09a6f52 + 2187e92 commit b60fcab
Show file tree
Hide file tree
Showing 65 changed files with 18,071 additions and 7 deletions.
2 changes: 1 addition & 1 deletion coverage.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"regexp"
"strings"

"github.com/pb33f/libopenapi-validator/paths"
"github.com/k1LoW/runn/tmpmod/github.com/pb33f/libopenapi-validator/paths"
v3 "github.com/pb33f/libopenapi/datamodel/high/v3"
"github.com/pb33f/libopenapi/orderedmap"
"github.com/samber/lo"
Expand Down
11 changes: 7 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,15 @@ require (
github.com/olekukonko/tablewriter v0.0.5
github.com/ory/dockertest/v3 v3.10.0
github.com/pb33f/libopenapi v0.16.5
github.com/pb33f/libopenapi-validator v0.0.55
github.com/rs/xid v1.5.0
github.com/ryo-yamaoka/otchkiss v0.1.2
github.com/samber/lo v1.39.0
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
github.com/spf13/cast v1.6.0
github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.9.0
github.com/tenntenn/golden v0.5.4
github.com/vmware-labs/yaml-jsonpath v0.3.2
github.com/xlab/treeprint v1.2.0
github.com/xo/dburl v0.23.0
golang.org/x/crypto v0.22.0
Expand All @@ -71,6 +73,7 @@ require (
google.golang.org/grpc v1.63.2
google.golang.org/protobuf v1.34.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
modernc.org/sqlite v1.29.9
)

Expand Down Expand Up @@ -102,6 +105,7 @@ require (
github.com/cli/go-gh/v2 v2.6.0 // indirect
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa // indirect
github.com/containerd/continuity v0.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect
github.com/docker/cli v26.1.0+incompatible // indirect
github.com/docker/docker v26.1.0+incompatible // indirect
Expand Down Expand Up @@ -158,14 +162,14 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/opencontainers/runc v1.1.12 // indirect
github.com/pb33f/libopenapi-validator v0.0.55 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pkg/term v1.2.0-beta.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
Expand All @@ -192,7 +196,6 @@ require (
google.golang.org/genproto v0.0.0-20240228224816-df926f6c8641 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240415180920-8c6c420018be // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
modernc.org/libc v1.49.3 // indirect
modernc.org/mathutil v1.6.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions http_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import (

"github.com/k1LoW/runn/tmpmod/github.com/goccy/go-yaml"
"github.com/pb33f/libopenapi"
validator "github.com/pb33f/libopenapi-validator"
verrors "github.com/pb33f/libopenapi-validator/errors"
validator "github.com/k1LoW/runn/tmpmod/github.com/pb33f/libopenapi-validator"
verrors "github.com/k1LoW/runn/tmpmod/github.com/pb33f/libopenapi-validator/errors"
)

type httpValidator interface { //nostyle:ifacenames
Expand Down
138 changes: 138 additions & 0 deletions http_validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -937,3 +937,141 @@ func pathToURL(t *testing.T, p string) *url.URL {
}
return u
}

const validOpenApi3SpecReproducePanicIssue = `
openapi: 3.0.3
info:
title: test spec
version: 0.0.1
paths:
/users/{id}:
get:
parameters:
- description: ID
explode: false
in: path
name: id
required: true
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
name:
type: string
4XX:
description: 4XX error
content:
application/json:
schema:
type: object
properties:
error:
type: string
'500':
description: 500 error
content:
application/json:
schema:
type: object
properties:
error:
type: string
`

func TestOpenAPI3ValidatorReproducePanicIssue(t *testing.T) {
tests := []struct {
req *http.Request
res *http.Response
wantErr bool
}{
// this test case passes without any issue
{
&http.Request{
Method: http.MethodGet,
URL: pathToURL(t, "/users/1"),
Header: http.Header{"Accept": []string{"application/json"}},
Body: nil,
},
&http.Response{
StatusCode: http.StatusBadRequest,
Header: http.Header{"Content-Type": []string{"application/json"}},
Body: io.NopCloser(strings.NewReader(`{"error":"foo"}`)),
},
false,
},
// this test case fails
{
&http.Request{
Method: http.MethodGet,
URL: pathToURL(t, "/users/1"),
Header: http.Header{"Accept": []string{"application/json"}},
Body: nil,
},
&http.Response{
StatusCode: http.StatusInternalServerError, // 500
Header: http.Header{"Content-Type": []string{"plain/text"}},
Body: io.NopCloser(strings.NewReader(`{"error":"foo"}`)),
},
true,
},
// this test case panics
{
&http.Request{
Method: http.MethodGet,
URL: pathToURL(t, "/users/1"),
Header: http.Header{"Accept": []string{"application/json"}},
Body: nil,
},
&http.Response{
StatusCode: http.StatusBadRequest, // 400
Header: http.Header{"Content-Type": []string{"plain/text"}},
Body: io.NopCloser(strings.NewReader(`{"error":"foo"}`)),
},
true,
},
}

ctx := context.Background()
c := &httpRunnerConfig{}

opts := []httpRunnerOption{
OpenAPI3FromData([]byte(validOpenApi3SpecReproducePanicIssue)),
}

for _, opt := range opts {
if err := opt(c); err != nil {
t.Fatal(err)
}
}

v, err := newOpenAPI3Validator(c) // reusing the validator is the second key
if err != nil {
t.Fatal(err)
}

for i, tt := range tests {
t.Run(fmt.Sprintf("testcase %d", i), func(t *testing.T) {
if err := v.ValidateRequest(ctx, tt.req); err != nil {
if !tt.wantErr {
t.Errorf("got error: %v", err)
}
return
}
if err := v.ValidateResponse(ctx, tt.req, tt.res); err != nil {
if !tt.wantErr {
t.Errorf("got error: %v", err)
}
return
}
if tt.wantErr {
t.Error("want error")
}
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Build

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.x
uses: actions/setup-go@v3
with:
go-version: 1.21
id: go

- name: Checkout code
uses: actions/checkout@v3

- name: Get dependencies
run: |
go get -v -t -d ./...
if [ -f Gopkg.toml ]; then
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
dep ensure
fi
- name: Test
run: go test ./...
- name: Coverage
run: |
go get github.com/axw/gocov/gocov
go get github.com/AlekSi/gocov-xml
go install github.com/axw/gocov/gocov
go install github.com/AlekSi/gocov-xml
- run: |
go test -v -coverprofile cover.out ./...
gocov convert cover.out | gocov-xml > coverage.xml
- uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage.xml
flags: unittests
fail_ci_if_error: false
verbose: true
1 change: 1 addition & 0 deletions tmpmod/github.com/pb33f/libopenapi-validator/.tmpmod.log
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Use github.com/k1LoW/libopenapi-validator@support-4xx-or-5xx-responce-content-type-not-found (e3c620ad83a236ecf761fc6d8f86b562b7eda22b) as github.com/k1LoW/runn/tmpmod/github.com/pb33f/libopenapi-validator temporarily
23 changes: 23 additions & 0 deletions tmpmod/github.com/pb33f/libopenapi-validator/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
MIT License

libopenapi-validator

Copyright (c) 2023 Princess Beef Heavy Industries, LLC & Dave Shanley

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
45 changes: 45 additions & 0 deletions tmpmod/github.com/pb33f/libopenapi-validator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<p align="center">
<img src="libopenapi-logo.png" alt="libopenapi" height="300px" width="450px"/>
</p>

# Enterprise grade OpenAPI validation tools for golang.

![Pipeline](https://github.com/pb33f/libopenapi-validator/workflows/Build/badge.svg)
[![codecov](https://codecov.io/gh/pb33f/libopenapi-validator/branch/main/graph/badge.svg?)](https://codecov.io/gh/pb33f/libopenapi-validator)
[![discord](https://img.shields.io/discord/923258363540815912)](https://discord.gg/x7VACVuEGP)
[![Docs](https://img.shields.io/badge/godoc-reference-5fafd7)](https://pkg.go.dev/github.com/pb33f/libopenapi-validator)

A validation module for [libopenapi](https://github.com/pb33f/libopenapi).

`libopenapi-validator` will validate the following elements against an OpenAPI 3+ specification

- *http.Request* - Validates the request against the OpenAPI specification
- *http.Response* - Validates the response against the OpenAPI specification
- *libopenapi.Document* - Validates the OpenAPI document against the OpenAPI specification
- *base.Schema* - Validates a schema against a JSON or YAML blob / unmarshalled object

👉👉 [Check out the full documentation](https://pb33f.io/libopenapi/validation/) 👈👈

---

## Installation

```bash
go get github.com/pb33f/libopenapi-validator
```

## Documentation

- [The structure of the validator](https://pb33f.io/libopenapi/validation/#the-structure-of-the-validator)
- [Validation errors](https://pb33f.io/libopenapi/validation/#validation-errors)
- [Schema errors](https://pb33f.io/libopenapi/validation/#schema-errors)
- [High-level validation](https://pb33f.io/libopenapi/validation/#high-level-validation)
- [Validating http.Request](https://pb33f.io/libopenapi/validation/#validating-httprequest)
- [Validating http.Request and http.Response](https://pb33f.io/libopenapi/validation/#validating-httprequest-and-httpresponse)
- [Validating just http.Response](https://pb33f.io/libopenapi/validation/#validating-just-httpresponse)
- [Validating HTTP Parameters](https://pb33f.io/libopenapi/validation/#validating-http-parameters)
- [Validating an OpenAPI document](https://pb33f.io/libopenapi/validation/#validating-an-openapi-document)
- [Validating Schemas](https://pb33f.io/libopenapi/validation/#validating-schemas)

[libopenapi](https://github.com/pb33f/libopenapi) and [libopenapi-validator](https://github.com/pb33f/libopenapi-validator) are
products of Princess Beef Heavy Industries, LLC
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package errors

import (
"net/http"
)

// PopulateValidationErrors mutates the provided validation errors with additional useful error information, that is
// not necessarily available when the ValidationError was created and are standard for all errors.
// Specifically, the RequestPath, SpecPath and RequestMethod are populated.
func PopulateValidationErrors(validationErrors []*ValidationError, request *http.Request, path string) {
for _, validationError := range validationErrors {
validationError.SpecPath = path
validationError.RequestMethod = request.Method
validationError.RequestPath = request.URL.Path
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Copyright 2023 Princess B33f Heavy Industries / Dave Shanley
// SPDX-License-Identifier: MIT

// Package errors contains all the error types used by the validator
package errors
Loading

0 comments on commit b60fcab

Please sign in to comment.