Fix the dependency issue (#231)
This commit is contained in:
26
vendor/github.com/go-openapi/runtime/.editorconfig
generated
vendored
26
vendor/github.com/go-openapi/runtime/.editorconfig
generated
vendored
@@ -1,26 +0,0 @@
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# Set default charset
|
||||
[*.{js,py,go,scala,rb,java,html,css,less,sass,md}]
|
||||
charset = utf-8
|
||||
|
||||
# Tab indentation (no size specified)
|
||||
[*.go]
|
||||
indent_style = tab
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
# Matches the exact files either package.json or .travis.yml
|
||||
[{package.json,.travis.yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
117
vendor/github.com/go-openapi/runtime/.github/CONTRIBUTING.md
generated
vendored
117
vendor/github.com/go-openapi/runtime/.github/CONTRIBUTING.md
generated
vendored
@@ -1,117 +0,0 @@
|
||||
## Contribution Guidelines
|
||||
|
||||
### Pull requests are always welcome
|
||||
|
||||
We are always thrilled to receive pull requests, and do our best to
|
||||
process them as fast as possible. Not sure if that typo is worth a pull
|
||||
request? Do it! We will appreciate it.
|
||||
|
||||
If your pull request is not accepted on the first try, don't be
|
||||
discouraged! If there's a problem with the implementation, hopefully you
|
||||
received feedback on what to improve.
|
||||
|
||||
We're trying very hard to keep go-swagger lean and focused. We don't want it
|
||||
to do everything for everybody. This means that we might decide against
|
||||
incorporating a new feature. However, there might be a way to implement
|
||||
that feature *on top of* go-swagger.
|
||||
|
||||
|
||||
### Conventions
|
||||
|
||||
Fork the repo and make changes on your fork in a feature branch:
|
||||
|
||||
- If it's a bugfix branch, name it XXX-something where XXX is the number of the
|
||||
issue
|
||||
- If it's a feature branch, create an enhancement issue to announce your
|
||||
intentions, and name it XXX-something where XXX is the number of the issue.
|
||||
|
||||
Submit unit tests for your changes. Go has a great test framework built in; use
|
||||
it! Take a look at existing tests for inspiration. Run the full test suite on
|
||||
your branch before submitting a pull request.
|
||||
|
||||
Update the documentation when creating or modifying features. Test
|
||||
your documentation changes for clarity, concision, and correctness, as
|
||||
well as a clean documentation build. See ``docs/README.md`` for more
|
||||
information on building the docs and how docs get released.
|
||||
|
||||
Write clean code. Universally formatted code promotes ease of writing, reading,
|
||||
and maintenance. Always run `gofmt -s -w file.go` on each changed file before
|
||||
committing your changes. Most editors have plugins that do this automatically.
|
||||
|
||||
Pull requests descriptions should be as clear as possible and include a
|
||||
reference to all the issues that they address.
|
||||
|
||||
Pull requests must not contain commits from other users or branches.
|
||||
|
||||
Commit messages must start with a capitalized and short summary (max. 50
|
||||
chars) written in the imperative, followed by an optional, more detailed
|
||||
explanatory text which is separated from the summary by an empty line.
|
||||
|
||||
Code review comments may be added to your pull request. Discuss, then make the
|
||||
suggested modifications and push additional commits to your feature branch. Be
|
||||
sure to post a comment after pushing. The new commits will show up in the pull
|
||||
request automatically, but the reviewers will not be notified unless you
|
||||
comment.
|
||||
|
||||
Before the pull request is merged, make sure that you squash your commits into
|
||||
logical units of work using `git rebase -i` and `git push -f`. After every
|
||||
commit the test suite should be passing. Include documentation changes in the
|
||||
same commit so that a revert would remove all traces of the feature or fix.
|
||||
|
||||
Commits that fix or close an issue should include a reference like `Closes #XXX`
|
||||
or `Fixes #XXX`, which will automatically close the issue when merged.
|
||||
|
||||
### Sign your work
|
||||
|
||||
The sign-off is a simple line at the end of the explanation for the
|
||||
patch, which certifies that you wrote it or otherwise have the right to
|
||||
pass it on as an open-source patch. The rules are pretty simple: if you
|
||||
can certify the below (from
|
||||
[developercertificate.org](http://developercertificate.org/)):
|
||||
|
||||
```
|
||||
Developer Certificate of Origin
|
||||
Version 1.1
|
||||
|
||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
||||
660 York Street, Suite 102,
|
||||
San Francisco, CA 94110 USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
|
||||
Developer's Certificate of Origin 1.1
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
```
|
||||
|
||||
then you just add a line to every git commit message:
|
||||
|
||||
Signed-off-by: Joe Smith <joe@gmail.com>
|
||||
|
||||
using your real name (sorry, no pseudonyms or anonymous contributions.)
|
||||
|
||||
You can add the sign off when creating the git commit via `git commit -s`.
|
||||
5
vendor/github.com/go-openapi/runtime/.gitignore
generated
vendored
5
vendor/github.com/go-openapi/runtime/.gitignore
generated
vendored
@@ -1,5 +0,0 @@
|
||||
secrets.yml
|
||||
coverage.out
|
||||
*.cov
|
||||
*.out
|
||||
playground
|
||||
24
vendor/github.com/go-openapi/runtime/.travis.yml
generated
vendored
24
vendor/github.com/go-openapi/runtime/.travis.yml
generated
vendored
@@ -1,24 +0,0 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.7.1
|
||||
install:
|
||||
- go get -u github.com/axw/gocov/gocov
|
||||
- go get -u gopkg.in/matm/v1/gocov-html
|
||||
- go get -u github.com/cee-dub/go-junit-report
|
||||
- go get -u github.com/stretchr/testify/assert
|
||||
- go get -u golang.org/x/net/context
|
||||
- go get -u gopkg.in/yaml.v2
|
||||
- go get -u github.com/gorilla/context
|
||||
- go get -u github.com/go-openapi/analysis
|
||||
- go get -u github.com/go-openapi/errors
|
||||
- go get -u github.com/go-openapi/loads
|
||||
- go get -u github.com/go-openapi/strfmt
|
||||
- go get -u github.com/go-openapi/validate
|
||||
- go get -u github.com/docker/go-units
|
||||
script:
|
||||
- ./hack/coverage
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
notifications:
|
||||
slack:
|
||||
secure: EmObnQuM9Mw8J9vpFaKKHqSMN4Wsr/A9+v7ewAD5cEhA0T1P4m7MbJMiJOhxUhj/X+BFh2DamW+P2lT8mybj5wg8wnkQ2BteKA8Tawi6f9PRw2NRheO8tAi8o/npLnlmet0kc93mn+oLuqHw36w4+j5mkOl2FghkfGiUVhwrhkCP7KXQN+3TU87e+/HzQumlJ3nsE+6terVxkH3PmaUTsS5ONaODZfuxFpfb7RsoEl3skHf6d+tr+1nViLxxly7558Nc33C+W1mr0qiEvMLZ+kJ/CpGWBJ6CUJM3jm6hNe2eMuIPwEK2hxZob8c7n22VPap4K6a0bBRoydoDXaba+2sD7Ym6ivDO/DVyL44VeBBLyIiIBylDGQdZH+6SoWm90Qe/i7tnY/T5Ao5igT8f3cfQY1c3EsTfqmlDfrhmACBmwSlgkdVBLTprHL63JMY24LWmh4jhxsmMRZhCL4dze8su1w6pLN/pD1pGHtKYCEVbdTmaM3PblNRFf12XB7qosmQsgUndH4Vq3bTbU0s1pKjeDhRyLvFzvR0TBbo0pDLEoF1A/i5GVFWa7yLZNUDudQERRh7qv/xBl2excIaQ1sV4DSVm7bAE9l6Kp+yeHQJW2uN6Y3X8wu9gB9nv9l5HBze7wh8KE6PyWAOLYYqZg9/sAtsv/2GcQqXcKFF1zcA=
|
||||
74
vendor/github.com/go-openapi/runtime/CODE_OF_CONDUCT.md
generated
vendored
74
vendor/github.com/go-openapi/runtime/CODE_OF_CONDUCT.md
generated
vendored
@@ -1,74 +0,0 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at ivan+abuse@flanders.co.nz. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
5
vendor/github.com/go-openapi/runtime/README.md
generated
vendored
5
vendor/github.com/go-openapi/runtime/README.md
generated
vendored
@@ -1,5 +0,0 @@
|
||||
# runtime [](https://travis-ci.org/go-openapi/runtime) [](https://codecov.io/gh/go-openapi/runtime) [](https://slackin.goswagger.io)
|
||||
|
||||
[](https://raw.githubusercontent.com/go-openapi/runtime/master/LICENSE) [](http://godoc.org/github.com/go-openapi/runtime)
|
||||
|
||||
The runtime component for use in codegeneration or as untyped usage.
|
||||
33
vendor/github.com/go-openapi/runtime/authinfo_test.go
generated
vendored
33
vendor/github.com/go-openapi/runtime/authinfo_test.go
generated
vendored
@@ -1,33 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAuthInfoWriter(t *testing.T) {
|
||||
hand := ClientAuthInfoWriterFunc(func(r ClientRequest, _ strfmt.Registry) error {
|
||||
r.SetHeaderParam("authorization", "Bearer the-token-goes-here")
|
||||
return nil
|
||||
})
|
||||
|
||||
tr := new(trw)
|
||||
hand.AuthenticateRequest(tr, nil)
|
||||
assert.Equal(t, "Bearer the-token-goes-here", tr.Headers.Get("Authorization"))
|
||||
}
|
||||
114
vendor/github.com/go-openapi/runtime/bytestream_test.go
generated
vendored
114
vendor/github.com/go-openapi/runtime/bytestream_test.go
generated
vendored
@@ -1,114 +0,0 @@
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestByteStreamConsumer(t *testing.T) {
|
||||
cons := ByteStreamConsumer()
|
||||
|
||||
expected := "the data for the stream to be sent over the wire"
|
||||
|
||||
// can consume as a Writer
|
||||
var b bytes.Buffer
|
||||
if assert.NoError(t, cons.Consume(bytes.NewBufferString(expected), &b)) {
|
||||
assert.Equal(t, expected, b.String())
|
||||
}
|
||||
|
||||
// can consume as an UnmarshalBinary
|
||||
var bu binaryUnmarshalDummy
|
||||
if assert.NoError(t, cons.Consume(bytes.NewBufferString(expected), &bu)) {
|
||||
assert.Equal(t, expected, bu.str)
|
||||
}
|
||||
|
||||
// can consume as a binary slice
|
||||
var bs []byte
|
||||
if assert.NoError(t, cons.Consume(bytes.NewBufferString(expected), &bs)) {
|
||||
assert.Equal(t, expected, string(bs))
|
||||
}
|
||||
type binarySlice []byte
|
||||
var bs2 binarySlice
|
||||
if assert.NoError(t, cons.Consume(bytes.NewBufferString(expected), &bs2)) {
|
||||
assert.Equal(t, expected, string(bs2))
|
||||
}
|
||||
|
||||
// passing in a nilslice wil result in an error
|
||||
var ns *[]byte
|
||||
assert.Error(t, cons.Consume(bytes.NewBufferString(expected), &ns))
|
||||
|
||||
// passing in nil wil result in an error as well
|
||||
assert.Error(t, cons.Consume(bytes.NewBufferString(expected), nil))
|
||||
|
||||
// a reader who results in an error, will make it fail
|
||||
assert.Error(t, cons.Consume(new(nopReader), &bu))
|
||||
assert.Error(t, cons.Consume(new(nopReader), &bs))
|
||||
|
||||
// the readers can also not be nil
|
||||
assert.Error(t, cons.Consume(nil, &bs))
|
||||
}
|
||||
|
||||
type binaryUnmarshalDummy struct {
|
||||
str string
|
||||
}
|
||||
|
||||
func (b *binaryUnmarshalDummy) UnmarshalBinary(bytes []byte) error {
|
||||
if len(bytes) == 0 {
|
||||
return errors.New("no text given")
|
||||
}
|
||||
|
||||
b.str = string(bytes)
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestByteStreamProducer(t *testing.T) {
|
||||
cons := ByteStreamProducer()
|
||||
expected := "the data for the stream to be sent over the wire"
|
||||
|
||||
var rdr bytes.Buffer
|
||||
|
||||
// can produce using a reader
|
||||
if assert.NoError(t, cons.Produce(&rdr, bytes.NewBufferString(expected))) {
|
||||
assert.Equal(t, expected, rdr.String())
|
||||
rdr.Reset()
|
||||
}
|
||||
|
||||
// can produce using a binary marshaller
|
||||
if assert.NoError(t, cons.Produce(&rdr, &binaryMarshalDummy{expected})) {
|
||||
assert.Equal(t, expected, rdr.String())
|
||||
rdr.Reset()
|
||||
}
|
||||
|
||||
// binary slices can also be used to produce
|
||||
if assert.NoError(t, cons.Produce(&rdr, []byte(expected))) {
|
||||
assert.Equal(t, expected, rdr.String())
|
||||
rdr.Reset()
|
||||
}
|
||||
type binarySlice []byte
|
||||
if assert.NoError(t, cons.Produce(&rdr, binarySlice(expected))) {
|
||||
assert.Equal(t, expected, rdr.String())
|
||||
rdr.Reset()
|
||||
}
|
||||
|
||||
// when binaryMarshal data is used, its potential error gets propagated
|
||||
assert.Error(t, cons.Produce(&rdr, new(binaryMarshalDummy)))
|
||||
// nil data should never be accepted either
|
||||
assert.Error(t, cons.Produce(&rdr, nil))
|
||||
// nil readers should also never be acccepted
|
||||
assert.Error(t, cons.Produce(nil, bytes.NewBufferString(expected)))
|
||||
}
|
||||
|
||||
type binaryMarshalDummy struct {
|
||||
str string
|
||||
}
|
||||
|
||||
func (b *binaryMarshalDummy) MarshalBinary() ([]byte, error) {
|
||||
if len(b.str) == 0 {
|
||||
return nil, errors.New("no text set")
|
||||
}
|
||||
|
||||
return []byte(b.str), nil
|
||||
}
|
||||
65
vendor/github.com/go-openapi/runtime/client/auth_info_test.go
generated
vendored
65
vendor/github.com/go-openapi/runtime/client/auth_info_test.go
generated
vendored
@@ -1,65 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestBasicAuth(t *testing.T) {
|
||||
r, _ := newRequest("GET", "/", nil)
|
||||
|
||||
writer := BasicAuth("someone", "with a password")
|
||||
writer.AuthenticateRequest(r, nil)
|
||||
|
||||
req := new(http.Request)
|
||||
req.Header = make(http.Header)
|
||||
req.Header.Set("Authorization", r.header.Get("Authorization"))
|
||||
usr, pw, ok := req.BasicAuth()
|
||||
if assert.True(t, ok) {
|
||||
assert.Equal(t, "someone", usr)
|
||||
assert.Equal(t, "with a password", pw)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPIKeyAuth_Query(t *testing.T) {
|
||||
r, _ := newRequest("GET", "/", nil)
|
||||
|
||||
writer := APIKeyAuth("api_key", "query", "the-shared-key")
|
||||
writer.AuthenticateRequest(r, nil)
|
||||
|
||||
assert.Equal(t, "the-shared-key", r.query.Get("api_key"))
|
||||
}
|
||||
|
||||
func TestAPIKeyAuth_Header(t *testing.T) {
|
||||
r, _ := newRequest("GET", "/", nil)
|
||||
|
||||
writer := APIKeyAuth("x-api-token", "header", "the-shared-key")
|
||||
writer.AuthenticateRequest(r, nil)
|
||||
|
||||
assert.Equal(t, "the-shared-key", r.header.Get("x-api-token"))
|
||||
}
|
||||
|
||||
func TestBearerTokenAuth(t *testing.T) {
|
||||
r, _ := newRequest("GET", "/", nil)
|
||||
|
||||
writer := BearerToken("the-shared-token")
|
||||
writer.AuthenticateRequest(r, nil)
|
||||
|
||||
assert.Equal(t, "Bearer the-shared-token", r.header.Get("Authorization"))
|
||||
}
|
||||
244
vendor/github.com/go-openapi/runtime/client/request_test.go
generated
vendored
244
vendor/github.com/go-openapi/runtime/client/request_test.go
generated
vendored
@@ -1,244 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"io/ioutil"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var testProducers = map[string]runtime.Producer{
|
||||
runtime.JSONMime: runtime.JSONProducer(),
|
||||
runtime.XMLMime: runtime.XMLProducer(),
|
||||
runtime.TextMime: runtime.TextProducer(),
|
||||
}
|
||||
|
||||
func TestBuildRequest_SetHeaders(t *testing.T) {
|
||||
r, _ := newRequest("GET", "/flats/{id}/", nil)
|
||||
// single value
|
||||
r.SetHeaderParam("X-Rate-Limit", "500")
|
||||
assert.Equal(t, "500", r.header.Get("X-Rate-Limit"))
|
||||
r.SetHeaderParam("X-Rate-Limit", "400")
|
||||
assert.Equal(t, "400", r.header.Get("X-Rate-Limit"))
|
||||
|
||||
// multi value
|
||||
r.SetHeaderParam("X-Accepts", "json", "xml", "yaml")
|
||||
assert.EqualValues(t, []string{"json", "xml", "yaml"}, r.header["X-Accepts"])
|
||||
}
|
||||
|
||||
func TestBuildRequest_SetPath(t *testing.T) {
|
||||
r, _ := newRequest("GET", "/flats/{id}/?hello=world", nil)
|
||||
|
||||
r.SetPathParam("id", "1345")
|
||||
assert.Equal(t, "1345", r.pathParams["id"])
|
||||
}
|
||||
|
||||
func TestBuildRequest_SetQuery(t *testing.T) {
|
||||
r, _ := newRequest("GET", "/flats/{id}/", nil)
|
||||
|
||||
// single value
|
||||
r.SetQueryParam("hello", "there")
|
||||
assert.Equal(t, "there", r.query.Get("hello"))
|
||||
|
||||
// multi value
|
||||
r.SetQueryParam("goodbye", "cruel", "world")
|
||||
assert.Equal(t, []string{"cruel", "world"}, r.query["goodbye"])
|
||||
}
|
||||
|
||||
func TestBuildRequest_SetForm(t *testing.T) {
|
||||
// non-multipart
|
||||
r, _ := newRequest("POST", "/flats", nil)
|
||||
r.SetFormParam("hello", "world")
|
||||
assert.Equal(t, "world", r.formFields.Get("hello"))
|
||||
r.SetFormParam("goodbye", "cruel", "world")
|
||||
assert.Equal(t, []string{"cruel", "world"}, r.formFields["goodbye"])
|
||||
}
|
||||
|
||||
func TestBuildRequest_SetFile(t *testing.T) {
|
||||
// needs to convert form to multipart
|
||||
r, _ := newRequest("POST", "/flats/{id}/image", nil)
|
||||
// error if it isn't there
|
||||
err := r.SetFileParam("not there", os.NewFile(0, "./i-dont-exist"))
|
||||
assert.Error(t, err)
|
||||
// error if it isn't a file
|
||||
err = r.SetFileParam("directory", os.NewFile(0, "../client"))
|
||||
assert.Error(t, err)
|
||||
// success adds it to the map
|
||||
err = r.SetFileParam("file", mustGetFile("./runtime.go"))
|
||||
if assert.NoError(t, err) {
|
||||
fl, ok := r.fileFields["file"]
|
||||
if assert.True(t, ok) {
|
||||
assert.Equal(t, "runtime.go", filepath.Base(fl.Name()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mustGetFile(path string) *os.File {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func TestBuildRequest_SetBody(t *testing.T) {
|
||||
r, _ := newRequest("GET", "/flats/{id}/?hello=world", nil)
|
||||
bd := []struct{ Name, Hobby string }{{"Tom", "Organ trail"}, {"John", "Bird watching"}}
|
||||
|
||||
r.SetBodyParam(bd)
|
||||
assert.Equal(t, bd, r.payload)
|
||||
}
|
||||
|
||||
func TestBuildRequest_BuildHTTP_Payload(t *testing.T) {
|
||||
bd := []struct{ Name, Hobby string }{{"Tom", "Organ trail"}, {"John", "Bird watching"}}
|
||||
reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
req.SetBodyParam(bd)
|
||||
req.SetQueryParam("hello", "world")
|
||||
req.SetPathParam("id", "1234")
|
||||
req.SetHeaderParam("X-Rate-Limit", "200")
|
||||
return nil
|
||||
})
|
||||
r, _ := newRequest("GET", "/flats/{id}/", reqWrtr)
|
||||
r.SetHeaderParam(runtime.HeaderContentType, runtime.JSONMime)
|
||||
|
||||
req, err := r.BuildHTTP(runtime.JSONMime, testProducers, nil)
|
||||
if assert.NoError(t, err) && assert.NotNil(t, req) {
|
||||
assert.Equal(t, "200", req.Header.Get("x-rate-limit"))
|
||||
assert.Equal(t, "world", req.URL.Query().Get("hello"))
|
||||
assert.Equal(t, "/flats/1234/", req.URL.Path)
|
||||
expectedBody, _ := json.Marshal(bd)
|
||||
actualBody, _ := ioutil.ReadAll(req.Body)
|
||||
assert.Equal(t, append(expectedBody, '\n'), actualBody)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildRequest_BuildHTTP_XMLPayload(t *testing.T) {
|
||||
bd := []struct {
|
||||
XMLName xml.Name `xml:"person"`
|
||||
Name string `xml:"name"`
|
||||
Hobby string `xml:"hobby"`
|
||||
}{{xml.Name{}, "Tom", "Organ trail"}, {xml.Name{}, "John", "Bird watching"}}
|
||||
reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
req.SetBodyParam(bd)
|
||||
req.SetQueryParam("hello", "world")
|
||||
req.SetPathParam("id", "1234")
|
||||
req.SetHeaderParam("X-Rate-Limit", "200")
|
||||
return nil
|
||||
})
|
||||
r, _ := newRequest("GET", "/flats/{id}/", reqWrtr)
|
||||
r.SetHeaderParam(runtime.HeaderContentType, runtime.XMLMime)
|
||||
|
||||
req, err := r.BuildHTTP(runtime.XMLMime, testProducers, nil)
|
||||
if assert.NoError(t, err) && assert.NotNil(t, req) {
|
||||
assert.Equal(t, "200", req.Header.Get("x-rate-limit"))
|
||||
assert.Equal(t, "world", req.URL.Query().Get("hello"))
|
||||
assert.Equal(t, "/flats/1234/", req.URL.Path)
|
||||
expectedBody, _ := xml.Marshal(bd)
|
||||
actualBody, _ := ioutil.ReadAll(req.Body)
|
||||
assert.Equal(t, expectedBody, actualBody)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildRequest_BuildHTTP_TextPayload(t *testing.T) {
|
||||
bd := "Tom: Organ trail; John: Bird watching"
|
||||
reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
req.SetBodyParam(bd)
|
||||
req.SetQueryParam("hello", "world")
|
||||
req.SetPathParam("id", "1234")
|
||||
req.SetHeaderParam("X-Rate-Limit", "200")
|
||||
return nil
|
||||
})
|
||||
r, _ := newRequest("GET", "/flats/{id}/", reqWrtr)
|
||||
r.SetHeaderParam(runtime.HeaderContentType, runtime.TextMime)
|
||||
|
||||
req, err := r.BuildHTTP(runtime.TextMime, testProducers, nil)
|
||||
if assert.NoError(t, err) && assert.NotNil(t, req) {
|
||||
assert.Equal(t, "200", req.Header.Get("x-rate-limit"))
|
||||
assert.Equal(t, "world", req.URL.Query().Get("hello"))
|
||||
assert.Equal(t, "/flats/1234/", req.URL.Path)
|
||||
expectedBody := []byte(bd)
|
||||
actualBody, _ := ioutil.ReadAll(req.Body)
|
||||
assert.Equal(t, expectedBody, actualBody)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildRequest_BuildHTTP_Form(t *testing.T) {
|
||||
reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
req.SetFormParam("something", "some value")
|
||||
req.SetQueryParam("hello", "world")
|
||||
req.SetPathParam("id", "1234")
|
||||
req.SetHeaderParam("X-Rate-Limit", "200")
|
||||
return nil
|
||||
})
|
||||
r, _ := newRequest("GET", "/flats/{id}/", reqWrtr)
|
||||
r.SetHeaderParam(runtime.HeaderContentType, runtime.JSONMime)
|
||||
|
||||
req, err := r.BuildHTTP(runtime.JSONMime, testProducers, nil)
|
||||
if assert.NoError(t, err) && assert.NotNil(t, req) {
|
||||
assert.Equal(t, "200", req.Header.Get("x-rate-limit"))
|
||||
assert.Equal(t, "world", req.URL.Query().Get("hello"))
|
||||
assert.Equal(t, "/flats/1234/", req.URL.Path)
|
||||
expected := []byte("something=some+value")
|
||||
actual, _ := ioutil.ReadAll(req.Body)
|
||||
assert.Equal(t, expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildRequest_BuildHTTP_Files(t *testing.T) {
|
||||
cont, _ := ioutil.ReadFile("./runtime.go")
|
||||
reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
req.SetFormParam("something", "some value")
|
||||
req.SetFileParam("file", mustGetFile("./runtime.go"))
|
||||
req.SetQueryParam("hello", "world")
|
||||
req.SetPathParam("id", "1234")
|
||||
req.SetHeaderParam("X-Rate-Limit", "200")
|
||||
return nil
|
||||
})
|
||||
r, _ := newRequest("GET", "/flats/{id}/", reqWrtr)
|
||||
r.SetHeaderParam(runtime.HeaderContentType, runtime.JSONMime)
|
||||
req, err := r.BuildHTTP(runtime.JSONMime, testProducers, nil)
|
||||
if assert.NoError(t, err) && assert.NotNil(t, req) {
|
||||
assert.Equal(t, "200", req.Header.Get("x-rate-limit"))
|
||||
assert.Equal(t, "world", req.URL.Query().Get("hello"))
|
||||
assert.Equal(t, "/flats/1234/", req.URL.Path)
|
||||
mediaType, params, err := mime.ParseMediaType(req.Header.Get(runtime.HeaderContentType))
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, runtime.MultipartFormMime, mediaType)
|
||||
boundary := params["boundary"]
|
||||
mr := multipart.NewReader(req.Body, boundary)
|
||||
defer req.Body.Close()
|
||||
frm, err := mr.ReadForm(1 << 20)
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, "some value", frm.Value["something"][0])
|
||||
mpff := frm.File["file"][0]
|
||||
mpf, _ := mpff.Open()
|
||||
defer mpf.Close()
|
||||
assert.Equal(t, "runtime.go", mpff.Filename)
|
||||
actual, _ := ioutil.ReadAll(mpf)
|
||||
assert.Equal(t, cont, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
40
vendor/github.com/go-openapi/runtime/client/response_test.go
generated
vendored
40
vendor/github.com/go-openapi/runtime/client/response_test.go
generated
vendored
@@ -1,40 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestResponse(t *testing.T) {
|
||||
under := new(http.Response)
|
||||
under.Status = "the status message"
|
||||
under.StatusCode = 392
|
||||
under.Header = make(http.Header)
|
||||
under.Header.Set("Blah", "blah blah")
|
||||
under.Body = ioutil.NopCloser(bytes.NewBufferString("some content"))
|
||||
|
||||
var resp runtime.ClientResponse = response{under}
|
||||
assert.EqualValues(t, under.StatusCode, resp.Code())
|
||||
assert.Equal(t, under.Status, resp.Message())
|
||||
assert.Equal(t, "blah blah", resp.GetHeader("blah"))
|
||||
assert.Equal(t, under.Body, resp.Body())
|
||||
}
|
||||
722
vendor/github.com/go-openapi/runtime/client/runtime_test.go
generated
vendored
722
vendor/github.com/go-openapi/runtime/client/runtime_test.go
generated
vendored
@@ -1,722 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// task This describes a task. Tasks require a content property to be set.
|
||||
type task struct {
|
||||
|
||||
// Completed
|
||||
Completed bool `json:"completed" xml:"completed"`
|
||||
|
||||
// Content Task content can contain [GFM](https://help.github.com/articles/github-flavored-markdown/).
|
||||
Content string `json:"content" xml:"content"`
|
||||
|
||||
// ID This id property is autogenerated when a task is created.
|
||||
ID int64 `json:"id" xml:"id"`
|
||||
}
|
||||
|
||||
func TestRuntime_TLSAuthConfig(t *testing.T) {
|
||||
var opts TLSClientOptions
|
||||
opts.CA = "../fixtures/certs/myCA.crt"
|
||||
opts.Key = "../fixtures/certs/myclient.key"
|
||||
opts.Certificate = "../fixtures/certs/myclient.crt"
|
||||
opts.ServerName = "somewhere"
|
||||
|
||||
cfg, err := TLSClientAuth(opts)
|
||||
if assert.NoError(t, err) {
|
||||
if assert.NotNil(t, cfg) {
|
||||
assert.Len(t, cfg.Certificates, 1)
|
||||
assert.NotNil(t, cfg.RootCAs)
|
||||
assert.Equal(t, "somewhere", cfg.ServerName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRuntime_Concurrent(t *testing.T) {
|
||||
// test that it can make a simple request
|
||||
// and get the response for it.
|
||||
// defaults all the way down
|
||||
result := []task{
|
||||
{false, "task 1 content", 1},
|
||||
{false, "task 2 content", 2},
|
||||
}
|
||||
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime)
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
jsongen := json.NewEncoder(rw)
|
||||
jsongen.Encode(result)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
hu, _ := url.Parse(server.URL)
|
||||
rt := New(hu.Host, "/", []string{"http"})
|
||||
resCC := make(chan interface{})
|
||||
errCC := make(chan error)
|
||||
var res interface{}
|
||||
var err error
|
||||
|
||||
for j := 0; j < 6; j++ {
|
||||
go func() {
|
||||
resC := make(chan interface{})
|
||||
errC := make(chan error)
|
||||
|
||||
go func() {
|
||||
var resp interface{}
|
||||
var errp error
|
||||
for i := 0; i < 3; i++ {
|
||||
resp, errp = rt.Submit(&runtime.ClientOperation{
|
||||
ID: "getTasks",
|
||||
Method: "GET",
|
||||
PathPattern: "/",
|
||||
Params: rwrtr,
|
||||
Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
if response.Code() == 200 {
|
||||
var result []task
|
||||
if err := consumer.Consume(response.Body(), &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
return nil, errors.New("Generic error")
|
||||
}),
|
||||
})
|
||||
<-time.After(100 * time.Millisecond)
|
||||
}
|
||||
resC <- resp
|
||||
errC <- errp
|
||||
}()
|
||||
resCC <- <-resC
|
||||
errCC <- <-errC
|
||||
}()
|
||||
}
|
||||
|
||||
c := 6
|
||||
for c > 0 {
|
||||
res = <-resCC
|
||||
err = <-errCC
|
||||
c--
|
||||
}
|
||||
|
||||
if assert.NoError(t, err) {
|
||||
assert.IsType(t, []task{}, res)
|
||||
actual := res.([]task)
|
||||
assert.EqualValues(t, result, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRuntime_Canary(t *testing.T) {
|
||||
// test that it can make a simple request
|
||||
// and get the response for it.
|
||||
// defaults all the way down
|
||||
result := []task{
|
||||
{false, "task 1 content", 1},
|
||||
{false, "task 2 content", 2},
|
||||
}
|
||||
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime)
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
jsongen := json.NewEncoder(rw)
|
||||
jsongen.Encode(result)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
hu, _ := url.Parse(server.URL)
|
||||
rt := New(hu.Host, "/", []string{"http"})
|
||||
res, err := rt.Submit(&runtime.ClientOperation{
|
||||
ID: "getTasks",
|
||||
Method: "GET",
|
||||
PathPattern: "/",
|
||||
Params: rwrtr,
|
||||
Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
if response.Code() == 200 {
|
||||
var result []task
|
||||
if err := consumer.Consume(response.Body(), &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
return nil, errors.New("Generic error")
|
||||
}),
|
||||
})
|
||||
|
||||
if assert.NoError(t, err) {
|
||||
assert.IsType(t, []task{}, res)
|
||||
actual := res.([]task)
|
||||
assert.EqualValues(t, result, actual)
|
||||
}
|
||||
}
|
||||
|
||||
type tasks struct {
|
||||
Tasks []task `xml:"task"`
|
||||
}
|
||||
|
||||
func TestRuntime_XMLCanary(t *testing.T) {
|
||||
// test that it can make a simple XML request
|
||||
// and get the response for it.
|
||||
result := tasks{
|
||||
Tasks: []task{
|
||||
{false, "task 1 content", 1},
|
||||
{false, "task 2 content", 2},
|
||||
},
|
||||
}
|
||||
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
rw.Header().Add(runtime.HeaderContentType, runtime.XMLMime)
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
xmlgen := xml.NewEncoder(rw)
|
||||
xmlgen.Encode(result)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
hu, _ := url.Parse(server.URL)
|
||||
rt := New(hu.Host, "/", []string{"http"})
|
||||
res, err := rt.Submit(&runtime.ClientOperation{
|
||||
ID: "getTasks",
|
||||
Method: "GET",
|
||||
PathPattern: "/",
|
||||
Params: rwrtr,
|
||||
Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
if response.Code() == 200 {
|
||||
var result tasks
|
||||
if err := consumer.Consume(response.Body(), &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
return nil, errors.New("Generic error")
|
||||
}),
|
||||
})
|
||||
|
||||
if assert.NoError(t, err) {
|
||||
assert.IsType(t, tasks{}, res)
|
||||
actual := res.(tasks)
|
||||
assert.EqualValues(t, result, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRuntime_TextCanary(t *testing.T) {
|
||||
// test that it can make a simple text request
|
||||
// and get the response for it.
|
||||
result := "1: task 1 content; 2: task 2 content"
|
||||
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
rw.Header().Add(runtime.HeaderContentType, runtime.TextMime)
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
rw.Write([]byte(result))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
hu, _ := url.Parse(server.URL)
|
||||
rt := New(hu.Host, "/", []string{"http"})
|
||||
res, err := rt.Submit(&runtime.ClientOperation{
|
||||
ID: "getTasks",
|
||||
Method: "GET",
|
||||
PathPattern: "/",
|
||||
Params: rwrtr,
|
||||
Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
if response.Code() == 200 {
|
||||
var result string
|
||||
if err := consumer.Consume(response.Body(), &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
return nil, errors.New("Generic error")
|
||||
}),
|
||||
})
|
||||
|
||||
if assert.NoError(t, err) {
|
||||
assert.IsType(t, "", res)
|
||||
actual := res.(string)
|
||||
assert.EqualValues(t, result, actual)
|
||||
}
|
||||
}
|
||||
|
||||
type roundTripperFunc func(*http.Request) (*http.Response, error)
|
||||
|
||||
func (fn roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
return fn(req)
|
||||
}
|
||||
|
||||
func TestRuntime_CustomTransport(t *testing.T) {
|
||||
rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error {
|
||||
return nil
|
||||
})
|
||||
result := []task{
|
||||
{false, "task 1 content", 1},
|
||||
{false, "task 2 content", 2},
|
||||
}
|
||||
|
||||
rt := New("localhost:3245", "/", []string{"ws", "wss", "https"})
|
||||
rt.Transport = roundTripperFunc(func(req *http.Request) (*http.Response, error) {
|
||||
if req.URL.Scheme != "https" {
|
||||
return nil, errors.New("this was not a https request")
|
||||
}
|
||||
var resp http.Response
|
||||
resp.StatusCode = 200
|
||||
resp.Header = make(http.Header)
|
||||
resp.Header.Set("content-type", "application/json")
|
||||
buf := bytes.NewBuffer(nil)
|
||||
enc := json.NewEncoder(buf)
|
||||
enc.Encode(result)
|
||||
resp.Body = ioutil.NopCloser(buf)
|
||||
return &resp, nil
|
||||
})
|
||||
|
||||
res, err := rt.Submit(&runtime.ClientOperation{
|
||||
ID: "getTasks",
|
||||
Method: "GET",
|
||||
PathPattern: "/",
|
||||
Schemes: []string{"ws", "wss", "https"},
|
||||
Params: rwrtr,
|
||||
Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
if response.Code() == 200 {
|
||||
var result []task
|
||||
if err := consumer.Consume(response.Body(), &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
return nil, errors.New("Generic error")
|
||||
}),
|
||||
})
|
||||
|
||||
if assert.NoError(t, err) {
|
||||
assert.IsType(t, []task{}, res)
|
||||
actual := res.([]task)
|
||||
assert.EqualValues(t, result, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRuntime_CustomCookieJar(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
authenticated := false
|
||||
for _, cookie := range req.Cookies() {
|
||||
if cookie.Name == "sessionid" && cookie.Value == "abc" {
|
||||
authenticated = true
|
||||
}
|
||||
}
|
||||
if !authenticated {
|
||||
username, password, ok := req.BasicAuth()
|
||||
if ok && username == "username" && password == "password" {
|
||||
authenticated = true
|
||||
http.SetCookie(rw, &http.Cookie{Name: "sessionid", Value: "abc"})
|
||||
}
|
||||
}
|
||||
if authenticated {
|
||||
rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime)
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
jsongen := json.NewEncoder(rw)
|
||||
jsongen.Encode([]task{})
|
||||
} else {
|
||||
rw.WriteHeader(http.StatusUnauthorized)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
hu, _ := url.Parse(server.URL)
|
||||
rt := New(hu.Host, "/", []string{"http"})
|
||||
rt.Jar, _ = cookiejar.New(nil)
|
||||
|
||||
submit := func(authInfo runtime.ClientAuthInfoWriter) {
|
||||
_, err := rt.Submit(&runtime.ClientOperation{
|
||||
ID: "getTasks",
|
||||
Method: "GET",
|
||||
PathPattern: "/",
|
||||
Params: rwrtr,
|
||||
AuthInfo: authInfo,
|
||||
Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
if response.Code() == 200 {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errors.New("Generic error")
|
||||
}),
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
submit(BasicAuth("username", "password"))
|
||||
submit(nil)
|
||||
}
|
||||
|
||||
func TestRuntime_AuthCanary(t *testing.T) {
|
||||
// test that it can make a simple request
|
||||
// and get the response for it.
|
||||
// defaults all the way down
|
||||
result := []task{
|
||||
{false, "task 1 content", 1},
|
||||
{false, "task 2 content", 2},
|
||||
}
|
||||
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Header.Get("Authorization") != "Bearer the-super-secret-token" {
|
||||
rw.WriteHeader(400)
|
||||
return
|
||||
}
|
||||
rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime)
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
jsongen := json.NewEncoder(rw)
|
||||
jsongen.Encode(result)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
hu, _ := url.Parse(server.URL)
|
||||
|
||||
rt := New(hu.Host, "/", []string{"http"})
|
||||
res, err := rt.Submit(&runtime.ClientOperation{
|
||||
ID: "getTasks",
|
||||
Params: rwrtr,
|
||||
Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
if response.Code() == 200 {
|
||||
var result []task
|
||||
if err := consumer.Consume(response.Body(), &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
return nil, errors.New("Generic error")
|
||||
}),
|
||||
AuthInfo: BearerToken("the-super-secret-token"),
|
||||
})
|
||||
|
||||
if assert.NoError(t, err) {
|
||||
assert.IsType(t, []task{}, res)
|
||||
actual := res.([]task)
|
||||
assert.EqualValues(t, result, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRuntime_PickConsumer(t *testing.T) {
|
||||
result := []task{
|
||||
{false, "task 1 content", 1},
|
||||
{false, "task 2 content", 2},
|
||||
}
|
||||
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Header.Get("Content-Type") != "application/octet-stream" {
|
||||
rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime+";charset=utf-8")
|
||||
rw.WriteHeader(400)
|
||||
return
|
||||
}
|
||||
rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime+";charset=utf-8")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
jsongen := json.NewEncoder(rw)
|
||||
jsongen.Encode(result)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error {
|
||||
req.SetBodyParam(bytes.NewBufferString("hello"))
|
||||
return nil
|
||||
})
|
||||
|
||||
hu, _ := url.Parse(server.URL)
|
||||
rt := New(hu.Host, "/", []string{"http"})
|
||||
res, err := rt.Submit(&runtime.ClientOperation{
|
||||
ID: "getTasks",
|
||||
Method: "POST",
|
||||
PathPattern: "/",
|
||||
Schemes: []string{"http"},
|
||||
ConsumesMediaTypes: []string{"application/octet-stream"},
|
||||
Params: rwrtr,
|
||||
Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
if response.Code() == 200 {
|
||||
var result []task
|
||||
if err := consumer.Consume(response.Body(), &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
return nil, errors.New("Generic error")
|
||||
}),
|
||||
AuthInfo: BearerToken("the-super-secret-token"),
|
||||
})
|
||||
|
||||
if assert.NoError(t, err) {
|
||||
assert.IsType(t, []task{}, res)
|
||||
actual := res.([]task)
|
||||
assert.EqualValues(t, result, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRuntime_ContentTypeCanary(t *testing.T) {
|
||||
// test that it can make a simple request
|
||||
// and get the response for it.
|
||||
// defaults all the way down
|
||||
result := []task{
|
||||
{false, "task 1 content", 1},
|
||||
{false, "task 2 content", 2},
|
||||
}
|
||||
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Header.Get("Authorization") != "Bearer the-super-secret-token" {
|
||||
rw.WriteHeader(400)
|
||||
return
|
||||
}
|
||||
rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime+";charset=utf-8")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
jsongen := json.NewEncoder(rw)
|
||||
jsongen.Encode(result)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
hu, _ := url.Parse(server.URL)
|
||||
rt := New(hu.Host, "/", []string{"http"})
|
||||
rt.do = nil
|
||||
res, err := rt.Submit(&runtime.ClientOperation{
|
||||
ID: "getTasks",
|
||||
Method: "GET",
|
||||
PathPattern: "/",
|
||||
Schemes: []string{"http"},
|
||||
Params: rwrtr,
|
||||
Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
if response.Code() == 200 {
|
||||
var result []task
|
||||
if err := consumer.Consume(response.Body(), &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
return nil, errors.New("Generic error")
|
||||
}),
|
||||
AuthInfo: BearerToken("the-super-secret-token"),
|
||||
})
|
||||
|
||||
if assert.NoError(t, err) {
|
||||
assert.IsType(t, []task{}, res)
|
||||
actual := res.([]task)
|
||||
assert.EqualValues(t, result, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRuntime_ChunkedResponse(t *testing.T) {
|
||||
// test that it can make a simple request
|
||||
// and get the response for it.
|
||||
// defaults all the way down
|
||||
result := []task{
|
||||
{false, "task 1 content", 1},
|
||||
{false, "task 2 content", 2},
|
||||
}
|
||||
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Header.Get("Authorization") != "Bearer the-super-secret-token" {
|
||||
rw.WriteHeader(400)
|
||||
return
|
||||
}
|
||||
rw.Header().Add(runtime.HeaderTransferEncoding, "chunked")
|
||||
rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime+";charset=utf-8")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
jsongen := json.NewEncoder(rw)
|
||||
jsongen.Encode(result)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
//specDoc, err := spec.Load("../../fixtures/codegen/todolist.simple.yml")
|
||||
hu, _ := url.Parse(server.URL)
|
||||
|
||||
rt := New(hu.Host, "/", []string{"http"})
|
||||
res, err := rt.Submit(&runtime.ClientOperation{
|
||||
ID: "getTasks",
|
||||
Method: "GET",
|
||||
PathPattern: "/",
|
||||
Schemes: []string{"http"},
|
||||
Params: rwrtr,
|
||||
Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
if response.Code() == 200 {
|
||||
var result []task
|
||||
if err := consumer.Consume(response.Body(), &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
return nil, errors.New("Generic error")
|
||||
}),
|
||||
AuthInfo: BearerToken("the-super-secret-token"),
|
||||
})
|
||||
|
||||
if assert.NoError(t, err) {
|
||||
assert.IsType(t, []task{}, res)
|
||||
actual := res.([]task)
|
||||
assert.EqualValues(t, result, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRuntime_DebugValue(t *testing.T) {
|
||||
original := os.Getenv("DEBUG")
|
||||
|
||||
// Emtpy DEBUG means Debug is False
|
||||
os.Setenv("DEBUG", "")
|
||||
runtime := New("", "/", []string{"https"})
|
||||
assert.False(t, runtime.Debug)
|
||||
|
||||
// Non-Empty Debug means Debug is True
|
||||
|
||||
os.Setenv("DEBUG", "1")
|
||||
runtime = New("", "/", []string{"https"})
|
||||
assert.True(t, runtime.Debug)
|
||||
|
||||
os.Setenv("DEBUG", "true")
|
||||
runtime = New("", "/", []string{"https"})
|
||||
assert.True(t, runtime.Debug)
|
||||
|
||||
os.Setenv("DEBUG", "foo")
|
||||
runtime = New("", "/", []string{"https"})
|
||||
assert.True(t, runtime.Debug)
|
||||
|
||||
// Make sure DEBUG is initial value once again
|
||||
os.Setenv("DEBUG", original)
|
||||
}
|
||||
|
||||
func TestRuntime_OverrideScheme(t *testing.T) {
|
||||
runtime := New("", "/", []string{"https"})
|
||||
sch := runtime.pickScheme([]string{"http"})
|
||||
assert.Equal(t, "https", sch)
|
||||
}
|
||||
|
||||
func TestRuntime_OverrideClient(t *testing.T) {
|
||||
client := &http.Client{}
|
||||
runtime := NewWithClient("", "/", []string{"https"}, client)
|
||||
var i int
|
||||
runtime.clientOnce.Do(func() { i++ })
|
||||
assert.Equal(t, client, runtime.client)
|
||||
assert.Equal(t, 0, i)
|
||||
}
|
||||
|
||||
func TestRuntime_OverrideClientOperation(t *testing.T) {
|
||||
client := &http.Client{}
|
||||
rt := NewWithClient("", "/", []string{"https"}, client)
|
||||
var i int
|
||||
rt.clientOnce.Do(func() { i++ })
|
||||
assert.Equal(t, client, rt.client)
|
||||
assert.Equal(t, 0, i)
|
||||
|
||||
var seen *http.Client
|
||||
rt.do = func(_ context.Context, cl *http.Client, _ *http.Request) (*http.Response, error) {
|
||||
seen = cl
|
||||
res := new(http.Response)
|
||||
res.StatusCode = 200
|
||||
res.Body = ioutil.NopCloser(bytes.NewBufferString("OK"))
|
||||
return res, nil
|
||||
}
|
||||
|
||||
client2 := new(http.Client)
|
||||
client2.Timeout = 3 * time.Second
|
||||
if assert.NotEqual(t, client, client2) {
|
||||
_, err := rt.Submit(&runtime.ClientOperation{
|
||||
Client: client2,
|
||||
Params: runtime.ClientRequestWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error {
|
||||
return nil
|
||||
}),
|
||||
Reader: runtime.ClientResponseReaderFunc(func(_ runtime.ClientResponse, _ runtime.Consumer) (interface{}, error) {
|
||||
return nil, nil
|
||||
}),
|
||||
})
|
||||
if assert.NoError(t, err) {
|
||||
|
||||
assert.Equal(t, client2, seen)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRuntime_PreserveTrailingSlash(t *testing.T) {
|
||||
var redirected bool
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime+";charset=utf-8")
|
||||
|
||||
if req.URL.Path == "/api/tasks" {
|
||||
redirected = true
|
||||
return
|
||||
}
|
||||
if req.URL.Path == "/api/tasks/" {
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
hu, _ := url.Parse(server.URL)
|
||||
|
||||
rt := New(hu.Host, "/", []string{"http"})
|
||||
|
||||
rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
_, err := rt.Submit(&runtime.ClientOperation{
|
||||
ID: "getTasks",
|
||||
Method: "GET",
|
||||
PathPattern: "/api/tasks/",
|
||||
Params: rwrtr,
|
||||
Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
if redirected {
|
||||
return nil, errors.New("expected Submit to preserve trailing slashes - this caused a redirect")
|
||||
}
|
||||
if response.Code() == http.StatusOK {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errors.New("Generic error")
|
||||
}),
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
68
vendor/github.com/go-openapi/runtime/client_request_test.go
generated
vendored
68
vendor/github.com/go-openapi/runtime/client_request_test.go
generated
vendored
@@ -1,68 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type trw struct {
|
||||
Headers http.Header
|
||||
Body interface{}
|
||||
}
|
||||
|
||||
func (t *trw) SetHeaderParam(name string, values ...string) error {
|
||||
if t.Headers == nil {
|
||||
t.Headers = make(http.Header)
|
||||
}
|
||||
t.Headers.Set(name, values[0])
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *trw) SetQueryParam(_ string, _ ...string) error { return nil }
|
||||
|
||||
func (t *trw) SetFormParam(_ string, _ ...string) error { return nil }
|
||||
|
||||
func (t *trw) SetPathParam(_ string, _ string) error { return nil }
|
||||
|
||||
func (t *trw) SetFileParam(_ string, _ NamedReadCloser) error { return nil }
|
||||
|
||||
func (t *trw) SetBodyParam(body interface{}) error {
|
||||
t.Body = body
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *trw) SetTimeout(timeout time.Duration) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestRequestWriterFunc(t *testing.T) {
|
||||
|
||||
hand := ClientRequestWriterFunc(func(r ClientRequest, reg strfmt.Registry) error {
|
||||
r.SetHeaderParam("blah", "blah blah")
|
||||
r.SetBodyParam(struct{ Name string }{"Adriana"})
|
||||
return nil
|
||||
})
|
||||
|
||||
tr := new(trw)
|
||||
hand.WriteToRequest(tr, nil)
|
||||
assert.Equal(t, "blah blah", tr.Headers.Get("blah"))
|
||||
assert.Equal(t, "Adriana", tr.Body.(struct{ Name string }).Name)
|
||||
}
|
||||
60
vendor/github.com/go-openapi/runtime/client_response_test.go
generated
vendored
60
vendor/github.com/go-openapi/runtime/client_response_test.go
generated
vendored
@@ -1,60 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type response struct {
|
||||
}
|
||||
|
||||
func (r response) Code() int {
|
||||
return 490
|
||||
}
|
||||
func (r response) Message() string {
|
||||
return "the message"
|
||||
}
|
||||
func (r response) GetHeader(_ string) string {
|
||||
return "the header"
|
||||
}
|
||||
func (r response) Body() io.ReadCloser {
|
||||
return ioutil.NopCloser(bytes.NewBufferString("the content"))
|
||||
}
|
||||
|
||||
func TestResponseReaderFunc(t *testing.T) {
|
||||
var actual struct {
|
||||
Header, Message, Body string
|
||||
Code int
|
||||
}
|
||||
reader := ClientResponseReaderFunc(func(r ClientResponse, _ Consumer) (interface{}, error) {
|
||||
b, _ := ioutil.ReadAll(r.Body())
|
||||
actual.Body = string(b)
|
||||
actual.Code = r.Code()
|
||||
actual.Message = r.Message()
|
||||
actual.Header = r.GetHeader("blah")
|
||||
return actual, nil
|
||||
})
|
||||
reader.ReadResponse(response{}, nil)
|
||||
assert.Equal(t, "the content", actual.Body)
|
||||
assert.Equal(t, "the message", actual.Message)
|
||||
assert.Equal(t, "the header", actual.Header)
|
||||
assert.Equal(t, 490, actual.Code)
|
||||
}
|
||||
21
vendor/github.com/go-openapi/runtime/fixtures/bugs/264/swagger.yml
generated
vendored
21
vendor/github.com/go-openapi/runtime/fixtures/bugs/264/swagger.yml
generated
vendored
@@ -1,21 +0,0 @@
|
||||
swagger: '2.0'
|
||||
info:
|
||||
version: 1.0.0
|
||||
title: 'Test'
|
||||
schemes:
|
||||
- http
|
||||
produces:
|
||||
- application/json
|
||||
consumes:
|
||||
- application/json
|
||||
paths:
|
||||
/key/{id}:
|
||||
delete:
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
type: integer
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
29
vendor/github.com/go-openapi/runtime/fixtures/certs/myCA.crt
generated
vendored
29
vendor/github.com/go-openapi/runtime/fixtures/certs/myCA.crt
generated
vendored
@@ -1,29 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE/TCCAuWgAwIBAgIJAJ0kpLFo4pEzMA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV
|
||||
BAMMCkdvIFN3YWdnZXIwHhcNMTYxMjIxMDgzMzM4WhcNMTgxMjIxMDgzMzM4WjAV
|
||||
MRMwEQYDVQQDDApHbyBTd2FnZ2VyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
|
||||
CgKCAgEAzQ5NC1JBNNP79HPiUBAO59LoUMGbmSU9K9v+cQMuyyOuv0nwuiXc5anU
|
||||
J1BINqgLR1VJjwTnQsXSlsr2SPs/144KgTsgk/QpMXdlFQwfqLJBIFlsQQBbMx6L
|
||||
/2Ho6KE7z/qz6cqgKvYrGDu6ELUu016MbUsPWfhPBJE7Ftoajk5AIomDPmiTi0cZ
|
||||
wdhC8SB0aVVQ2IWrsusfgPeOQ+ZLa/WHmpJ2Syfq41i/VKllEeCrMwtMP2By2kA/
|
||||
ufBLCnhr7yZ0u22O1Bl1+0XedWli2GiXyt1h9nQ5blTTKZi5grOzAgCcshb/bw1H
|
||||
1hdJKMqkzbqt2Mxc/78PJbDgicJU1ap+fhfBmUviWIMML6eum2ObuKd4ihhXKfqp
|
||||
T/nSUA0P9565W71SLAHFLdZX/VSMZnoehkwIicVGgEzjlYj2j9qBc0CjYzbEtQXH
|
||||
TRGhbjMX5LSByeE6hwLM6hIbQL4nriRobar63rbOc74Tm1ed02R6BvQjgXgOGqAN
|
||||
BgCKKjfUIm0Qm2qV4WkwGIAOi+hdUpbNJ0X2dU/B00qLhar+h4NT9TW4PmKf4agk
|
||||
NZ6O3C1saGxjtuPnIdDxWTdRhPSUyjsllmWhrmkY2bsRB8Z47zqrdfyajXlPOmBM
|
||||
1f0am4Zeo3ditBTfFqtA2LLQbn1yZwYJQ8+sESu6bsm3S89DFT0CAwEAAaNQME4w
|
||||
HQYDVR0OBBYEFN4BShcjqDbbgaGvPiGMNrUEi/RZMB8GA1UdIwQYMBaAFN4BShcj
|
||||
qDbbgaGvPiGMNrUEi/RZMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIB
|
||||
AIqZYn+PFMcOwraYtXtAzJwU4gElWDjIA+xVMMzulHde8t7EWo+I5iDdtn+sHzhG
|
||||
B1oYFhKv/HIX9GR3XDYWluoUVA4Ed9eBamL0Qqzq4Era6ZN1VQd0egvyOT40UQ7m
|
||||
2aNw1nLgWadCmsxeVMKQRdzct9G3dOfJp7K5WybINWTibNMTuoSuU5RwtzriK000
|
||||
C9pnxCD8boSNY/flOX0M5Mt3kv2JaIH2UsMKNGBf5+rXcKfhTE6JgiXorUEEztHP
|
||||
PFpZ6VFKDlr8QC/4aLYhOJ9LIloaxZyk/rccCuHbdPPX5XGA3Z9i/lxSoqtShYlS
|
||||
mt5vmdRwQob/ul6hPch3YRqD4VgeM1O80FEsWBK2WmGGH3wKNKea7u6dZyfQv3t3
|
||||
fUVmByAVMllVRA1YiKmBZ/kOeAMku5hpR9kzErCXZd/xrKWVym000RsvRb6apltM
|
||||
sYnlCyKfIdKxUXavO0Bf4+YoaN4/p3mZchxpLBwrzhPyUpGQ9b3TuGjoEmtG57yn
|
||||
6I3U40/TouJR0aF7i1bAF5QJWYOS7OycJbHAIZiQx9ENDP3ZMfYNWQO6STFJAjvC
|
||||
C0u23DyiJWZqE4Uw51O7jWKh7bSEKWutwa0XKWrpxhUjHFX4qGigIvXpO9LMjR60
|
||||
YDhdCEmUiu/Hc0tt0QzyTA6w47TP0gXREeBLabzuEDPi
|
||||
-----END CERTIFICATE-----
|
||||
51
vendor/github.com/go-openapi/runtime/fixtures/certs/myCA.key
generated
vendored
51
vendor/github.com/go-openapi/runtime/fixtures/certs/myCA.key
generated
vendored
@@ -1,51 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIJKgIBAAKCAgEAzQ5NC1JBNNP79HPiUBAO59LoUMGbmSU9K9v+cQMuyyOuv0nw
|
||||
uiXc5anUJ1BINqgLR1VJjwTnQsXSlsr2SPs/144KgTsgk/QpMXdlFQwfqLJBIFls
|
||||
QQBbMx6L/2Ho6KE7z/qz6cqgKvYrGDu6ELUu016MbUsPWfhPBJE7Ftoajk5AIomD
|
||||
PmiTi0cZwdhC8SB0aVVQ2IWrsusfgPeOQ+ZLa/WHmpJ2Syfq41i/VKllEeCrMwtM
|
||||
P2By2kA/ufBLCnhr7yZ0u22O1Bl1+0XedWli2GiXyt1h9nQ5blTTKZi5grOzAgCc
|
||||
shb/bw1H1hdJKMqkzbqt2Mxc/78PJbDgicJU1ap+fhfBmUviWIMML6eum2ObuKd4
|
||||
ihhXKfqpT/nSUA0P9565W71SLAHFLdZX/VSMZnoehkwIicVGgEzjlYj2j9qBc0Cj
|
||||
YzbEtQXHTRGhbjMX5LSByeE6hwLM6hIbQL4nriRobar63rbOc74Tm1ed02R6BvQj
|
||||
gXgOGqANBgCKKjfUIm0Qm2qV4WkwGIAOi+hdUpbNJ0X2dU/B00qLhar+h4NT9TW4
|
||||
PmKf4agkNZ6O3C1saGxjtuPnIdDxWTdRhPSUyjsllmWhrmkY2bsRB8Z47zqrdfya
|
||||
jXlPOmBM1f0am4Zeo3ditBTfFqtA2LLQbn1yZwYJQ8+sESu6bsm3S89DFT0CAwEA
|
||||
AQKCAgAjBkBOoLwWg+bTOD/9oOCK5FFeCdPD8sJiDW+Gah7B/9RHRB/kC7eRWtKr
|
||||
7GCJRWa3xm+MCDBgDV4M95ndmVysOsy8ihbkbp3inxwa3jlCHUBWgC+nYqIxNxR+
|
||||
iIC5y2BmA9JbKor1C5sMxpbfZ7MZ01p1CI8UtP76LrxDCPnkOKVnwMk0DbS1420Y
|
||||
2RGGEh8QJsxqT1qmctastpwMKPfU9tk0o7Ok3qqWLoBvu4dR6GgVjeZ2JMk5UiQQ
|
||||
ZGTM4wi8jnr90JbGz5qBUsvOjjOd9y+GLQ4ghHWSzNZMkpONKZh3zRb2rErw8vnE
|
||||
LbIHT6Wapjovf6ia3k1+CJoxrYnDrsOHcWopm2kle7FXjgfHRXubcNU2aLdIAcRg
|
||||
ZGGyalex3/NXKjhGf8jhaXKkOYDL37ZFtEmaUJVjjhiIE5jGByBHU0pqKk9Tdtv0
|
||||
s5r5m0T8Gk8h70+fZ/C+wkYE4h8uzqAlq/yrxBSlGMHEVG9PI9tr9bM1FLM/H92q
|
||||
CqoVR6YWTC7o5Kasr33RKYJg5vPHfFoIGHX9etbfHPGQsbCLaWhTLIYus+0b4ZS1
|
||||
D1jHCoxHCjKzf2PFwogtRsmhyQSS3A3GyEWy7BZgFvgKFpq9hRC66k8Z7pnnkKrW
|
||||
i4YihK17ivI5uG67Aqlc+kdahRNVWOOaPbwjGosmlULyfCOdGQKCAQEA79dD3caa
|
||||
zXqFQkYDZwZcthXw9Hn+ChTCcfucJz9I0DUeL8FpUQYCkFZRUoEgF/eNrKSG+ctn
|
||||
VDgrj0IZAcumpfjc4ZMug8svFYkE+vsUVgSI03KPRJ5NZ+Egn+HExURzCSQY6fK8
|
||||
mCp05+gXndiUhoco2H851esmMtCSd/5IyR3d3C64ZfFGSk/Nx66A4Z643ffB6tOH
|
||||
KYWFgVoQtSb92pgyxuBzZ1JhxuBVihRzAQtuE+uZ14xPoVv52fUlYXUhGmdqtZ3l
|
||||
Cio3YGZTaUqtF0BP8HshzAWQ2k2vCJUxY99dbFfsE+v8vCojgMz8KmzO7C+j3Pa1
|
||||
hq77rT29WFvaHwKCAQEA2t8R3QCkcaCRDMAPomqPJjUHrX2gdPM2zFFCvSqiVkh6
|
||||
8ft9NF8sO1aXq600IxTiTf/L8ZvM0HlPlYQSjFzGWsOgNww9MKF7L4NnJ7e/8mwP
|
||||
jqfajNcqecHIXvNi0AqXOpN/hEhm5MWKce/BPV6GpnRnb5doy8wOG0ESsmUA/5TJ
|
||||
y/65LVxDKT9SdymDVayRwq2vNn9qW2BBcM9yan5GstkE3zzkrzKcCgz5X09/vO3R
|
||||
K3fYk0FReE9CY9XAQGtz36Ra19efETzvWPi18zsP96QMUYIS2+Y45sVPhGZbY2aG
|
||||
HQXTg8xIJN51E+jmWpJ1vv27izFh5TXeloRD4qldIwKCAQEAqkG6+KVy4OjXzlsb
|
||||
MTiP+eaLfVFYaFmiSv3dNPM0wjDi8+2t0Imeqk3MPvBRExJ17ReChbLB8ERLj8/R
|
||||
Jrgl3e5TBoLP41kKXJQ/B9fS8NkZNFk/oOtrcZGb8kN3xr23l8abNQBOpwqEoNfe
|
||||
Y/wKO5GZCk8OhHAAVtQ/FZVaoAJmq1YzKpLjXf9WyihzbzaYb2Hgs81jRrN1OYTx
|
||||
FVfPnyyp5woQgkk2BdLchj/L//LYOqXmOOBu6tH7BKGE3rEiRbciRjkHDXc4hmM9
|
||||
VSJgy3+o/8K5FDbjREUfOs2GGSrIDBBCE0ZTzFNxjo51d7x0C7Ap98Ley/RNzwZj
|
||||
8mSJ6wKCAQEA0NXvcXPfdBvEyumnAU2zcL1AqiUoKO635pPSnjRD2RgnVySi/omg
|
||||
5q1k4oXNLXwLwmjD67DA6FoXuY3fNNaA3LGz+VJQQEqUA23Zy2fkWicJYRB/08qp
|
||||
2KsxyIdqTR8N1PJPxaRfqQFja/tb4naC++gtmahacbot64tXj6gYH8WUFnThs4pI
|
||||
+t5UjSarDeAu5BZdDB7fGHjrd/w4K6x5QMUZhPfRK+maQWzHtE1ikJ5J6rPbjgXQ
|
||||
+n6F1kRpwA3G7ikgFLrEJ+qAZeBJm99LCPsaVdtKq08sE+VITghsQpfcd2zLuQH+
|
||||
BE/OXkTnJpyAhNANVm6z/cQ8sllZfLglCQKCAQEAkZTQ0xnUeJTV0CqljMNCIN4M
|
||||
i6Xyqf5uUDPfooY+fILbemT/acYUAkbjamgJlQMQ7yui9WV7Q/9HiCHaVh3o5zrV
|
||||
zaq3vocA9x9nK998/He7772/uJarINvLFj/p/vTQM4Lni+bJ93bk6XE+FQKPgY9B
|
||||
GfeFFaVtH7gimB4CjrxYprhAfqyxyE/m6JVMRg1olIFuav37GYP+TJ2K85klQRNa
|
||||
TEXbm6ZJpSHfNjKZzUczziaIbwnMN9OxJY6M3a1JuEy2h+og5oRdMOoB6RETzhle
|
||||
mxT5uEtA6mR6KyBZBjWhcl/V/Rw1DVMmtVbHCdc0+Xn/CMemRLCw1bxRUu/iww==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
27
vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.crt
generated
vendored
27
vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.crt
generated
vendored
@@ -1,27 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEqzCCApMCCQChJZEdSdrQkjANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDDApH
|
||||
byBTd2FnZ2VyMB4XDTE2MTIyMTA4MzMzOFoXDTE3MTIyMTA4MzMzOFowGjEYMBYG
|
||||
A1UEAwwPZ29zd2FnZ2VyLmxvY2FsMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
|
||||
CgKCAgEAs1MHhleossLBkYKYwOT+82RT651CfCOilpEUhm92KGRSMQXZEk+2TUgc
|
||||
dGPeQNDNmbpXGzdk1HZkqWR5XKfSjWWxfmBlbBoYnkL3neoiXBdBVsgHkEPdP5ly
|
||||
uJRkohy6az1vnq2vLaI+YujStutf8hSdcPu9VeALbrR027dMbY2XMC97FteeVaw1
|
||||
mXmW9UHDVSV9UPBPswUOQWhjIADBk5IYaYASCY3M4X5BPCWFu1oQhgVMEhodBoBj
|
||||
pHhHrfoDm1TwtT+dp53TmR10zpUiN+FcaVMsjqN4DWX4ma0uhu+zJew2XjCJkNfX
|
||||
wVqGFpe2Hx+lupOGs/kwBvQ4PYn5ydgcm5DTggBC45JxCAVi3tQCYGsg2xkX9yPj
|
||||
aXYc8E4/aeQI9UZxUeR2siBn8ECX4gJTmPJbQ4Xykqn6YOHyxIVoqd+9wo9Z1weH
|
||||
xCWtPGESg7l7Jn/6WQ5V8z6RzrquGi67asrpYpv2lxNXMQA0f3S8sWYe4f8QVazy
|
||||
ALtu8+0XE17UPjlbNBqEfCIrMsYmL5VyMVbL0dlXXBxHjzfpXraNGoSD4v6LxRxP
|
||||
dWQgrhEZ6DmfiWfX8uhLdMwlvUxNXj33UDtM8dtN6mHERA9wF2RQQzPddZ0MYmUF
|
||||
DI92i9mRC7Yzx6mcv/yUnFw213Jnzg297lW0Xp0ifawyPi2V8f8CAwEAATANBgkq
|
||||
hkiG9w0BAQsFAAOCAgEAme1gyNQry3E5bj4XfdL4aNvZamzLaQVRlNZSHUzDhhpH
|
||||
6N/DK/CAw4g4Msty7g3KBZPmldJhxH0bnSoRGMjFdKn9tVQeJOjaHQ2Z3cQWwdte
|
||||
iXtu2F38SVfP5HCh9ASQ9vQXahGOruUPUUNUnDLfOBea7vrT3DmVugXlMSmaYuSJ
|
||||
JdrbPzD48yy60AEDlCVpY2m1cEc5SmTkXbrAg2jhQd6ytaPQ28vGQnpZHSS/xWjC
|
||||
Hh68o5SUoGoFErZxPd0o2brHavi4YybYt7CXlWG2TJ89s3BCSPIHclNF2HjxRq/r
|
||||
2Q/Ttzo3cRBxi3RBnrLdn4qNgJjZnWaLobjaWcs1fbI32allogLsiurCwZb0ToC0
|
||||
fNMzyHVNWY8BqsuyWyF2H0F9rklmqGFJSmrqt8kDLx0xpkZchGPIDSRh+f+PPDmE
|
||||
jGPPH2qxz4un0foJx99dtw18TPaplFo2LxRK89koTiQNyzAHwSn6PHGlyXhNPsUt
|
||||
K5GzjAu6B4uyldcg2m+4O/dbNdeqSczYAFenfEO7PRAy3AP7Lxs2xqQaNiA10965
|
||||
vYmCNIOuV24CuFEIrjOQkZeFCw+odsgFs5Nv8JfDdA+BRr+Haq8FVX8afEc0BEnr
|
||||
xY6f2fvgYTMvx0Z3UVT/XJ3POWHRL0HFLj5avHE0eOOkrcPbX6UsANd1v0F2BH8=
|
||||
-----END CERTIFICATE-----
|
||||
51
vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.key
generated
vendored
51
vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.key
generated
vendored
@@ -1,51 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIJKQIBAAKCAgEAs1MHhleossLBkYKYwOT+82RT651CfCOilpEUhm92KGRSMQXZ
|
||||
Ek+2TUgcdGPeQNDNmbpXGzdk1HZkqWR5XKfSjWWxfmBlbBoYnkL3neoiXBdBVsgH
|
||||
kEPdP5lyuJRkohy6az1vnq2vLaI+YujStutf8hSdcPu9VeALbrR027dMbY2XMC97
|
||||
FteeVaw1mXmW9UHDVSV9UPBPswUOQWhjIADBk5IYaYASCY3M4X5BPCWFu1oQhgVM
|
||||
EhodBoBjpHhHrfoDm1TwtT+dp53TmR10zpUiN+FcaVMsjqN4DWX4ma0uhu+zJew2
|
||||
XjCJkNfXwVqGFpe2Hx+lupOGs/kwBvQ4PYn5ydgcm5DTggBC45JxCAVi3tQCYGsg
|
||||
2xkX9yPjaXYc8E4/aeQI9UZxUeR2siBn8ECX4gJTmPJbQ4Xykqn6YOHyxIVoqd+9
|
||||
wo9Z1weHxCWtPGESg7l7Jn/6WQ5V8z6RzrquGi67asrpYpv2lxNXMQA0f3S8sWYe
|
||||
4f8QVazyALtu8+0XE17UPjlbNBqEfCIrMsYmL5VyMVbL0dlXXBxHjzfpXraNGoSD
|
||||
4v6LxRxPdWQgrhEZ6DmfiWfX8uhLdMwlvUxNXj33UDtM8dtN6mHERA9wF2RQQzPd
|
||||
dZ0MYmUFDI92i9mRC7Yzx6mcv/yUnFw213Jnzg297lW0Xp0ifawyPi2V8f8CAwEA
|
||||
AQKCAgBZtF8/RPqO8f4C3GGtnOAswTN52eE4WFstFsY9ueRRsF2tSE+eaWG4pyoU
|
||||
zyCPK+St0hlg9ATsg403b5uGTi11rjlsDqyttyA5iyZzSHyHtNpqnwWplUlIV2qc
|
||||
Cx+MOPLIUqNTrW7EVTUAJZfDCVulrcpUipncK4eMiZkrkDYbV4kaAaaBdrsuAEeP
|
||||
ztNFPPCJ14coxg4Yb58B+UYc7EPpnlu36uka/mRPKOlZPSv43MUHRf8XzxhV+EPg
|
||||
Moso7LiBK6x9/qTPBJSlM6cK8G99pK6lwYW4lO2pRilmNsvflGj5v4Ay/fTTECZO
|
||||
AwqwopPoXdx5yPLJdQ4hbGn13t+k0pB4LYXl1xqLg2Z9QN+pgC2h41OrSx8Ozw9U
|
||||
KTocbsMV6pafnMRoQ5Fjb+eTy4VE8rZl/OlMDX2cR2XL+a3ypIAA5E4KrYDiIBiU
|
||||
MSA3EA3GsOOnyrV+fII+f2tVo/qDnvxQO/ZPUr/XG2xtJ+gqThWlrBft/O4/lCju
|
||||
+kfNg8cMHtahGOmLz1ALsl32ANj5jTZmVOEs9xTG7+TeQ2RzWeBYTB7oNTMNIbaL
|
||||
pTZTzxoeRyxx8sUvtaTb23IWSpRUiS4+F7Tn97g6ks8fYQPsVkl3WzXeECaL9uNN
|
||||
hFkAwd0omD4TwQlmOUVm3IH7A0InTAaooC9jJfNqmhhHcLUAgQKCAQEA3N+pR1ed
|
||||
aCXQit6bgw0rIF6RzjeGp6lLGaPdvCUM7sdAUwSGbFOgkcaw9TELFpCpfZGKFXI9
|
||||
IxPOwjFrURY4S2iuyAVv+Cw7trXW4BF1z+08M9RWYGLvyUsO7FIsGUmdYRtasb5L
|
||||
IfHfGoXttadKWcdFMSF+25CUcbleyCNrJzXOzeMn1/UoN6+qfsyfaAD03nw/ZmhA
|
||||
mK3UKjR7UOUPXt9gIXVivRaEQBakrLkJtK33fl1hztqxComE3/h6Qmj6iRmyxX3y
|
||||
v3mzXbyC6jobq1tLUWpxvlQgoAyk+zZ0LNEHlkVfertaz0XdN/L2ZgjoGjJxfn/y
|
||||
OK0a4jJyCpXXEwKCAQEAz9fJcpqaB25joZsqG+islNljyFjJRT9+E8IU97OglhJM
|
||||
8T9TFs4RNsAxIqHwYm4KuoSlI4GhYeuOxGk6yUGm8cO314J7Wv4CAgZeJBcmxJUs
|
||||
C8FbcXKbesK3VIuvATgzI9Vq/UF+GxJCkPctZJ9Oa0t578rVS4JH5ZJQdw2A77Lq
|
||||
kGunMDboVY7EYDOn/fNMKGfcnH8KIQn/2b6CKLarj39b1fG7MeCuxPRejijaKtZI
|
||||
ra5n0ofLluGo9HBXLgqgsjhjkSWU79lRypuKS8qOcjI08Xaw3Q8+qn0uLCARd8rN
|
||||
2+mQy5OAZJCWpYIKPL6E41GaxcaTdOYzlOCs9Oz65QKCAQEAgSqzXitYvC1RFcU1
|
||||
AKDU1as4bXZ/YtFYP/halcq9E26mqWX+Dp+hSV7+4YT6zQlwdSSFsiEKq9bLlTk9
|
||||
X0A1T7Q6cnLrliCYEzOoI4VSdnRwPocwtFFnlTo10fIEJA2u4bkTgtqcKY+/P02P
|
||||
RCo/Ct3EEwVZoKGejhsv2K8N3PJUrIbpKBwQlvA+LsUPe80DZpEWqpbRH/iYGM50
|
||||
R0yNfpf3KdnyEk52rNwRFYloqacLE3Uc29F8s4LUl/5B0VB/I2pJ58DOEzfiszCp
|
||||
Br1QrRdIpqYvOnUMV0zNtrOToRnk6/ZJ7gZfBtP+mNeXTPhsc9WIFchRKN/i1uFV
|
||||
W+dgzQKCAQEArcXTDdio85GeB1395PuyX3kqbjWdgiJFvStF8JvkpdSDNCknxSdh
|
||||
SQ+DhVsz6nfqzGtezsLxNTeHVDxPBDm55OUobi0QCdHZx+ufBjm9FhtKikGNvNp/
|
||||
mDH4qd1n4nMkfs9O9pOtZeDsetvOvhRbsmWWe6BwmQNCLXUZhZBqvv4uE7WOQUeH
|
||||
FRGaqnxF9pNWl2nPD6E/zMPZgCpCFNw1sHJhTA0h39/k/5L5A46waaRje6MX9vPG
|
||||
ik39vvG2Ui5ckOWIibCMR8TBF87X3+ppEp1bmo8L7Kd0U4L5+baOJEQRvc4YW7zl
|
||||
Wi9xZMvG12bLIGv4JWeTnediNRVsRhNk6QKCAQBXYkpxk6LTgP+b6FJ7fiImzDbH
|
||||
QJ+RbBYJdgYLEarKWdWhNqj3YiDOUJt+ve13reybL4cLmOYoNzeUO9IHyGeTp+WV
|
||||
gtPf1g2hm2TZannWsoTvnoXJ8yR52ZQQ5JusNosbmlrqWRAN8GhISdYTJDNcS2hD
|
||||
PnVX/kaJfRDennokD+FWuyygua66LBdZi3UNgGMay15/2CCoC3PoejfQORxDyPP9
|
||||
am+e3/U6QG1/VWMHen3Mb0AZKwEBAwX1jL4EpoDZ+Y6jP0tbQ5xL7RivsUNtAVlQ
|
||||
m7lumflcBy1WqkmviVJ9M2iFuo0HznuH1qlgOJpUiqZZjL/gEvkdDNMcQSmH
|
||||
-----END RSA PRIVATE KEY-----
|
||||
26
vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.req
generated
vendored
26
vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.req
generated
vendored
@@ -1,26 +0,0 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIEXzCCAkcCAQAwGjEYMBYGA1UEAwwPZ29zd2FnZ2VyLmxvY2FsMIICIjANBgkq
|
||||
hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs1MHhleossLBkYKYwOT+82RT651CfCOi
|
||||
lpEUhm92KGRSMQXZEk+2TUgcdGPeQNDNmbpXGzdk1HZkqWR5XKfSjWWxfmBlbBoY
|
||||
nkL3neoiXBdBVsgHkEPdP5lyuJRkohy6az1vnq2vLaI+YujStutf8hSdcPu9VeAL
|
||||
brR027dMbY2XMC97FteeVaw1mXmW9UHDVSV9UPBPswUOQWhjIADBk5IYaYASCY3M
|
||||
4X5BPCWFu1oQhgVMEhodBoBjpHhHrfoDm1TwtT+dp53TmR10zpUiN+FcaVMsjqN4
|
||||
DWX4ma0uhu+zJew2XjCJkNfXwVqGFpe2Hx+lupOGs/kwBvQ4PYn5ydgcm5DTggBC
|
||||
45JxCAVi3tQCYGsg2xkX9yPjaXYc8E4/aeQI9UZxUeR2siBn8ECX4gJTmPJbQ4Xy
|
||||
kqn6YOHyxIVoqd+9wo9Z1weHxCWtPGESg7l7Jn/6WQ5V8z6RzrquGi67asrpYpv2
|
||||
lxNXMQA0f3S8sWYe4f8QVazyALtu8+0XE17UPjlbNBqEfCIrMsYmL5VyMVbL0dlX
|
||||
XBxHjzfpXraNGoSD4v6LxRxPdWQgrhEZ6DmfiWfX8uhLdMwlvUxNXj33UDtM8dtN
|
||||
6mHERA9wF2RQQzPddZ0MYmUFDI92i9mRC7Yzx6mcv/yUnFw213Jnzg297lW0Xp0i
|
||||
fawyPi2V8f8CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4ICAQB7U21HoBp5Qfrwd8aA
|
||||
KzBY2BfEp5ouyn32kpfkB3Ha6+XJ69Lt1WHMSKnmYamlwZCSOS2uQ6DzdTLDfZpC
|
||||
8PH5Gs32O9zJwUeSuYcUQGfcAenauu9gwC5ZnIbhOs5YTnEFquVsBqrNUKS+hLKJ
|
||||
sAPtucoqlLX5qSkv/BOK2X4os90LAmx+yB/yarAzZOO0ku8qXt+MHI+rOMPLTmm9
|
||||
kYhtyXejQaXLOVbvQ9b2gxHvMcyLhklc4KpJPRfPzOdNebHsf5o4Em6lxeglGw/A
|
||||
z05sBSAla69sEygcItZryQ4WjMRUpsLePXJrlSL5DYWGK6BX1gCkWtpXLqE1HgR3
|
||||
4L/xvaJQ5ZWpLoyJoJauU37Zhd5dLNGpNiSSEA0BKOjj9Kjm8nvsJE9DgziTaG57
|
||||
qFLRkMkDdBdb5wOfVYI/MY9zc+igrFPQJkQ0Xkdza8yXegBldv1JRe+49zifysea
|
||||
Y/B+qWx8IpeHke0iEMqR6iWrw6oGBG/obHJ/V09DwC6iU8vot+pLr/bSyoUCUP30
|
||||
OEATJf50ic9oZYXgdT9oNBcAlAriuzoQuGi9nAKZJss6YkhooWoqXlXNQgAEc2gl
|
||||
WF4fNumXwVaPVeW2q36Xk1btHz7k+IeVUg1jaPMPUJ+1dgIOZA7FcoYotvF6StyX
|
||||
xoHybhvC7lbeif8EK7tJ2p4hug==
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
29
vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.crt
generated
vendored
29
vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.crt
generated
vendored
@@ -1,29 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE7jCCAtYCCQChJZEdSdrQkzANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDDApH
|
||||
byBTd2FnZ2VyMB4XDTE2MTIyMTA4MzM0N1oXDTE3MTIyMTA4MzM0N1owXTELMAkG
|
||||
A1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExETAPBgNVBAcMCE1pbGxicmFl
|
||||
MRIwEAYDVQQKDAlMb2NhbCBEZXYxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJ
|
||||
KoZIhvcNAQEBBQADggIPADCCAgoCggIBALGjhpJfej7btWCO4OCRJBliUAUyPMO8
|
||||
B649Qjn1Yiw9E1L5viByYJSihsfUQ7u2gHip7QdigKCA/s4+w8V2L0Dv8lCowCLk
|
||||
exf10b7XGQaOqhk2mlr/jOapAg0pKDoUlVErBBZK2s6UbD/gLXAbxudwxCFKJ1Y7
|
||||
d/Dw5aTl1vlWZpHzf2o9/ZCeHXf8Xu3aMIEPJ79wG0vzNZK7bL1r1lQVzACdHAr3
|
||||
4HAQAvgWB4ZjKqN8z0vGC0N0MpaAuHD8fH8wQ5YiWBbDhDPFVzRYU8PcQjeZSMFq
|
||||
Oulew9KVm+vXtcMvteEoXMXwWlqAGlvnv7sskc/VbrLJJQaoswyKgy1QCKxVO47E
|
||||
f2iU4kP75iDYx6NpApdnpN3zxHMHyZDxuwmtoKealenxl5cZeHc6uUU1wXk+nmy7
|
||||
TrgW509mcopHzHj+Q0zyGUg/dRws3qXPAGZehJPoaYF1F54eiindF1yLMMH5osvy
|
||||
1bNp2EQezOlY3P4gqW9VHq3CQvytmDbXqS0vPzVAsFu8YazM3Bs0mW2bBXrEsajW
|
||||
DSjrvbhdZjlL9j2jqwZ2nzyan88M5t5T0vZhcu+wKisATI1yLdV3oWvLmdFz/XA9
|
||||
L6UyosTiwC1MWPmkOY4mcHn/Px70f40+wO815pZ6FbjecxRSyMfAm6vDPWtLAMUr
|
||||
1UoD4vasyvQNAgMBAAEwDQYJKoZIhvcNAQELBQADggIBACI85R1LfDwKpmWFdCeN
|
||||
M8O6TwSftxh113QzMvobYDMmBI+yVn0ZvpcfP7E+LWRjzNcDxMFbntbbFWt99Rcd
|
||||
rJek6CVxLJug53mUEFmvktreHsJ1T7cMbk1ZVroAurE7hZOWYM2HwXlKzVyXX0qh
|
||||
wR26HSuzQcGBfo5/8e6dzMuy0fUVkgDMu4oKt0+mGgS4kXsOyexfRRBkY9GPusVk
|
||||
gSzu/WbSGNxNvp/ewWNi8waqrN3noM83iae+BXxI0Sq4eLTQ/vnV1ReM4gRR12Vw
|
||||
anwZqHZ/WzBV27z9gW36t7wRxJS/uTXQ8J08KtBRBPv+19NXSqqjys5Jg0P1f+l9
|
||||
k+sWwpVqIF2rAQ3FyMfboaFKPC0jRn7iJMjp9KyvMbSI+25/rP5xvMicoJwRlk9I
|
||||
GNGasxSfmRpVpV+WG04xMGp3cPrCXHBdAAjI3O68YIPOX3VqZ6MasN1iGuYWOmam
|
||||
yeKzLUApYdtkR7yJ+X1FOKVfbzX27CLYmzwrHnDLJzu8NVgqLGU+qTSK0zm3sYE3
|
||||
w3ex6WX86Oz2QBJ5h/s2TLbsWis7ZkKjMyXqVWlbg4P3reyNrfpAoc0y1R9EjZlf
|
||||
1c9HZBRBuRMgaPWmdSR4lxw1FhQBTstIfzC8lBYNbt8QRRtJIxVF9mxiL7H+6XH5
|
||||
FZXcQCHun6klGtCkypeAaviE
|
||||
-----END CERTIFICATE-----
|
||||
27
vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.csr
generated
vendored
27
vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.csr
generated
vendored
@@ -1,27 +0,0 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIEojCCAooCAQAwXTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx
|
||||
ETAPBgNVBAcMCE1pbGxicmFlMRIwEAYDVQQKDAlMb2NhbCBEZXYxEjAQBgNVBAMM
|
||||
CWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALGjhpJf
|
||||
ej7btWCO4OCRJBliUAUyPMO8B649Qjn1Yiw9E1L5viByYJSihsfUQ7u2gHip7Qdi
|
||||
gKCA/s4+w8V2L0Dv8lCowCLkexf10b7XGQaOqhk2mlr/jOapAg0pKDoUlVErBBZK
|
||||
2s6UbD/gLXAbxudwxCFKJ1Y7d/Dw5aTl1vlWZpHzf2o9/ZCeHXf8Xu3aMIEPJ79w
|
||||
G0vzNZK7bL1r1lQVzACdHAr34HAQAvgWB4ZjKqN8z0vGC0N0MpaAuHD8fH8wQ5Yi
|
||||
WBbDhDPFVzRYU8PcQjeZSMFqOulew9KVm+vXtcMvteEoXMXwWlqAGlvnv7sskc/V
|
||||
brLJJQaoswyKgy1QCKxVO47Ef2iU4kP75iDYx6NpApdnpN3zxHMHyZDxuwmtoKea
|
||||
lenxl5cZeHc6uUU1wXk+nmy7TrgW509mcopHzHj+Q0zyGUg/dRws3qXPAGZehJPo
|
||||
aYF1F54eiindF1yLMMH5osvy1bNp2EQezOlY3P4gqW9VHq3CQvytmDbXqS0vPzVA
|
||||
sFu8YazM3Bs0mW2bBXrEsajWDSjrvbhdZjlL9j2jqwZ2nzyan88M5t5T0vZhcu+w
|
||||
KisATI1yLdV3oWvLmdFz/XA9L6UyosTiwC1MWPmkOY4mcHn/Px70f40+wO815pZ6
|
||||
FbjecxRSyMfAm6vDPWtLAMUr1UoD4vasyvQNAgMBAAGgADANBgkqhkiG9w0BAQsF
|
||||
AAOCAgEAM9VLDurmvoYQyNEpRvFpOLPkgr8rgboo/HN+O/hN9jtmXranLxzTzd+u
|
||||
OJCujyzS3sbqiZwPeT3APHH4c/mLdrEKZHjfy2sEeXMsVW6dCOcIEYsADSCM6chi
|
||||
zU86aw4rAkd6YYB+lXFsEmBq78AIpw0vcdpoPoqGRG9ETQsjr4kD3ATGHTnaP551
|
||||
61JJed7Kn5FTbieTmzmMa46dn7GjTTmPEcoAnHNCx4CbJAHwWEzvQWF4lVlyb2di
|
||||
jFD0NQ0WeaFHK/f6UQMqMq+7TpurN8sLWDlyPHA2X/FT+OsUMAX2mLcwZEsYhTjP
|
||||
dC4ZCuZ/itDgEp3hyPeKiLo+mL/bhhy50nzah/qclI9PS8ufUXEjWoObqiJ5eyIZ
|
||||
jTZ73qpLupS+Yrami98IYfuOotwGzKkVLwUPtCWQrKsun6YNtotuKKmqEEQX3Fm3
|
||||
ZXIYv0BckkXIGd0aKPeMGgMUO26pyxPBSRWB29F07LXzS6eEmfOHvZcT+QLZmys9
|
||||
FkH3yePeTilojCnxNINPyKT4Dk0NiZviCdKavUIJ5QtOyDJ1Nc9j5ss+QaAaNtZZ
|
||||
VTTjupNp+cfCh/kdyGpGP+GgXQQcGgw4OaIbfXqmec7RsqTOppK5gDR4Ne3e5FVm
|
||||
SpPDyHbv2GJolPG8/HCOsLCJED+wAEfhK/wUg8ZpC+7Ymct2TU8=
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
51
vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.key
generated
vendored
51
vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.key
generated
vendored
@@ -1,51 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIJJwIBAAKCAgEAsaOGkl96Ptu1YI7g4JEkGWJQBTI8w7wHrj1COfViLD0TUvm+
|
||||
IHJglKKGx9RDu7aAeKntB2KAoID+zj7DxXYvQO/yUKjAIuR7F/XRvtcZBo6qGTaa
|
||||
Wv+M5qkCDSkoOhSVUSsEFkrazpRsP+AtcBvG53DEIUonVjt38PDlpOXW+VZmkfN/
|
||||
aj39kJ4dd/xe7dowgQ8nv3AbS/M1krtsvWvWVBXMAJ0cCvfgcBAC+BYHhmMqo3zP
|
||||
S8YLQ3QyloC4cPx8fzBDliJYFsOEM8VXNFhTw9xCN5lIwWo66V7D0pWb69e1wy+1
|
||||
4ShcxfBaWoAaW+e/uyyRz9VussklBqizDIqDLVAIrFU7jsR/aJTiQ/vmINjHo2kC
|
||||
l2ek3fPEcwfJkPG7Ca2gp5qV6fGXlxl4dzq5RTXBeT6ebLtOuBbnT2ZyikfMeP5D
|
||||
TPIZSD91HCzepc8AZl6Ek+hpgXUXnh6KKd0XXIswwfmiy/LVs2nYRB7M6Vjc/iCp
|
||||
b1UercJC/K2YNtepLS8/NUCwW7xhrMzcGzSZbZsFesSxqNYNKOu9uF1mOUv2PaOr
|
||||
BnafPJqfzwzm3lPS9mFy77AqKwBMjXIt1Xeha8uZ0XP9cD0vpTKixOLALUxY+aQ5
|
||||
jiZwef8/HvR/jT7A7zXmlnoVuN5zFFLIx8Cbq8M9a0sAxSvVSgPi9qzK9A0CAwEA
|
||||
AQKCAgAb4VyHsLCRGQ64nvQwitctnL6OcjoTRnm2ISs5yYelBdj4lvX+RbVe3rtk
|
||||
ta4D0jsLtS/cjts9VcGoQTWc0lXMTVysyC+Pymh/dDd9SmlFHDMaTfWf/qfws+n8
|
||||
gs8rfnuJB8VWcl0xOx5aUCcRh2qKfKprxyWxZRgIGucQIHrDG4pxsdP3qs8XWZmq
|
||||
cVO85RfjyaslYsUGAKAR7ZS9jiVPgTRJjF8QYaM6M2kj4uE/eGUCz94BOI4gAibG
|
||||
dGF+akJn+/0/nRhSSlF/hqOPNaXAAdvqugYvRSsF4be+X3jfZTXD8sMLGbil4Hlt
|
||||
5tk8P31aNT6Vbhw3t1Y2W1fuyfaYbPZfprpR/6ZPV3Uf1oWoh1ystIxWnfU7Qdxu
|
||||
vrkHkrtho6Qt/7d8nNg0mQ8y5glNcVh/iNu9gkyHIpQ2dZpM9tpHArBGweHVDMvZ
|
||||
vrb/oJ5fRxnKkyouMtWvqO1TY4STPBwCDNSwJa0yxTn3fLvkOdHk1nGEKra7E7Nc
|
||||
hgsIe4q1ZoEikg7cZe8pvcsHIFfju3Kv/zgDTvHjzHPTdNear7mpk/LihlWdbTiI
|
||||
UKkgv17JHRsIhfE5G4pZXLRv2qjCGh+uS8yn2k5qPJqGoyIQ2A7BYbaQ/y2gVh6u
|
||||
hnVdKeETT2uUqIS3xHrV0U9grAeldPJu7bHRwSoJ+HUbp+D8QQKCAQEA4/5K0+Qq
|
||||
p4rpB+4FpPkMcM4yE1j0ASwHsKGMDPU70/t8yfzZBlpf5WNHTOWa8frnxOyazo8E
|
||||
sjm2Xw1RlMb21bFF0wjb3uhN2ak++0zIKMf5vWnM0bb2z7yzbcOJVxLzO9DmRUh0
|
||||
OXvHvbeKbW9KXHT3YKA2zjaw0mO1zl7sd7r028wYpD6owGtfzooyXwWCnByIQ3nM
|
||||
JFB7wFJGIg6Kbu2eJULrN1EaT1Ye0FUVmc4x55FLmZvkYziQ88e4UsjYdZ4R5EFi
|
||||
2XULVI1RA+NPqDXkXmpIx3JnRRvaPc74QatGvDFwY8YeCAjfGFN5LiwFJ6Cz3/jf
|
||||
WjDLOhqoSiYQ2QKCAQEAx3W7uPE7WNQRsyu2QnsEDdlikgP0FJf3fFZOYurfsxp7
|
||||
iqTpNkR9pSWXftP4FBM/KRruoY5TucmPTfGPRS6sQWTfUkVOhrUpOLnuWjf2DJxH
|
||||
Qqb0wnT76WcAB4L5Gr//91a+w3dwAX5YhdTZLxEKgpm8ky290otCg3+AYOb/P3Ja
|
||||
V8RR8RQCNV1+y7peBgjj/mbYeVpxjTiZ5cq4cx2OU4rnup/k3HIg1Gw+qr0N9AUN
|
||||
2WYOL+X0qaKffDa2ekv88H6mVnfRSReFIpteuV0XITwvMc0DbHdj6zEj1TSZMExu
|
||||
rDVe7eh2BeL1QxbuazRUgwZ+kfy2NUzPkB1SSwi8VQKCAQBs8K4qj0S+Z8avjlFO
|
||||
Id6K7EvLKN72zGYkRRzZeDiNMwbOsS22NmrJ/eUs3i1qYJxsYS4bcwUocCEvS/rm
|
||||
XyfEtf8KNppw6YmBbrh0dZzSt7MiibJfptBKNP17fkpau+hTdZ8CDfvTF806XsAb
|
||||
SGk8wnsNxaBKaqGU9iYCJSNSlpe3is9fc71IrEXMOAaXltdw5sVJkKI12+s121o9
|
||||
nbsSBCJj5ZTlCrDKpfj1TSKUKo13+9om3PGFY5sHkTAHBoc/tDcSXRfxllbCoP/M
|
||||
HsqKMq4bWyfJfWXRBN0EWagQINocxHbShfEFn8+SHRizMj+ITuaEJ7P5sYT6D5DI
|
||||
VWYJAoIBAEqaxdFiIYGTKN+sbOqm2phXhB/7bJM7WC1glsc29N8n+6ebEUPkEF7y
|
||||
FZ0xqavQmyJD2ZgCBV0LgBd2T9FfqLx4/3LlS37lSfrWyMlj/xsuZRUQH6KQYR0n
|
||||
EoK8wXH4+MPJ5WZ1SSa13GSKfYW2SQkaecdPJ54VypYm3ZzhKf3QRuxnGQMkKcNO
|
||||
KjwHhF2be7PPQg75/lkFH8MstRsRpgengA90+QRfh9oMdtAkEJECRvDW1F2kFIRS
|
||||
uHacfFp4C67koFDdViGRs5GDLcYFhL5ApaJp/WrXqT7yTWXU26uOGyM8fzpbZbHD
|
||||
91rVu+3LUAUGK9ds/7Yl+cj8vqgkJ1UCggEAc0a5kmBREz/8rAWKnlCZrhBsxUUM
|
||||
tiIj32h6dVdFo5SsoyVTxdB394npw1DAsC8xdowrcm/zsYstB3IDMYlrBnCdRxTU
|
||||
Xu6RD3Jci0Qg1cfLQg5snlRnrNz12wygXcvTvW8cHsda8vO+FL1RgFdehDtYoyZr
|
||||
swcLLRAOOLTRXy1Xdbv+8vE6s5ryl3uAO+2Zwbmur3tRL+rhXE+Tb308jlt8g2NK
|
||||
WrRbc3c092aImdGcKmkMGqo6H+xnL9Jj7sR161uO5JJQjxcYbZ5PBmm3J5Z71cSY
|
||||
LR5snbYdxUy7WKE3yxAoWi+FMsoGf+O77+oHAcpXRaTDv0Enr/7rEku5Yw==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
BIN
vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.p12
generated
vendored
BIN
vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.p12
generated
vendored
Binary file not shown.
1
vendor/github.com/go-openapi/runtime/fixtures/certs/serial
generated
vendored
1
vendor/github.com/go-openapi/runtime/fixtures/certs/serial
generated
vendored
@@ -1 +0,0 @@
|
||||
A125911D49DAD093
|
||||
38
vendor/github.com/go-openapi/runtime/flagext/byte_size.go
generated
vendored
38
vendor/github.com/go-openapi/runtime/flagext/byte_size.go
generated
vendored
@@ -1,38 +0,0 @@
|
||||
package flagext
|
||||
|
||||
import (
|
||||
"github.com/docker/go-units"
|
||||
)
|
||||
|
||||
// ByteSize used to pass byte sizes to a go-flags CLI
|
||||
type ByteSize int
|
||||
|
||||
// MarshalFlag implements go-flags Marshaller interface
|
||||
func (b ByteSize) MarshalFlag() (string, error) {
|
||||
return units.HumanSize(float64(b)), nil
|
||||
}
|
||||
|
||||
// UnmarshalFlag implements go-flags Unmarshaller interface
|
||||
func (b *ByteSize) UnmarshalFlag(value string) error {
|
||||
sz, err := units.FromHumanSize(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*b = ByteSize(int(sz))
|
||||
return nil
|
||||
}
|
||||
|
||||
// String method for a bytesize (pflag value and stringer interface)
|
||||
func (b ByteSize) String() string {
|
||||
return units.HumanSize(float64(b))
|
||||
}
|
||||
|
||||
// Set the value of this bytesize (pflag value interfaces)
|
||||
func (b *ByteSize) Set(value string) error {
|
||||
return b.UnmarshalFlag(value)
|
||||
}
|
||||
|
||||
// Type returns the type of the pflag value (pflag value interface)
|
||||
func (b *ByteSize) Type() string {
|
||||
return "byte-size"
|
||||
}
|
||||
43
vendor/github.com/go-openapi/runtime/flagext/byte_size_test.go
generated
vendored
43
vendor/github.com/go-openapi/runtime/flagext/byte_size_test.go
generated
vendored
@@ -1,43 +0,0 @@
|
||||
package flagext
|
||||
|
||||
import "testing"
|
||||
import "github.com/stretchr/testify/assert"
|
||||
|
||||
func TestMarshalBytesize(t *testing.T) {
|
||||
v, err := ByteSize(1024).MarshalFlag()
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, "1.024 kB", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringBytesize(t *testing.T) {
|
||||
v := ByteSize(2048).String()
|
||||
assert.Equal(t, "2.048 kB", v)
|
||||
}
|
||||
|
||||
func TestUnmarshalBytesize(t *testing.T) {
|
||||
var b ByteSize
|
||||
err := b.UnmarshalFlag("notASize")
|
||||
assert.Error(t, err)
|
||||
|
||||
err = b.UnmarshalFlag("1MB")
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, ByteSize(1000000), b)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetBytesize(t *testing.T) {
|
||||
var b ByteSize
|
||||
err := b.Set("notASize")
|
||||
assert.Error(t, err)
|
||||
|
||||
err = b.Set("2MB")
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, ByteSize(2000000), b)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTypeBytesize(t *testing.T) {
|
||||
var b ByteSize
|
||||
assert.Equal(t, "byte-size", b.Type())
|
||||
}
|
||||
20
vendor/github.com/go-openapi/runtime/hack/coverage
generated
vendored
20
vendor/github.com/go-openapi/runtime/hack/coverage
generated
vendored
@@ -1,20 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e -o pipefail
|
||||
|
||||
# Run test coverage on each subdirectories and merge the coverage profile.
|
||||
echo "mode: ${GOCOVMODE-atomic}" > coverage.txt
|
||||
|
||||
# Standard go tooling behavior is to ignore dirs with leading underscores
|
||||
# skip generator for race detection and coverage
|
||||
for dir in $(go list ./...)
|
||||
do
|
||||
pth="$GOPATH/src/$dir"
|
||||
go test -race -timeout 20m -covermode=${GOCOVMODE-atomic} -coverprofile=${pth}/profile.out $dir
|
||||
if [ -f $pth/profile.out ]
|
||||
then
|
||||
cat $pth/profile.out | tail -n +2 >> coverage.txt
|
||||
rm $pth/profile.out
|
||||
fi
|
||||
done
|
||||
|
||||
go tool cover -func coverage.txt
|
||||
16
vendor/github.com/go-openapi/runtime/hack/gen-self-signed-certs.sh
generated
vendored
16
vendor/github.com/go-openapi/runtime/hack/gen-self-signed-certs.sh
generated
vendored
@@ -1,16 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# generate CA
|
||||
openssl genrsa -out myCA.key 4096
|
||||
openssl req -x509 -new -key myCA.key -out myCA.crt -days 730 -subj /CN="Go Swagger"
|
||||
|
||||
# generate server cert and key
|
||||
openssl genrsa -out mycert1.key 4096
|
||||
openssl req -new -out mycert1.req -key mycert1.key -subj /CN="goswagger.local"
|
||||
openssl x509 -req -in mycert1.req -out mycert1.crt -CAkey myCA.key -CA myCA.crt -days 365 -CAcreateserial -CAserial serial
|
||||
|
||||
# generate client cert, key and bundle
|
||||
openssl genrsa -out myclient.key 4096
|
||||
openssl req -new -key myclient.key -out myclient.csr
|
||||
openssl x509 -req -days 730 -in myclient.csr -out myclient.crt -CAkey myCA.key -CA myCA.crt -days 365 -CAcreateserial -CAserial serial
|
||||
openssl pkcs12 -export -clcerts -in myclient.crt -inkey myclient.key -out myclient.p12
|
||||
61
vendor/github.com/go-openapi/runtime/headers_test.go
generated
vendored
61
vendor/github.com/go-openapi/runtime/headers_test.go
generated
vendored
@@ -1,61 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"mime"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParseContentType(t *testing.T) {
|
||||
_, _, reason1 := mime.ParseMediaType("application(")
|
||||
_, _, reason2 := mime.ParseMediaType("application/json;char*")
|
||||
data := []struct {
|
||||
hdr, mt, cs string
|
||||
err *errors.ParseError
|
||||
}{
|
||||
{"application/json", "application/json", "", nil},
|
||||
{"text/html; charset=utf-8", "text/html", "utf-8", nil},
|
||||
{"text/html;charset=utf-8", "text/html", "utf-8", nil},
|
||||
{"", "application/octet-stream", "", nil},
|
||||
{"text/html; charset=utf-8", "text/html", "utf-8", nil},
|
||||
{"application(", "", "", errors.NewParseError("Content-Type", "header", "application(", reason1)},
|
||||
{"application/json;char*", "", "", errors.NewParseError("Content-Type", "header", "application/json;char*", reason2)},
|
||||
}
|
||||
|
||||
headers := http.Header(map[string][]string{})
|
||||
for _, v := range data {
|
||||
if v.hdr != "" {
|
||||
headers.Set("Content-Type", v.hdr)
|
||||
} else {
|
||||
headers.Del("Content-Type")
|
||||
}
|
||||
ct, cs, err := ContentType(headers)
|
||||
if v.err == nil {
|
||||
assert.NoError(t, err, "input: %q, err: %v", v.hdr, err)
|
||||
} else {
|
||||
assert.Error(t, err, "input: %q", v.hdr)
|
||||
assert.IsType(t, &errors.ParseError{}, err, "input: %q", v.hdr)
|
||||
assert.Equal(t, v.err.Error(), err.Error(), "input: %q", v.hdr)
|
||||
}
|
||||
assert.Equal(t, v.mt, ct, "input: %q", v.hdr)
|
||||
assert.Equal(t, v.cs, cs, "input: %q", v.hdr)
|
||||
}
|
||||
|
||||
}
|
||||
811
vendor/github.com/go-openapi/runtime/internal/testing/data.go
generated
vendored
811
vendor/github.com/go-openapi/runtime/internal/testing/data.go
generated
vendored
@@ -1,811 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package testing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// PetStore20YAML yaml doc for swagger 2.0 pet store
|
||||
const PetStore20YAML = `swagger: '2.0'
|
||||
info:
|
||||
version: '1.0.0'
|
||||
title: Swagger Petstore
|
||||
description: A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification
|
||||
termsOfService: http://helloreverb.com/terms/
|
||||
contact:
|
||||
name: Swagger API team
|
||||
email: foo@example.com
|
||||
url: http://swagger.io
|
||||
license:
|
||||
name: MIT
|
||||
url: http://opensource.org/licenses/MIT
|
||||
host: petstore.swagger.wordnik.com
|
||||
basePath: /api
|
||||
schemes:
|
||||
- http
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
paths:
|
||||
/pets:
|
||||
get:
|
||||
description: Returns all pets from the system that the user has access to
|
||||
operationId: findPets
|
||||
produces:
|
||||
- application/json
|
||||
- application/xml
|
||||
- text/xml
|
||||
- text/html
|
||||
parameters:
|
||||
- name: tags
|
||||
in: query
|
||||
description: tags to filter by
|
||||
required: false
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
collectionFormat: csv
|
||||
- name: limit
|
||||
in: query
|
||||
description: maximum number of results to return
|
||||
required: false
|
||||
type: integer
|
||||
format: int32
|
||||
responses:
|
||||
'200':
|
||||
description: pet response
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/pet'
|
||||
default:
|
||||
description: unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/errorModel'
|
||||
post:
|
||||
description: Creates a new pet in the store. Duplicates are allowed
|
||||
operationId: addPet
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- name: pet
|
||||
in: body
|
||||
description: Pet to add to the store
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/newPet'
|
||||
responses:
|
||||
'200':
|
||||
description: pet response
|
||||
schema:
|
||||
$ref: '#/definitions/pet'
|
||||
default:
|
||||
description: unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/errorModel'
|
||||
/pets/{id}:
|
||||
get:
|
||||
description: Returns a user based on a single ID, if the user does not have access to the pet
|
||||
operationId: findPetById
|
||||
produces:
|
||||
- application/json
|
||||
- application/xml
|
||||
- text/xml
|
||||
- text/html
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
description: ID of pet to fetch
|
||||
required: true
|
||||
type: integer
|
||||
format: int64
|
||||
responses:
|
||||
'200':
|
||||
description: pet response
|
||||
schema:
|
||||
$ref: '#/definitions/pet'
|
||||
default:
|
||||
description: unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/errorModel'
|
||||
delete:
|
||||
description: deletes a single pet based on the ID supplied
|
||||
operationId: deletePet
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
description: ID of pet to delete
|
||||
required: true
|
||||
type: integer
|
||||
format: int64
|
||||
responses:
|
||||
'204':
|
||||
description: pet deleted
|
||||
default:
|
||||
description: unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/errorModel'
|
||||
definitions:
|
||||
pet:
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
name:
|
||||
type: string
|
||||
tag:
|
||||
type: string
|
||||
newPet:
|
||||
allOf:
|
||||
- $ref: '#/definitions/pet'
|
||||
- required:
|
||||
- name
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
name:
|
||||
type: string
|
||||
errorModel:
|
||||
required:
|
||||
- code
|
||||
- message
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
format: int32
|
||||
message:
|
||||
type: string
|
||||
`
|
||||
|
||||
// PetStore20 json doc for swagger 2.0 pet store
|
||||
const PetStore20 = `{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"version": "1.0.0",
|
||||
"title": "Swagger Petstore",
|
||||
"contact": {
|
||||
"name": "Wordnik API Team",
|
||||
"url": "http://developer.wordnik.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "Creative Commons 4.0 International",
|
||||
"url": "http://creativecommons.org/licenses/by/4.0/"
|
||||
}
|
||||
},
|
||||
"host": "petstore.swagger.wordnik.com",
|
||||
"basePath": "/api",
|
||||
"schemes": [
|
||||
"http"
|
||||
],
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"basic": []
|
||||
}
|
||||
],
|
||||
"tags": [ "Pet Operations" ],
|
||||
"operationId": "getAllPets",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "status",
|
||||
"in": "query",
|
||||
"description": "The status to filter by",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"description": "The maximum number of results to return",
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
],
|
||||
"summary": "Finds all pets in the system",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Pet response",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Pet"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Unexpected error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"basic": []
|
||||
}
|
||||
],
|
||||
"tags": [ "Pet Operations" ],
|
||||
"operationId": "createPet",
|
||||
"summary": "Creates a new pet",
|
||||
"consumes": ["application/x-yaml"],
|
||||
"produces": ["application/x-yaml"],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "pet",
|
||||
"in": "body",
|
||||
"description": "The Pet to create",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/newPet"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Created Pet response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Pet"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Unexpected error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/pets/{id}": {
|
||||
"delete": {
|
||||
"security": [
|
||||
{
|
||||
"apiKey": []
|
||||
}
|
||||
],
|
||||
"description": "Deletes the Pet by id",
|
||||
"operationId": "deletePet",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"description": "ID of pet to delete",
|
||||
"required": true,
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "pet deleted"
|
||||
},
|
||||
"default": {
|
||||
"description": "unexpected error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"get": {
|
||||
"tags": [ "Pet Operations" ],
|
||||
"operationId": "getPetById",
|
||||
"summary": "Finds the pet by id",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Pet response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Pet"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Unexpected error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"description": "ID of pet",
|
||||
"required": true,
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"Category": {
|
||||
"id": "Category",
|
||||
"properties": {
|
||||
"id": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Pet": {
|
||||
"id": "Pet",
|
||||
"properties": {
|
||||
"category": {
|
||||
"$ref": "#/definitions/Category"
|
||||
},
|
||||
"id": {
|
||||
"description": "unique identifier for the pet",
|
||||
"format": "int64",
|
||||
"maximum": 100.0,
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"photoUrls": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"status": {
|
||||
"description": "pet status in the store",
|
||||
"enum": [
|
||||
"available",
|
||||
"pending",
|
||||
"sold"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"tags": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/Tag"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name"
|
||||
]
|
||||
},
|
||||
"newPet": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Pet"
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"name"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"Tag": {
|
||||
"id": "Tag",
|
||||
"properties": {
|
||||
"id": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Error": {
|
||||
"required": [
|
||||
"code",
|
||||
"message"
|
||||
],
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"consumes": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml",
|
||||
"text/plain",
|
||||
"text/html"
|
||||
],
|
||||
"securityDefinitions": {
|
||||
"basic": {
|
||||
"type": "basic"
|
||||
},
|
||||
"apiKey": {
|
||||
"type": "apiKey",
|
||||
"in": "header",
|
||||
"name": "X-API-KEY"
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// RootPetStore20 json doc for swagger 2.0 pet store at /
|
||||
const RootPetStore20 = `{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"version": "1.0.0",
|
||||
"title": "Swagger Petstore",
|
||||
"contact": {
|
||||
"name": "Wordnik API Team",
|
||||
"url": "http://developer.wordnik.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "Creative Commons 4.0 International",
|
||||
"url": "http://creativecommons.org/licenses/by/4.0/"
|
||||
}
|
||||
},
|
||||
"host": "petstore.swagger.wordnik.com",
|
||||
"basePath": "/",
|
||||
"schemes": [
|
||||
"http"
|
||||
],
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"basic": []
|
||||
}
|
||||
],
|
||||
"tags": [ "Pet Operations" ],
|
||||
"operationId": "getAllPets",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "status",
|
||||
"in": "query",
|
||||
"description": "The status to filter by",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"summary": "Finds all pets in the system",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Pet response",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Pet"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Unexpected error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"basic": []
|
||||
}
|
||||
],
|
||||
"tags": [ "Pet Operations" ],
|
||||
"operationId": "createPet",
|
||||
"summary": "Creates a new pet",
|
||||
"consumes": ["application/x-yaml"],
|
||||
"produces": ["application/x-yaml"],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "pet",
|
||||
"in": "body",
|
||||
"description": "The Pet to create",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/newPet"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Created Pet response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Pet"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Unexpected error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/pets/{id}": {
|
||||
"delete": {
|
||||
"security": [
|
||||
{
|
||||
"apiKey": []
|
||||
}
|
||||
],
|
||||
"description": "Deletes the Pet by id",
|
||||
"operationId": "deletePet",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"description": "ID of pet to delete",
|
||||
"required": true,
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "pet deleted"
|
||||
},
|
||||
"default": {
|
||||
"description": "unexpected error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"get": {
|
||||
"tags": [ "Pet Operations" ],
|
||||
"operationId": "getPetById",
|
||||
"summary": "Finds the pet by id",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Pet response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Pet"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Unexpected error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"description": "ID of pet",
|
||||
"required": true,
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"Category": {
|
||||
"id": "Category",
|
||||
"properties": {
|
||||
"id": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Pet": {
|
||||
"id": "Pet",
|
||||
"properties": {
|
||||
"category": {
|
||||
"$ref": "#/definitions/Category"
|
||||
},
|
||||
"id": {
|
||||
"description": "unique identifier for the pet",
|
||||
"format": "int64",
|
||||
"maximum": 100.0,
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"photoUrls": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"status": {
|
||||
"description": "pet status in the store",
|
||||
"enum": [
|
||||
"available",
|
||||
"pending",
|
||||
"sold"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"tags": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/Tag"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name"
|
||||
]
|
||||
},
|
||||
"newPet": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Pet"
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"name"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"Tag": {
|
||||
"id": "Tag",
|
||||
"properties": {
|
||||
"id": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Error": {
|
||||
"required": [
|
||||
"code",
|
||||
"message"
|
||||
],
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"consumes": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml",
|
||||
"text/plain",
|
||||
"text/html"
|
||||
],
|
||||
"securityDefinitions": {
|
||||
"basic": {
|
||||
"type": "basic"
|
||||
},
|
||||
"apiKey": {
|
||||
"type": "apiKey",
|
||||
"in": "header",
|
||||
"name": "X-API-KEY"
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// PetStoreJSONMessage json raw message for Petstore20
|
||||
var PetStoreJSONMessage = json.RawMessage([]byte(PetStore20))
|
||||
|
||||
// RootPetStoreJSONMessage json raw message for Petstore20
|
||||
var RootPetStoreJSONMessage = json.RawMessage([]byte(RootPetStore20))
|
||||
|
||||
// InvalidJSON invalid swagger 2.0 spec in JSON
|
||||
const InvalidJSON = `{
|
||||
"apiVersion": "1.0.0",
|
||||
"apis": [
|
||||
{
|
||||
"description": "Operations about pets",
|
||||
"path": "/pet"
|
||||
},
|
||||
{
|
||||
"description": "Operations about user",
|
||||
"path": "/user"
|
||||
},
|
||||
{
|
||||
"description": "Operations about store",
|
||||
"path": "/store"
|
||||
}
|
||||
],
|
||||
"authorizations": {
|
||||
"oauth2": {
|
||||
"grantTypes": {
|
||||
"authorization_code": {
|
||||
"tokenEndpoint": {
|
||||
"tokenName": "auth_code",
|
||||
"url": "http://petstore.swagger.wordnik.com/oauth/token"
|
||||
},
|
||||
"tokenRequestEndpoint": {
|
||||
"clientIdName": "client_id",
|
||||
"clientSecretName": "client_secret",
|
||||
"url": "http://petstore.swagger.wordnik.com/oauth/requestToken"
|
||||
}
|
||||
},
|
||||
"implicit": {
|
||||
"loginEndpoint": {
|
||||
"url": "http://petstore.swagger.wordnik.com/oauth/dialog"
|
||||
},
|
||||
"tokenName": "access_token"
|
||||
}
|
||||
},
|
||||
"scopes": [
|
||||
{
|
||||
"description": "Modify pets in your account",
|
||||
"scope": "write:pets"
|
||||
},
|
||||
{
|
||||
"description": "Read your pets",
|
||||
"scope": "read:pets"
|
||||
},
|
||||
{
|
||||
"description": "Anything (testing)",
|
||||
"scope": "test:anything"
|
||||
}
|
||||
],
|
||||
"type": "oauth2"
|
||||
}
|
||||
},
|
||||
"info": {
|
||||
"contact": "apiteam@wordnik.com",
|
||||
"description": "This is a sample server Petstore server. You can find out more about Swagger \n at <a href=\"http://swagger.wordnik.com\">http://swagger.wordnik.com</a> or on irc.freenode.net, #swagger. For this sample,\n you can use the api key \"special-key\" to test the authorization filters",
|
||||
"license": "Apache 2.0",
|
||||
"licenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.html",
|
||||
"termsOfServiceUrl": "http://helloreverb.com/terms/",
|
||||
"title": "Swagger Sample App"
|
||||
},
|
||||
"swaggerVersion": "1.2"
|
||||
}
|
||||
`
|
||||
|
||||
// InvalidJSONMessage json raw message for invalid json
|
||||
var InvalidJSONMessage = json.RawMessage([]byte(InvalidJSON))
|
||||
147
vendor/github.com/go-openapi/runtime/internal/testing/petstore/api.go
generated
vendored
147
vendor/github.com/go-openapi/runtime/internal/testing/petstore/api.go
generated
vendored
@@ -1,147 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package petstore
|
||||
|
||||
import (
|
||||
"io"
|
||||
gotest "testing"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/runtime"
|
||||
testingutil "github.com/go-openapi/runtime/internal/testing"
|
||||
"github.com/go-openapi/runtime/middleware/untyped"
|
||||
"github.com/go-openapi/runtime/security"
|
||||
"github.com/go-openapi/runtime/yamlpc"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// NewAPI registers a stub api for the pet store
|
||||
func NewAPI(t gotest.TB) (*loads.Document, *untyped.API) {
|
||||
spec, err := loads.Analyzed(testingutil.PetStoreJSONMessage, "")
|
||||
assert.NoError(t, err)
|
||||
api := untyped.NewAPI(spec)
|
||||
|
||||
api.RegisterConsumer("application/json", runtime.JSONConsumer())
|
||||
api.RegisterProducer("application/json", runtime.JSONProducer())
|
||||
api.RegisterConsumer("application/xml", new(stubConsumer))
|
||||
api.RegisterProducer("application/xml", new(stubProducer))
|
||||
api.RegisterProducer("text/plain", new(stubProducer))
|
||||
api.RegisterProducer("text/html", new(stubProducer))
|
||||
api.RegisterConsumer("application/x-yaml", yamlpc.YAMLConsumer())
|
||||
api.RegisterProducer("application/x-yaml", yamlpc.YAMLProducer())
|
||||
|
||||
api.RegisterAuth("basic", security.BasicAuth(func(username, password string) (interface{}, error) {
|
||||
if username == "admin" && password == "admin" {
|
||||
return "admin", nil
|
||||
}
|
||||
return nil, errors.Unauthenticated("basic")
|
||||
}))
|
||||
api.RegisterAuth("apiKey", security.APIKeyAuth("X-API-KEY", "header", func(token string) (interface{}, error) {
|
||||
if token == "token123" {
|
||||
return "admin", nil
|
||||
}
|
||||
return nil, errors.Unauthenticated("token")
|
||||
}))
|
||||
api.RegisterOperation("get", "/pets", new(stubOperationHandler))
|
||||
api.RegisterOperation("post", "/pets", new(stubOperationHandler))
|
||||
api.RegisterOperation("delete", "/pets/{id}", new(stubOperationHandler))
|
||||
api.RegisterOperation("get", "/pets/{id}", new(stubOperationHandler))
|
||||
|
||||
api.Models["pet"] = func() interface{} { return new(Pet) }
|
||||
api.Models["newPet"] = func() interface{} { return new(Pet) }
|
||||
api.Models["tag"] = func() interface{} { return new(Tag) }
|
||||
|
||||
return spec, api
|
||||
}
|
||||
|
||||
// NewRootAPI registers a stub api for the pet store
|
||||
func NewRootAPI(t gotest.TB) (*loads.Document, *untyped.API) {
|
||||
spec, err := loads.Analyzed(testingutil.RootPetStoreJSONMessage, "")
|
||||
assert.NoError(t, err)
|
||||
api := untyped.NewAPI(spec)
|
||||
|
||||
api.RegisterConsumer("application/json", runtime.JSONConsumer())
|
||||
api.RegisterProducer("application/json", runtime.JSONProducer())
|
||||
api.RegisterConsumer("application/xml", new(stubConsumer))
|
||||
api.RegisterProducer("application/xml", new(stubProducer))
|
||||
api.RegisterProducer("text/plain", new(stubProducer))
|
||||
api.RegisterProducer("text/html", new(stubProducer))
|
||||
api.RegisterConsumer("application/x-yaml", yamlpc.YAMLConsumer())
|
||||
api.RegisterProducer("application/x-yaml", yamlpc.YAMLProducer())
|
||||
|
||||
api.RegisterAuth("basic", security.BasicAuth(func(username, password string) (interface{}, error) {
|
||||
if username == "admin" && password == "admin" {
|
||||
return "admin", nil
|
||||
}
|
||||
return nil, errors.Unauthenticated("basic")
|
||||
}))
|
||||
api.RegisterAuth("apiKey", security.APIKeyAuth("X-API-KEY", "header", func(token string) (interface{}, error) {
|
||||
if token == "token123" {
|
||||
return "admin", nil
|
||||
}
|
||||
return nil, errors.Unauthenticated("token")
|
||||
}))
|
||||
api.RegisterOperation("get", "/pets", new(stubOperationHandler))
|
||||
api.RegisterOperation("post", "/pets", new(stubOperationHandler))
|
||||
api.RegisterOperation("delete", "/pets/{id}", new(stubOperationHandler))
|
||||
api.RegisterOperation("get", "/pets/{id}", new(stubOperationHandler))
|
||||
|
||||
api.Models["pet"] = func() interface{} { return new(Pet) }
|
||||
api.Models["newPet"] = func() interface{} { return new(Pet) }
|
||||
api.Models["tag"] = func() interface{} { return new(Tag) }
|
||||
|
||||
return spec, api
|
||||
}
|
||||
|
||||
// Tag the tag model
|
||||
type Tag struct {
|
||||
ID int64
|
||||
Name string
|
||||
}
|
||||
|
||||
// Pet the pet model
|
||||
type Pet struct {
|
||||
ID int64
|
||||
Name string
|
||||
PhotoURLs []string
|
||||
Status string
|
||||
Tags []Tag
|
||||
}
|
||||
|
||||
type stubConsumer struct {
|
||||
}
|
||||
|
||||
func (s *stubConsumer) Consume(_ io.Reader, _ interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type stubProducer struct {
|
||||
}
|
||||
|
||||
func (s *stubProducer) Produce(_ io.Writer, _ interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type stubOperationHandler struct {
|
||||
}
|
||||
|
||||
func (s *stubOperationHandler) ParameterModel() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stubOperationHandler) Handle(params interface{}) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
351
vendor/github.com/go-openapi/runtime/internal/testing/simplepetstore/api.go
generated
vendored
351
vendor/github.com/go-openapi/runtime/internal/testing/simplepetstore/api.go
generated
vendored
@@ -1,351 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package simplepetstore
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/runtime/middleware/untyped"
|
||||
)
|
||||
|
||||
// NewPetstore creates a new petstore api handler
|
||||
func NewPetstore() (http.Handler, error) {
|
||||
spec, err := loads.Analyzed(json.RawMessage([]byte(swaggerJSON)), "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
api := untyped.NewAPI(spec)
|
||||
|
||||
api.RegisterOperation("get", "/pets", getAllPets)
|
||||
api.RegisterOperation("post", "/pets", createPet)
|
||||
api.RegisterOperation("delete", "/pets/{id}", deletePet)
|
||||
api.RegisterOperation("get", "/pets/{id}", getPetByID)
|
||||
|
||||
return middleware.Serve(spec, api), nil
|
||||
}
|
||||
|
||||
var getAllPets = runtime.OperationHandlerFunc(func(data interface{}) (interface{}, error) {
|
||||
return pets, nil
|
||||
})
|
||||
|
||||
var createPet = runtime.OperationHandlerFunc(func(data interface{}) (interface{}, error) {
|
||||
body := data.(map[string]interface{})["pet"].(map[string]interface{})
|
||||
return addPet(Pet{
|
||||
Name: body["name"].(string),
|
||||
Status: body["status"].(string),
|
||||
}), nil
|
||||
})
|
||||
|
||||
var deletePet = runtime.OperationHandlerFunc(func(data interface{}) (interface{}, error) {
|
||||
id := data.(map[string]interface{})["id"].(int64)
|
||||
removePet(id)
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
var getPetByID = runtime.OperationHandlerFunc(func(data interface{}) (interface{}, error) {
|
||||
id := data.(map[string]interface{})["id"].(int64)
|
||||
return petByID(id)
|
||||
})
|
||||
|
||||
// Tag the tag model
|
||||
type Tag struct {
|
||||
ID int64
|
||||
Name string
|
||||
}
|
||||
|
||||
// Pet the pet model
|
||||
type Pet struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
PhotoURLs []string `json:"photoUrls,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Tags []Tag `json:"tags,omitempty"`
|
||||
}
|
||||
|
||||
var pets = []Pet{
|
||||
{1, "Dog", []string{}, "available", nil},
|
||||
{2, "Cat", []string{}, "pending", nil},
|
||||
}
|
||||
|
||||
var petsLock = &sync.Mutex{}
|
||||
var lastPetID int64 = 2
|
||||
|
||||
func newPetID() int64 {
|
||||
return atomic.AddInt64(&lastPetID, 1)
|
||||
}
|
||||
|
||||
func addPet(pet Pet) Pet {
|
||||
petsLock.Lock()
|
||||
defer petsLock.Unlock()
|
||||
pet.ID = newPetID()
|
||||
pets = append(pets, pet)
|
||||
return pet
|
||||
}
|
||||
|
||||
func removePet(id int64) {
|
||||
petsLock.Lock()
|
||||
defer petsLock.Unlock()
|
||||
var newPets []Pet
|
||||
for _, pet := range pets {
|
||||
if pet.ID != id {
|
||||
newPets = append(newPets, pet)
|
||||
}
|
||||
}
|
||||
pets = newPets
|
||||
}
|
||||
|
||||
func petByID(id int64) (*Pet, error) {
|
||||
for _, pet := range pets {
|
||||
if pet.ID == id {
|
||||
return &pet, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.NotFound("not found: pet %d", id)
|
||||
}
|
||||
|
||||
var swaggerJSON = `{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"version": "1.0.0",
|
||||
"title": "Swagger Petstore",
|
||||
"description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification",
|
||||
"termsOfService": "http://helloreverb.com/terms/",
|
||||
"contact": {
|
||||
"name": "Wordnik API Team"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT"
|
||||
}
|
||||
},
|
||||
"host": "localhost:8344",
|
||||
"basePath": "/api",
|
||||
"schemes": [
|
||||
"http"
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"get": {
|
||||
"description": "Returns all pets from the system that the user has access to",
|
||||
"operationId": "findPets",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml",
|
||||
"text/xml",
|
||||
"text/html"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tags",
|
||||
"in": "query",
|
||||
"description": "tags to filter by",
|
||||
"required": false,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"collectionFormat": "csv"
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"description": "maximum number of results to return",
|
||||
"required": false,
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "pet response",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/pet"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "unexpected error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/errorModel"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"description": "Creates a new pet in the store. Duplicates are allowed",
|
||||
"operationId": "addPet",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "pet",
|
||||
"in": "body",
|
||||
"description": "Pet to add to the store",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/petInput"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "pet response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/pet"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "unexpected error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/errorModel"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/pets/{id}": {
|
||||
"get": {
|
||||
"description": "Returns a user based on a single ID, if the user does not have access to the pet",
|
||||
"operationId": "findPetById",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml",
|
||||
"text/xml",
|
||||
"text/html"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"description": "ID of pet to fetch",
|
||||
"required": true,
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "pet response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/pet"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "unexpected error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/errorModel"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"description": "deletes a single pet based on the ID supplied",
|
||||
"operationId": "deletePet",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"description": "ID of pet to delete",
|
||||
"required": true,
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "pet deleted"
|
||||
},
|
||||
"default": {
|
||||
"description": "unexpected error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/errorModel"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"pet": {
|
||||
"required": [
|
||||
"name",
|
||||
"status"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"petInput": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/pet"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"errorModel": {
|
||||
"required": [
|
||||
"code",
|
||||
"message"
|
||||
],
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
81
vendor/github.com/go-openapi/runtime/internal/testing/simplepetstore/api_test.go
generated
vendored
81
vendor/github.com/go-openapi/runtime/internal/testing/simplepetstore/api_test.go
generated
vendored
@@ -1,81 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package simplepetstore
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSimplePetstoreSpec(t *testing.T) {
|
||||
handler, _ := NewPetstore()
|
||||
// Serves swagger spec document
|
||||
r, _ := runtime.JSONRequest("GET", "/swagger.json", nil)
|
||||
rw := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rw, r)
|
||||
assert.Equal(t, 200, rw.Code)
|
||||
assert.Equal(t, swaggerJSON, rw.Body.String())
|
||||
}
|
||||
|
||||
func TestSimplePetstoreAllPets(t *testing.T) {
|
||||
handler, _ := NewPetstore()
|
||||
// Serves swagger spec document
|
||||
r, _ := runtime.JSONRequest("GET", "/api/pets", nil)
|
||||
rw := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rw, r)
|
||||
assert.Equal(t, 200, rw.Code)
|
||||
assert.Equal(t, "[{\"id\":1,\"name\":\"Dog\",\"status\":\"available\"},{\"id\":2,\"name\":\"Cat\",\"status\":\"pending\"}]\n", rw.Body.String())
|
||||
}
|
||||
|
||||
func TestSimplePetstorePetByID(t *testing.T) {
|
||||
handler, _ := NewPetstore()
|
||||
|
||||
// Serves swagger spec document
|
||||
r, _ := runtime.JSONRequest("GET", "/api/pets/1", nil)
|
||||
rw := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rw, r)
|
||||
assert.Equal(t, 200, rw.Code)
|
||||
assert.Equal(t, "{\"id\":1,\"name\":\"Dog\",\"status\":\"available\"}\n", rw.Body.String())
|
||||
}
|
||||
|
||||
func TestSimplePetstoreAddPet(t *testing.T) {
|
||||
handler, _ := NewPetstore()
|
||||
// Serves swagger spec document
|
||||
r, _ := runtime.JSONRequest("POST", "/api/pets", bytes.NewBuffer([]byte(`{"name": "Fish","status": "available"}`)))
|
||||
rw := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rw, r)
|
||||
assert.Equal(t, 200, rw.Code)
|
||||
assert.Equal(t, "{\"id\":3,\"name\":\"Fish\",\"status\":\"available\"}\n", rw.Body.String())
|
||||
}
|
||||
|
||||
func TestSimplePetstoreDeletePet(t *testing.T) {
|
||||
handler, _ := NewPetstore()
|
||||
// Serves swagger spec document
|
||||
r, _ := runtime.JSONRequest("DELETE", "/api/pets/1", nil)
|
||||
rw := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rw, r)
|
||||
assert.Equal(t, 204, rw.Code)
|
||||
assert.Equal(t, "", rw.Body.String())
|
||||
|
||||
r, _ = runtime.JSONRequest("GET", "/api/pets/1", nil)
|
||||
rw = httptest.NewRecorder()
|
||||
handler.ServeHTTP(rw, r)
|
||||
assert.Equal(t, 404, rw.Code)
|
||||
assert.Equal(t, "{\"code\":404,\"message\":\"not found: pet 1\"}", rw.Body.String())
|
||||
}
|
||||
62
vendor/github.com/go-openapi/runtime/json_test.go
generated
vendored
62
vendor/github.com/go-openapi/runtime/json_test.go
generated
vendored
@@ -1,62 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var consProdJSON = `{"name":"Somebody","id":1}`
|
||||
|
||||
type eofRdr struct {
|
||||
}
|
||||
|
||||
func (r *eofRdr) Read(d []byte) (int, error) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
func TestJSONConsumer(t *testing.T) {
|
||||
cons := JSONConsumer()
|
||||
var data struct {
|
||||
Name string
|
||||
ID int
|
||||
}
|
||||
err := cons.Consume(bytes.NewBuffer([]byte(consProdJSON)), &data)
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, "Somebody", data.Name)
|
||||
assert.Equal(t, 1, data.ID)
|
||||
|
||||
err = cons.Consume(new(eofRdr), &data)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONProducer(t *testing.T) {
|
||||
prod := JSONProducer()
|
||||
data := struct {
|
||||
Name string `json:"name"`
|
||||
ID int `json:"id"`
|
||||
}{Name: "Somebody", ID: 1}
|
||||
|
||||
rw := httptest.NewRecorder()
|
||||
err := prod.Produce(rw, data)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, consProdJSON+"\n", rw.Body.String())
|
||||
}
|
||||
101
vendor/github.com/go-openapi/runtime/middleware/body_test.go
generated
vendored
101
vendor/github.com/go-openapi/runtime/middleware/body_test.go
generated
vendored
@@ -1,101 +0,0 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/internal/testing/petstore"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type eofReader struct {
|
||||
}
|
||||
|
||||
func (r *eofReader) Read(b []byte) (int, error) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
func (r *eofReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type rbn func(*http.Request, *MatchedRoute) error
|
||||
|
||||
func (b rbn) BindRequest(r *http.Request, rr *MatchedRoute) error {
|
||||
return b(r, rr)
|
||||
}
|
||||
|
||||
func TestBindRequest_BodyValidation(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
ctx := NewContext(spec, api, nil)
|
||||
api.DefaultConsumes = runtime.JSONMime
|
||||
ctx.router = DefaultRouter(spec, ctx.api)
|
||||
|
||||
req, err := http.NewRequest("GET", path.Join(spec.BasePath(), "/pets"), new(eofReader))
|
||||
if assert.NoError(t, err) {
|
||||
req.Header.Set("Content-Type", runtime.JSONMime)
|
||||
|
||||
ri, ok := ctx.RouteInfo(req)
|
||||
if assert.True(t, ok) {
|
||||
|
||||
err := ctx.BindValidRequest(req, ri, rbn(func(r *http.Request, rr *MatchedRoute) error {
|
||||
defer r.Body.Close()
|
||||
var data interface{}
|
||||
err := runtime.JSONConsumer().Consume(r.Body, &data)
|
||||
_ = data
|
||||
return err
|
||||
}))
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, io.EOF, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBindRequest_DeleteNoBody(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
ctx := NewContext(spec, api, nil)
|
||||
api.DefaultConsumes = runtime.JSONMime
|
||||
ctx.router = DefaultRouter(spec, ctx.api)
|
||||
|
||||
req, err := http.NewRequest("DELETE", path.Join(spec.BasePath(), "/pets/123"), new(eofReader))
|
||||
if assert.NoError(t, err) {
|
||||
req.Header.Set("Accept", "*/*")
|
||||
|
||||
ri, ok := ctx.RouteInfo(req)
|
||||
if assert.True(t, ok) {
|
||||
|
||||
err := ctx.BindValidRequest(req, ri, rbn(func(r *http.Request, rr *MatchedRoute) error {
|
||||
return nil
|
||||
}))
|
||||
|
||||
assert.NoError(t, err)
|
||||
//assert.Equal(t, io.EOF, err)
|
||||
}
|
||||
}
|
||||
|
||||
req, err = http.NewRequest("DELETE", path.Join(spec.BasePath(), "/pets/123"), new(eofReader))
|
||||
if assert.NoError(t, err) {
|
||||
req.Header.Set("Accept", "*/*")
|
||||
req.Header.Set("Content-Type", runtime.JSONMime)
|
||||
req.ContentLength = 1
|
||||
|
||||
ri, ok := ctx.RouteInfo(req)
|
||||
if assert.True(t, ok) {
|
||||
|
||||
err := ctx.BindValidRequest(req, ri, rbn(func(r *http.Request, rr *MatchedRoute) error {
|
||||
defer r.Body.Close()
|
||||
var data interface{}
|
||||
err := runtime.JSONConsumer().Consume(r.Body, &data)
|
||||
_ = data
|
||||
return err
|
||||
}))
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, io.EOF, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
526
vendor/github.com/go-openapi/runtime/middleware/context.go
generated
vendored
526
vendor/github.com/go-openapi/runtime/middleware/context.go
generated
vendored
@@ -1,526 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware/untyped"
|
||||
"github.com/go-openapi/runtime/security"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/gorilla/context"
|
||||
)
|
||||
|
||||
// Debug when true turns on verbose logging
|
||||
var Debug = os.Getenv("SWAGGER_DEBUG") != "" || os.Getenv("DEBUG") != ""
|
||||
|
||||
func debugLog(format string, args ...interface{}) {
|
||||
if Debug {
|
||||
log.Printf(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// A Builder can create middlewares
|
||||
type Builder func(http.Handler) http.Handler
|
||||
|
||||
// PassthroughBuilder returns the handler, aka the builder identity function
|
||||
func PassthroughBuilder(handler http.Handler) http.Handler { return handler }
|
||||
|
||||
// RequestBinder is an interface for types to implement
|
||||
// when they want to be able to bind from a request
|
||||
type RequestBinder interface {
|
||||
BindRequest(*http.Request, *MatchedRoute) error
|
||||
}
|
||||
|
||||
// Responder is an interface for types to implement
|
||||
// when they want to be considered for writing HTTP responses
|
||||
type Responder interface {
|
||||
WriteResponse(http.ResponseWriter, runtime.Producer)
|
||||
}
|
||||
|
||||
// ResponderFunc wraps a func as a Responder interface
|
||||
type ResponderFunc func(http.ResponseWriter, runtime.Producer)
|
||||
|
||||
// WriteResponse writes to the response
|
||||
func (fn ResponderFunc) WriteResponse(rw http.ResponseWriter, pr runtime.Producer) {
|
||||
fn(rw, pr)
|
||||
}
|
||||
|
||||
// Context is a type safe wrapper around an untyped request context
|
||||
// used throughout to store request context with the gorilla context module
|
||||
type Context struct {
|
||||
spec *loads.Document
|
||||
analyzer *analysis.Spec
|
||||
api RoutableAPI
|
||||
router Router
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
type routableUntypedAPI struct {
|
||||
api *untyped.API
|
||||
hlock *sync.Mutex
|
||||
handlers map[string]map[string]http.Handler
|
||||
defaultConsumes string
|
||||
defaultProduces string
|
||||
}
|
||||
|
||||
func newRoutableUntypedAPI(spec *loads.Document, api *untyped.API, context *Context) *routableUntypedAPI {
|
||||
var handlers map[string]map[string]http.Handler
|
||||
if spec == nil || api == nil {
|
||||
return nil
|
||||
}
|
||||
analyzer := analysis.New(spec.Spec())
|
||||
for method, hls := range analyzer.Operations() {
|
||||
um := strings.ToUpper(method)
|
||||
for path, op := range hls {
|
||||
schemes := analyzer.SecurityDefinitionsFor(op)
|
||||
|
||||
if oh, ok := api.OperationHandlerFor(method, path); ok {
|
||||
if handlers == nil {
|
||||
handlers = make(map[string]map[string]http.Handler)
|
||||
}
|
||||
if b, ok := handlers[um]; !ok || b == nil {
|
||||
handlers[um] = make(map[string]http.Handler)
|
||||
}
|
||||
|
||||
var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// lookup route info in the context
|
||||
route, _ := context.RouteInfo(r)
|
||||
|
||||
// bind and validate the request using reflection
|
||||
bound, validation := context.BindAndValidate(r, route)
|
||||
if validation != nil {
|
||||
context.Respond(w, r, route.Produces, route, validation)
|
||||
return
|
||||
}
|
||||
|
||||
// actually handle the request
|
||||
result, err := oh.Handle(bound)
|
||||
if err != nil {
|
||||
// respond with failure
|
||||
context.Respond(w, r, route.Produces, route, err)
|
||||
return
|
||||
}
|
||||
|
||||
// respond with success
|
||||
context.Respond(w, r, route.Produces, route, result)
|
||||
})
|
||||
|
||||
if len(schemes) > 0 {
|
||||
handler = newSecureAPI(context, handler)
|
||||
}
|
||||
handlers[um][path] = handler
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &routableUntypedAPI{
|
||||
api: api,
|
||||
hlock: new(sync.Mutex),
|
||||
handlers: handlers,
|
||||
defaultProduces: api.DefaultProduces,
|
||||
defaultConsumes: api.DefaultConsumes,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *routableUntypedAPI) HandlerFor(method, path string) (http.Handler, bool) {
|
||||
r.hlock.Lock()
|
||||
paths, ok := r.handlers[strings.ToUpper(method)]
|
||||
if !ok {
|
||||
r.hlock.Unlock()
|
||||
return nil, false
|
||||
}
|
||||
handler, ok := paths[path]
|
||||
r.hlock.Unlock()
|
||||
return handler, ok
|
||||
}
|
||||
func (r *routableUntypedAPI) ServeErrorFor(operationID string) func(http.ResponseWriter, *http.Request, error) {
|
||||
return r.api.ServeError
|
||||
}
|
||||
func (r *routableUntypedAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer {
|
||||
return r.api.ConsumersFor(mediaTypes)
|
||||
}
|
||||
func (r *routableUntypedAPI) ProducersFor(mediaTypes []string) map[string]runtime.Producer {
|
||||
return r.api.ProducersFor(mediaTypes)
|
||||
}
|
||||
func (r *routableUntypedAPI) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[string]runtime.Authenticator {
|
||||
return r.api.AuthenticatorsFor(schemes)
|
||||
}
|
||||
func (r *routableUntypedAPI) Formats() strfmt.Registry {
|
||||
return r.api.Formats()
|
||||
}
|
||||
|
||||
func (r *routableUntypedAPI) DefaultProduces() string {
|
||||
return r.defaultProduces
|
||||
}
|
||||
|
||||
func (r *routableUntypedAPI) DefaultConsumes() string {
|
||||
return r.defaultConsumes
|
||||
}
|
||||
|
||||
// NewRoutableContext creates a new context for a routable API
|
||||
func NewRoutableContext(spec *loads.Document, routableAPI RoutableAPI, routes Router) *Context {
|
||||
var an *analysis.Spec
|
||||
if spec != nil {
|
||||
an = analysis.New(spec.Spec())
|
||||
}
|
||||
ctx := &Context{spec: spec, api: routableAPI, analyzer: an}
|
||||
return ctx
|
||||
}
|
||||
|
||||
// NewContext creates a new context wrapper
|
||||
func NewContext(spec *loads.Document, api *untyped.API, routes Router) *Context {
|
||||
var an *analysis.Spec
|
||||
if spec != nil {
|
||||
an = analysis.New(spec.Spec())
|
||||
}
|
||||
ctx := &Context{spec: spec, analyzer: an}
|
||||
ctx.api = newRoutableUntypedAPI(spec, api, ctx)
|
||||
return ctx
|
||||
}
|
||||
|
||||
// Serve serves the specified spec with the specified api registrations as a http.Handler
|
||||
func Serve(spec *loads.Document, api *untyped.API) http.Handler {
|
||||
return ServeWithBuilder(spec, api, PassthroughBuilder)
|
||||
}
|
||||
|
||||
// ServeWithBuilder serves the specified spec with the specified api registrations as a http.Handler that is decorated
|
||||
// by the Builder
|
||||
func ServeWithBuilder(spec *loads.Document, api *untyped.API, builder Builder) http.Handler {
|
||||
context := NewContext(spec, api, nil)
|
||||
return context.APIHandler(builder)
|
||||
}
|
||||
|
||||
type contextKey int8
|
||||
|
||||
const (
|
||||
_ contextKey = iota
|
||||
ctxContentType
|
||||
ctxResponseFormat
|
||||
ctxMatchedRoute
|
||||
ctxAllowedMethods
|
||||
ctxBoundParams
|
||||
ctxSecurityPrincipal
|
||||
ctxSecurityScopes
|
||||
|
||||
ctxConsumer
|
||||
)
|
||||
|
||||
type contentTypeValue struct {
|
||||
MediaType string
|
||||
Charset string
|
||||
}
|
||||
|
||||
// BasePath returns the base path for this API
|
||||
func (c *Context) BasePath() string {
|
||||
return c.spec.BasePath()
|
||||
}
|
||||
|
||||
// RequiredProduces returns the accepted content types for responses
|
||||
func (c *Context) RequiredProduces() []string {
|
||||
return c.analyzer.RequiredProduces()
|
||||
}
|
||||
|
||||
// BindValidRequest binds a params object to a request but only when the request is valid
|
||||
// if the request is not valid an error will be returned
|
||||
func (c *Context) BindValidRequest(request *http.Request, route *MatchedRoute, binder RequestBinder) error {
|
||||
var res []error
|
||||
|
||||
requestContentType := "*/*"
|
||||
// check and validate content type, select consumer
|
||||
if runtime.HasBody(request) {
|
||||
ct, _, err := runtime.ContentType(request.Header)
|
||||
if err != nil {
|
||||
res = append(res, err)
|
||||
} else {
|
||||
if err := validateContentType(route.Consumes, ct); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
if len(res) == 0 {
|
||||
cons, ok := route.Consumers[ct]
|
||||
if !ok {
|
||||
res = append(res, errors.New(500, "no consumer registered for %s", ct))
|
||||
} else {
|
||||
route.Consumer = cons
|
||||
requestContentType = ct
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check and validate the response format
|
||||
if len(res) == 0 && runtime.HasBody(request) {
|
||||
if str := NegotiateContentType(request, route.Produces, requestContentType); str == "" {
|
||||
res = append(res, errors.InvalidResponseFormat(request.Header.Get(runtime.HeaderAccept), route.Produces))
|
||||
}
|
||||
}
|
||||
|
||||
// now bind the request with the provided binder
|
||||
// it's assumed the binder will also validate the request and return an error if the
|
||||
// request is invalid
|
||||
if binder != nil && len(res) == 0 {
|
||||
if err := binder.BindRequest(request, route); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContentType gets the parsed value of a content type
|
||||
func (c *Context) ContentType(request *http.Request) (string, string, error) {
|
||||
if v, ok := context.GetOk(request, ctxContentType); ok {
|
||||
if val, ok := v.(*contentTypeValue); ok {
|
||||
return val.MediaType, val.Charset, nil
|
||||
}
|
||||
}
|
||||
|
||||
mt, cs, err := runtime.ContentType(request.Header)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
context.Set(request, ctxContentType, &contentTypeValue{mt, cs})
|
||||
return mt, cs, nil
|
||||
}
|
||||
|
||||
// LookupRoute looks a route up and returns true when it is found
|
||||
func (c *Context) LookupRoute(request *http.Request) (*MatchedRoute, bool) {
|
||||
if route, ok := c.router.Lookup(request.Method, request.URL.EscapedPath()); ok {
|
||||
return route, ok
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// RouteInfo tries to match a route for this request
|
||||
func (c *Context) RouteInfo(request *http.Request) (*MatchedRoute, bool) {
|
||||
if v, ok := context.GetOk(request, ctxMatchedRoute); ok {
|
||||
if val, ok := v.(*MatchedRoute); ok {
|
||||
return val, ok
|
||||
}
|
||||
}
|
||||
|
||||
if route, ok := c.LookupRoute(request); ok {
|
||||
context.Set(request, ctxMatchedRoute, route)
|
||||
return route, ok
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// ResponseFormat negotiates the response content type
|
||||
func (c *Context) ResponseFormat(r *http.Request, offers []string) string {
|
||||
if v, ok := context.GetOk(r, ctxResponseFormat); ok {
|
||||
if val, ok := v.(string); ok {
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
format := NegotiateContentType(r, offers, "")
|
||||
if format != "" {
|
||||
context.Set(r, ctxResponseFormat, format)
|
||||
}
|
||||
return format
|
||||
}
|
||||
|
||||
// AllowedMethods gets the allowed methods for the path of this request
|
||||
func (c *Context) AllowedMethods(request *http.Request) []string {
|
||||
return c.router.OtherMethods(request.Method, request.URL.EscapedPath())
|
||||
}
|
||||
|
||||
// Authorize authorizes the request
|
||||
func (c *Context) Authorize(request *http.Request, route *MatchedRoute) (interface{}, error) {
|
||||
if route == nil || len(route.Authenticators) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if v, ok := context.GetOk(request, ctxSecurityPrincipal); ok {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
var lastError error
|
||||
for scheme, authenticator := range route.Authenticators {
|
||||
applies, usr, err := authenticator.Authenticate(&security.ScopedAuthRequest{
|
||||
Request: request,
|
||||
RequiredScopes: route.Scopes[scheme],
|
||||
})
|
||||
if !applies || err != nil || usr == nil {
|
||||
if err != nil {
|
||||
lastError = err
|
||||
}
|
||||
continue
|
||||
}
|
||||
context.Set(request, ctxSecurityPrincipal, usr)
|
||||
context.Set(request, ctxSecurityScopes, route.Scopes[scheme])
|
||||
return usr, nil
|
||||
}
|
||||
|
||||
if lastError != nil {
|
||||
return nil, lastError
|
||||
}
|
||||
|
||||
return nil, errors.Unauthenticated("invalid credentials")
|
||||
}
|
||||
|
||||
// BindAndValidate binds and validates the request
|
||||
func (c *Context) BindAndValidate(request *http.Request, matched *MatchedRoute) (interface{}, error) {
|
||||
if v, ok := context.GetOk(request, ctxBoundParams); ok {
|
||||
if val, ok := v.(*validation); ok {
|
||||
debugLog("got cached validation (valid: %t)", len(val.result) == 0)
|
||||
if len(val.result) > 0 {
|
||||
return val.bound, errors.CompositeValidationError(val.result...)
|
||||
}
|
||||
return val.bound, nil
|
||||
}
|
||||
}
|
||||
result := validateRequest(c, request, matched)
|
||||
if result != nil {
|
||||
context.Set(request, ctxBoundParams, result)
|
||||
}
|
||||
if len(result.result) > 0 {
|
||||
return result.bound, errors.CompositeValidationError(result.result...)
|
||||
}
|
||||
debugLog("no validation errors found")
|
||||
return result.bound, nil
|
||||
}
|
||||
|
||||
// NotFound the default not found responder for when no route has been matched yet
|
||||
func (c *Context) NotFound(rw http.ResponseWriter, r *http.Request) {
|
||||
c.Respond(rw, r, []string{c.api.DefaultProduces()}, nil, errors.NotFound("not found"))
|
||||
}
|
||||
|
||||
// Respond renders the response after doing some content negotiation
|
||||
func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []string, route *MatchedRoute, data interface{}) {
|
||||
offers := []string{}
|
||||
for _, mt := range produces {
|
||||
if mt != c.api.DefaultProduces() {
|
||||
offers = append(offers, mt)
|
||||
}
|
||||
}
|
||||
// the default producer is last so more specific producers take precedence
|
||||
offers = append(offers, c.api.DefaultProduces())
|
||||
|
||||
format := c.ResponseFormat(r, offers)
|
||||
rw.Header().Set(runtime.HeaderContentType, format)
|
||||
|
||||
if resp, ok := data.(Responder); ok {
|
||||
producers := route.Producers
|
||||
prod, ok := producers[format]
|
||||
if !ok {
|
||||
prods := c.api.ProducersFor([]string{c.api.DefaultProduces()})
|
||||
pr, ok := prods[c.api.DefaultProduces()]
|
||||
if !ok {
|
||||
panic(errors.New(http.StatusInternalServerError, "can't find a producer for "+format))
|
||||
}
|
||||
prod = pr
|
||||
}
|
||||
resp.WriteResponse(rw, prod)
|
||||
return
|
||||
}
|
||||
|
||||
if err, ok := data.(error); ok {
|
||||
if format == "" {
|
||||
rw.Header().Set(runtime.HeaderContentType, runtime.JSONMime)
|
||||
}
|
||||
if route == nil || route.Operation == nil {
|
||||
c.api.ServeErrorFor("")(rw, r, err)
|
||||
return
|
||||
}
|
||||
c.api.ServeErrorFor(route.Operation.ID)(rw, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
if route == nil || route.Operation == nil {
|
||||
rw.WriteHeader(200)
|
||||
if r.Method == "HEAD" {
|
||||
return
|
||||
}
|
||||
producers := c.api.ProducersFor(offers)
|
||||
prod, ok := producers[format]
|
||||
if !ok {
|
||||
panic(errors.New(http.StatusInternalServerError, "can't find a producer for "+format))
|
||||
}
|
||||
if err := prod.Produce(rw, data); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if _, code, ok := route.Operation.SuccessResponse(); ok {
|
||||
rw.WriteHeader(code)
|
||||
if code == 204 || r.Method == "HEAD" {
|
||||
return
|
||||
}
|
||||
|
||||
producers := route.Producers
|
||||
prod, ok := producers[format]
|
||||
if !ok {
|
||||
if !ok {
|
||||
prods := c.api.ProducersFor([]string{c.api.DefaultProduces()})
|
||||
pr, ok := prods[c.api.DefaultProduces()]
|
||||
if !ok {
|
||||
panic(errors.New(http.StatusInternalServerError, "can't find a producer for "+format))
|
||||
}
|
||||
prod = pr
|
||||
}
|
||||
}
|
||||
if err := prod.Produce(rw, data); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
c.api.ServeErrorFor(route.Operation.ID)(rw, r, errors.New(http.StatusInternalServerError, "can't produce response"))
|
||||
}
|
||||
|
||||
// APIHandler returns a handler to serve the API, this includes a swagger spec, router and the contract defined in the swagger spec
|
||||
func (c *Context) APIHandler(builder Builder) http.Handler {
|
||||
b := builder
|
||||
if b == nil {
|
||||
b = PassthroughBuilder
|
||||
}
|
||||
|
||||
var title string
|
||||
sp := c.spec.Spec()
|
||||
if sp != nil && sp.Info != nil && sp.Info.Title != "" {
|
||||
title = sp.Info.Title
|
||||
}
|
||||
|
||||
redocOpts := RedocOpts{
|
||||
BasePath: c.BasePath(),
|
||||
Title: title,
|
||||
}
|
||||
|
||||
return Spec("", c.spec.Raw(), Redoc(redocOpts, c.RoutesHandler(builder)))
|
||||
}
|
||||
|
||||
// RoutesHandler returns a handler to serve the API, just the routes and the contract defined in the swagger spec
|
||||
func (c *Context) RoutesHandler(builder Builder) http.Handler {
|
||||
b := builder
|
||||
if b == nil {
|
||||
b = PassthroughBuilder
|
||||
}
|
||||
return NewRouter(c, b(NewOperationExecutor(c)))
|
||||
}
|
||||
395
vendor/github.com/go-openapi/runtime/middleware/context_test.go
generated
vendored
395
vendor/github.com/go-openapi/runtime/middleware/context_test.go
generated
vendored
@@ -1,395 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/loads/fmts"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/internal/testing/petstore"
|
||||
"github.com/go-openapi/runtime/middleware/untyped"
|
||||
"github.com/gorilla/context"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type stubOperationHandler struct {
|
||||
}
|
||||
|
||||
func (s *stubOperationHandler) ParameterModel() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stubOperationHandler) Handle(params interface{}) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type testBinder struct {
|
||||
}
|
||||
|
||||
func (t *testBinder) BindRequest(r *http.Request, m *MatchedRoute) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
loads.AddLoader(fmts.YAMLMatcher, fmts.YAMLDoc)
|
||||
}
|
||||
|
||||
func TestContentType_Issue264(t *testing.T) {
|
||||
swspec, err := loads.Spec("../fixtures/bugs/264/swagger.yml")
|
||||
if assert.NoError(t, err) {
|
||||
api := untyped.NewAPI(swspec)
|
||||
api.RegisterConsumer("application/json", runtime.JSONConsumer())
|
||||
api.RegisterProducer("application/json", runtime.JSONProducer())
|
||||
api.RegisterOperation("delete", "/key/{id}", new(stubOperationHandler))
|
||||
|
||||
handler := Serve(swspec, api)
|
||||
request, _ := http.NewRequest("DELETE", "/key/1", nil)
|
||||
recorder := httptest.NewRecorder()
|
||||
handler.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServe(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
handler := Serve(spec, api)
|
||||
|
||||
// serve spec document
|
||||
request, _ := http.NewRequest("GET", "http://localhost:8080/swagger.json", nil)
|
||||
request.Header.Add("Content-Type", runtime.JSONMime)
|
||||
request.Header.Add("Accept", runtime.JSONMime)
|
||||
recorder := httptest.NewRecorder()
|
||||
|
||||
handler.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
|
||||
request, _ = http.NewRequest("GET", "http://localhost:8080/swagger-ui", nil)
|
||||
recorder = httptest.NewRecorder()
|
||||
|
||||
handler.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 404, recorder.Code)
|
||||
}
|
||||
|
||||
func TestContextAuthorize(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
ctx := NewContext(spec, api, nil)
|
||||
ctx.router = DefaultRouter(spec, ctx.api)
|
||||
|
||||
request, _ := runtime.JSONRequest("GET", "/api/pets", nil)
|
||||
|
||||
v, ok := context.GetOk(request, ctxSecurityPrincipal)
|
||||
assert.False(t, ok)
|
||||
assert.Nil(t, v)
|
||||
|
||||
ri, ok := ctx.RouteInfo(request)
|
||||
assert.True(t, ok)
|
||||
p, err := ctx.Authorize(request, ri)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, p)
|
||||
|
||||
v, ok = context.GetOk(request, ctxSecurityPrincipal)
|
||||
assert.False(t, ok)
|
||||
assert.Nil(t, v)
|
||||
|
||||
request.SetBasicAuth("wrong", "wrong")
|
||||
p, err = ctx.Authorize(request, ri)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, p)
|
||||
|
||||
v, ok = context.GetOk(request, ctxSecurityPrincipal)
|
||||
assert.False(t, ok)
|
||||
assert.Nil(t, v)
|
||||
|
||||
request.SetBasicAuth("admin", "admin")
|
||||
p, err = ctx.Authorize(request, ri)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "admin", p)
|
||||
|
||||
v, ok = context.GetOk(request, ctxSecurityPrincipal)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "admin", v)
|
||||
|
||||
request.SetBasicAuth("doesn't matter", "doesn't")
|
||||
pp, rr := ctx.Authorize(request, ri)
|
||||
assert.Equal(t, p, pp)
|
||||
assert.Equal(t, err, rr)
|
||||
}
|
||||
|
||||
func TestContextNegotiateContentType(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
ctx := NewContext(spec, api, nil)
|
||||
ctx.router = DefaultRouter(spec, ctx.api)
|
||||
|
||||
request, _ := http.NewRequest("POST", "/api/pets", nil)
|
||||
// request.Header.Add("Accept", "*/*")
|
||||
request.Header.Add("content-type", "text/html")
|
||||
|
||||
v, ok := context.GetOk(request, ctxBoundParams)
|
||||
assert.False(t, ok)
|
||||
assert.Nil(t, v)
|
||||
|
||||
ri, _ := ctx.RouteInfo(request)
|
||||
|
||||
res := NegotiateContentType(request, ri.Produces, "")
|
||||
assert.Equal(t, "", res)
|
||||
|
||||
res2 := NegotiateContentType(request, ri.Produces, "text/plain")
|
||||
assert.Equal(t, "text/plain", res2)
|
||||
}
|
||||
|
||||
func TestContextBindAndValidate(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
ctx := NewContext(spec, api, nil)
|
||||
ctx.router = DefaultRouter(spec, ctx.api)
|
||||
|
||||
request, _ := http.NewRequest("POST", "/api/pets", nil)
|
||||
request.Header.Add("Accept", "*/*")
|
||||
request.Header.Add("content-type", "text/html")
|
||||
request.ContentLength = 1
|
||||
|
||||
v, ok := context.GetOk(request, ctxBoundParams)
|
||||
assert.False(t, ok)
|
||||
assert.Nil(t, v)
|
||||
|
||||
ri, _ := ctx.RouteInfo(request)
|
||||
data, result := ctx.BindAndValidate(request, ri) // this requires a much more thorough test
|
||||
assert.NotNil(t, data)
|
||||
assert.NotNil(t, result)
|
||||
|
||||
v, ok = context.GetOk(request, ctxBoundParams)
|
||||
assert.True(t, ok)
|
||||
assert.NotNil(t, v)
|
||||
|
||||
dd, rr := ctx.BindAndValidate(request, ri)
|
||||
assert.Equal(t, data, dd)
|
||||
assert.Equal(t, result, rr)
|
||||
}
|
||||
|
||||
func TestContextRender(t *testing.T) {
|
||||
ct := runtime.JSONMime
|
||||
spec, api := petstore.NewAPI(t)
|
||||
|
||||
assert.NotNil(t, spec)
|
||||
assert.NotNil(t, api)
|
||||
ctx := NewContext(spec, api, nil)
|
||||
ctx.router = DefaultRouter(spec, ctx.api)
|
||||
|
||||
request, _ := http.NewRequest("GET", "pets", nil)
|
||||
request.Header.Set(runtime.HeaderAccept, ct)
|
||||
ri, _ := ctx.RouteInfo(request)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
ctx.Respond(recorder, request, []string{ct}, ri, map[string]interface{}{"name": "hello"})
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Equal(t, "{\"name\":\"hello\"}\n", recorder.Body.String())
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
ctx.Respond(recorder, request, []string{ct}, ri, errors.New("this went wrong"))
|
||||
assert.Equal(t, 500, recorder.Code)
|
||||
|
||||
// recorder = httptest.NewRecorder()
|
||||
// assert.Panics(t, func() { ctx.Respond(recorder, request, []string{ct}, ri, map[int]interface{}{1: "hello"}) })
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("GET", "pets", nil)
|
||||
assert.Panics(t, func() { ctx.Respond(recorder, request, []string{}, ri, map[string]interface{}{"name": "hello"}) })
|
||||
|
||||
request, _ = http.NewRequest("GET", "/pets", nil)
|
||||
request.Header.Set(runtime.HeaderAccept, ct)
|
||||
ri, _ = ctx.RouteInfo(request)
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
ctx.Respond(recorder, request, []string{ct}, ri, map[string]interface{}{"name": "hello"})
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Equal(t, "{\"name\":\"hello\"}\n", recorder.Body.String())
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
ctx.Respond(recorder, request, []string{ct}, ri, errors.New("this went wrong"))
|
||||
assert.Equal(t, 500, recorder.Code)
|
||||
|
||||
// recorder = httptest.NewRecorder()
|
||||
// assert.Panics(t, func() { ctx.Respond(recorder, request, []string{ct}, ri, map[int]interface{}{1: "hello"}) })
|
||||
|
||||
// recorder = httptest.NewRecorder()
|
||||
// request, _ = http.NewRequest("GET", "/pets", nil)
|
||||
// assert.Panics(t, func() { ctx.Respond(recorder, request, []string{}, ri, map[string]interface{}{"name": "hello"}) })
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("DELETE", "/api/pets/1", nil)
|
||||
ri, _ = ctx.RouteInfo(request)
|
||||
ctx.Respond(recorder, request, ri.Produces, ri, nil)
|
||||
assert.Equal(t, 204, recorder.Code)
|
||||
}
|
||||
|
||||
func TestContextValidResponseFormat(t *testing.T) {
|
||||
ct := "application/json"
|
||||
spec, api := petstore.NewAPI(t)
|
||||
ctx := NewContext(spec, api, nil)
|
||||
ctx.router = DefaultRouter(spec, ctx.api)
|
||||
|
||||
request, _ := http.NewRequest("GET", "http://localhost:8080", nil)
|
||||
request.Header.Set(runtime.HeaderAccept, ct)
|
||||
|
||||
// check there's nothing there
|
||||
cached, ok := context.GetOk(request, ctxResponseFormat)
|
||||
assert.False(t, ok)
|
||||
assert.Empty(t, cached)
|
||||
|
||||
// trigger the parse
|
||||
mt := ctx.ResponseFormat(request, []string{ct})
|
||||
assert.Equal(t, ct, mt)
|
||||
|
||||
// check it was cached
|
||||
cached, ok = context.GetOk(request, ctxResponseFormat)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, ct, cached)
|
||||
|
||||
// check if the cast works and fetch from cache too
|
||||
mt = ctx.ResponseFormat(request, []string{ct})
|
||||
assert.Equal(t, ct, mt)
|
||||
}
|
||||
|
||||
func TestContextInvalidResponseFormat(t *testing.T) {
|
||||
ct := "application/x-yaml"
|
||||
other := "application/sgml"
|
||||
spec, api := petstore.NewAPI(t)
|
||||
ctx := NewContext(spec, api, nil)
|
||||
ctx.router = DefaultRouter(spec, ctx.api)
|
||||
|
||||
request, _ := http.NewRequest("GET", "http://localhost:8080", nil)
|
||||
request.Header.Set(runtime.HeaderAccept, ct)
|
||||
|
||||
// check there's nothing there
|
||||
cached, ok := context.GetOk(request, ctxResponseFormat)
|
||||
assert.False(t, ok)
|
||||
assert.Empty(t, cached)
|
||||
|
||||
// trigger the parse
|
||||
mt := ctx.ResponseFormat(request, []string{other})
|
||||
assert.Empty(t, mt)
|
||||
|
||||
// check it was cached
|
||||
cached, ok = context.GetOk(request, ctxResponseFormat)
|
||||
assert.False(t, ok)
|
||||
assert.Empty(t, cached)
|
||||
|
||||
// check if the cast works and fetch from cache too
|
||||
mt = ctx.ResponseFormat(request, []string{other})
|
||||
assert.Empty(t, mt)
|
||||
}
|
||||
|
||||
func TestContextValidRoute(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
ctx := NewContext(spec, api, nil)
|
||||
ctx.router = DefaultRouter(spec, ctx.api)
|
||||
|
||||
request, _ := http.NewRequest("GET", "/api/pets", nil)
|
||||
|
||||
// check there's nothing there
|
||||
_, ok := context.GetOk(request, ctxMatchedRoute)
|
||||
assert.False(t, ok)
|
||||
|
||||
matched, ok := ctx.RouteInfo(request)
|
||||
assert.True(t, ok)
|
||||
assert.NotNil(t, matched)
|
||||
|
||||
// check it was cached
|
||||
_, ok = context.GetOk(request, ctxMatchedRoute)
|
||||
assert.True(t, ok)
|
||||
|
||||
matched, ok = ctx.RouteInfo(request)
|
||||
assert.True(t, ok)
|
||||
assert.NotNil(t, matched)
|
||||
}
|
||||
|
||||
func TestContextInvalidRoute(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
ctx := NewContext(spec, api, nil)
|
||||
ctx.router = DefaultRouter(spec, ctx.api)
|
||||
|
||||
request, _ := http.NewRequest("DELETE", "pets", nil)
|
||||
|
||||
// check there's nothing there
|
||||
_, ok := context.GetOk(request, ctxMatchedRoute)
|
||||
assert.False(t, ok)
|
||||
|
||||
matched, ok := ctx.RouteInfo(request)
|
||||
assert.False(t, ok)
|
||||
assert.Nil(t, matched)
|
||||
|
||||
// check it was cached
|
||||
_, ok = context.GetOk(request, ctxMatchedRoute)
|
||||
assert.False(t, ok)
|
||||
|
||||
matched, ok = ctx.RouteInfo(request)
|
||||
assert.False(t, ok)
|
||||
assert.Nil(t, matched)
|
||||
}
|
||||
|
||||
func TestContextValidContentType(t *testing.T) {
|
||||
ct := "application/json"
|
||||
ctx := NewContext(nil, nil, nil)
|
||||
|
||||
request, _ := http.NewRequest("GET", "http://localhost:8080", nil)
|
||||
request.Header.Set(runtime.HeaderContentType, ct)
|
||||
|
||||
// check there's nothing there
|
||||
_, ok := context.GetOk(request, ctxContentType)
|
||||
assert.False(t, ok)
|
||||
|
||||
// trigger the parse
|
||||
mt, _, err := ctx.ContentType(request)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, ct, mt)
|
||||
|
||||
// check it was cached
|
||||
_, ok = context.GetOk(request, ctxContentType)
|
||||
assert.True(t, ok)
|
||||
|
||||
// check if the cast works and fetch from cache too
|
||||
mt, _, err = ctx.ContentType(request)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, ct, mt)
|
||||
}
|
||||
|
||||
func TestContextInvalidContentType(t *testing.T) {
|
||||
ct := "application("
|
||||
ctx := NewContext(nil, nil, nil)
|
||||
|
||||
request, _ := http.NewRequest("GET", "http://localhost:8080", nil)
|
||||
request.Header.Set(runtime.HeaderContentType, ct)
|
||||
|
||||
// check there's nothing there
|
||||
_, ok := context.GetOk(request, ctxContentType)
|
||||
assert.False(t, ok)
|
||||
|
||||
// trigger the parse
|
||||
mt, _, err := ctx.ContentType(request)
|
||||
assert.Error(t, err)
|
||||
assert.Empty(t, mt)
|
||||
|
||||
// check it was not cached
|
||||
_, ok = context.GetOk(request, ctxContentType)
|
||||
assert.False(t, ok)
|
||||
|
||||
// check if the failure continues
|
||||
_, _, err = ctx.ContentType(request)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
180
vendor/github.com/go-openapi/runtime/middleware/denco/README.md
generated
vendored
180
vendor/github.com/go-openapi/runtime/middleware/denco/README.md
generated
vendored
@@ -1,180 +0,0 @@
|
||||
# Denco [](https://travis-ci.org/naoina/denco)
|
||||
|
||||
The fast and flexible HTTP request router for [Go](http://golang.org).
|
||||
|
||||
Denco is based on Double-Array implementation of [Kocha-urlrouter](https://github.com/naoina/kocha-urlrouter).
|
||||
However, Denco is optimized and some features added.
|
||||
|
||||
## Features
|
||||
|
||||
* Fast (See [go-http-routing-benchmark](https://github.com/naoina/go-http-routing-benchmark))
|
||||
* [URL patterns](#url-patterns) (`/foo/:bar` and `/foo/*wildcard`)
|
||||
* Small (but enough) URL router API
|
||||
* HTTP request multiplexer like `http.ServeMux`
|
||||
|
||||
## Installation
|
||||
|
||||
go get -u github.com/go-openapi/runtime/middleware/denco
|
||||
|
||||
## Using as HTTP request multiplexer
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware/denco"
|
||||
)
|
||||
|
||||
func Index(w http.ResponseWriter, r *http.Request, params denco.Params) {
|
||||
fmt.Fprintf(w, "Welcome to Denco!\n")
|
||||
}
|
||||
|
||||
func User(w http.ResponseWriter, r *http.Request, params denco.Params) {
|
||||
fmt.Fprintf(w, "Hello %s!\n", params.Get("name"))
|
||||
}
|
||||
|
||||
func main() {
|
||||
mux := denco.NewMux()
|
||||
handler, err := mux.Build([]denco.Handler{
|
||||
mux.GET("/", Index),
|
||||
mux.GET("/user/:name", User),
|
||||
mux.POST("/user/:name", User),
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Fatal(http.ListenAndServe(":8080", handler))
|
||||
}
|
||||
```
|
||||
|
||||
## Using as URL router
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware/denco"
|
||||
)
|
||||
|
||||
type route struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func main() {
|
||||
router := denco.New()
|
||||
router.Build([]denco.Record{
|
||||
{"/", &route{"root"}},
|
||||
{"/user/:id", &route{"user"}},
|
||||
{"/user/:name/:id", &route{"username"}},
|
||||
{"/static/*filepath", &route{"static"}},
|
||||
})
|
||||
|
||||
data, params, found := router.Lookup("/")
|
||||
// print `&main.route{name:"root"}, denco.Params(nil), true`.
|
||||
fmt.Printf("%#v, %#v, %#v\n", data, params, found)
|
||||
|
||||
data, params, found = router.Lookup("/user/hoge")
|
||||
// print `&main.route{name:"user"}, denco.Params{denco.Param{Name:"id", Value:"hoge"}}, true`.
|
||||
fmt.Printf("%#v, %#v, %#v\n", data, params, found)
|
||||
|
||||
data, params, found = router.Lookup("/user/hoge/7")
|
||||
// print `&main.route{name:"username"}, denco.Params{denco.Param{Name:"name", Value:"hoge"}, denco.Param{Name:"id", Value:"7"}}, true`.
|
||||
fmt.Printf("%#v, %#v, %#v\n", data, params, found)
|
||||
|
||||
data, params, found = router.Lookup("/static/path/to/file")
|
||||
// print `&main.route{name:"static"}, denco.Params{denco.Param{Name:"filepath", Value:"path/to/file"}}, true`.
|
||||
fmt.Printf("%#v, %#v, %#v\n", data, params, found)
|
||||
}
|
||||
```
|
||||
|
||||
See [Godoc](http://godoc.org/github.com/go-openapi/runtime/middleware/denco) for more details.
|
||||
|
||||
## Getting the value of path parameter
|
||||
|
||||
You can get the value of path parameter by 2 ways.
|
||||
|
||||
1. Using [`denco.Params.Get`](http://godoc.org/github.com/go-openapi/runtime/middleware/denco#Params.Get) method
|
||||
2. Find by loop
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware/denco"
|
||||
)
|
||||
|
||||
func main() {
|
||||
router := denco.New()
|
||||
if err := router.Build([]denco.Record{
|
||||
{"/user/:name/:id", "route1"},
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 1. Using denco.Params.Get method.
|
||||
_, params, _ := router.Lookup("/user/alice/1")
|
||||
name := params.Get("name")
|
||||
if name != "" {
|
||||
fmt.Printf("Hello %s.\n", name) // prints "Hello alice.".
|
||||
}
|
||||
|
||||
// 2. Find by loop.
|
||||
for _, param := range params {
|
||||
if param.Name == "name" {
|
||||
fmt.Printf("Hello %s.\n", name) // prints "Hello alice.".
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## URL patterns
|
||||
|
||||
Denco's route matching strategy is "most nearly matching".
|
||||
|
||||
When routes `/:name` and `/alice` have been built, URI `/alice` matches the route `/alice`, not `/:name`.
|
||||
Because URI `/alice` is more match with the route `/alice` than `/:name`.
|
||||
|
||||
For more example, when routes below have been built:
|
||||
|
||||
```
|
||||
/user/alice
|
||||
/user/:name
|
||||
/user/:name/:id
|
||||
/user/alice/:id
|
||||
/user/:id/bob
|
||||
```
|
||||
|
||||
Routes matching are:
|
||||
|
||||
```
|
||||
/user/alice => "/user/alice" (no match with "/user/:name")
|
||||
/user/bob => "/user/:name"
|
||||
/user/naoina/1 => "/user/:name/1"
|
||||
/user/alice/1 => "/user/alice/:id" (no match with "/user/:name/:id")
|
||||
/user/1/bob => "/user/:id/bob" (no match with "/user/:name/:id")
|
||||
/user/alice/bob => "/user/alice/:id" (no match with "/user/:name/:id" and "/user/:id/bob")
|
||||
```
|
||||
|
||||
## Limitation
|
||||
|
||||
Denco has some limitations below.
|
||||
|
||||
* Number of param records (such as `/:name`) must be less than 2^22
|
||||
* Number of elements of internal slice must be less than 2^22
|
||||
|
||||
## Benchmarks
|
||||
|
||||
cd $GOPATH/github.com/go-openapi/runtime/middleware/denco
|
||||
go test -bench . -benchmem
|
||||
|
||||
## License
|
||||
|
||||
Denco is licensed under the MIT License.
|
||||
452
vendor/github.com/go-openapi/runtime/middleware/denco/router.go
generated
vendored
452
vendor/github.com/go-openapi/runtime/middleware/denco/router.go
generated
vendored
@@ -1,452 +0,0 @@
|
||||
// Package denco provides fast URL router.
|
||||
package denco
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// ParamCharacter is a special character for path parameter.
|
||||
ParamCharacter = ':'
|
||||
|
||||
// WildcardCharacter is a special character for wildcard path parameter.
|
||||
WildcardCharacter = '*'
|
||||
|
||||
// TerminationCharacter is a special character for end of path.
|
||||
TerminationCharacter = '#'
|
||||
|
||||
// MaxSize is max size of records and internal slice.
|
||||
MaxSize = (1 << 22) - 1
|
||||
)
|
||||
|
||||
// Router represents a URL router.
|
||||
type Router struct {
|
||||
// SizeHint expects the maximum number of path parameters in records to Build.
|
||||
// SizeHint will be used to determine the capacity of the memory to allocate.
|
||||
// By default, SizeHint will be determined from given records to Build.
|
||||
SizeHint int
|
||||
|
||||
static map[string]interface{}
|
||||
param *doubleArray
|
||||
}
|
||||
|
||||
// New returns a new Router.
|
||||
func New() *Router {
|
||||
return &Router{
|
||||
SizeHint: -1,
|
||||
static: make(map[string]interface{}),
|
||||
param: newDoubleArray(),
|
||||
}
|
||||
}
|
||||
|
||||
// Lookup returns data and path parameters that associated with path.
|
||||
// params is a slice of the Param that arranged in the order in which parameters appeared.
|
||||
// e.g. when built routing path is "/path/to/:id/:name" and given path is "/path/to/1/alice". params order is [{"id": "1"}, {"name": "alice"}], not [{"name": "alice"}, {"id": "1"}].
|
||||
func (rt *Router) Lookup(path string) (data interface{}, params Params, found bool) {
|
||||
if data, found := rt.static[path]; found {
|
||||
return data, nil, true
|
||||
}
|
||||
if len(rt.param.node) == 1 {
|
||||
return nil, nil, false
|
||||
}
|
||||
nd, params, found := rt.param.lookup(path, make([]Param, 0, rt.SizeHint), 1)
|
||||
if !found {
|
||||
return nil, nil, false
|
||||
}
|
||||
for i := 0; i < len(params); i++ {
|
||||
params[i].Name = nd.paramNames[i]
|
||||
}
|
||||
return nd.data, params, true
|
||||
}
|
||||
|
||||
// Build builds URL router from records.
|
||||
func (rt *Router) Build(records []Record) error {
|
||||
statics, params := makeRecords(records)
|
||||
if len(params) > MaxSize {
|
||||
return fmt.Errorf("denco: too many records")
|
||||
}
|
||||
if rt.SizeHint < 0 {
|
||||
rt.SizeHint = 0
|
||||
for _, p := range params {
|
||||
size := 0
|
||||
for _, k := range p.Key {
|
||||
if k == ParamCharacter || k == WildcardCharacter {
|
||||
size++
|
||||
}
|
||||
}
|
||||
if size > rt.SizeHint {
|
||||
rt.SizeHint = size
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, r := range statics {
|
||||
rt.static[r.Key] = r.Value
|
||||
}
|
||||
if err := rt.param.build(params, 1, 0, make(map[int]struct{})); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Param represents name and value of path parameter.
|
||||
type Param struct {
|
||||
Name string
|
||||
Value string
|
||||
}
|
||||
|
||||
// Params represents the name and value of path parameters.
|
||||
type Params []Param
|
||||
|
||||
// Get gets the first value associated with the given name.
|
||||
// If there are no values associated with the key, Get returns "".
|
||||
func (ps Params) Get(name string) string {
|
||||
for _, p := range ps {
|
||||
if p.Name == name {
|
||||
return p.Value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type doubleArray struct {
|
||||
bc []baseCheck
|
||||
node []*node
|
||||
}
|
||||
|
||||
func newDoubleArray() *doubleArray {
|
||||
return &doubleArray{
|
||||
bc: []baseCheck{0},
|
||||
node: []*node{nil}, // A start index is adjusting to 1 because 0 will be used as a mark of non-existent node.
|
||||
}
|
||||
}
|
||||
|
||||
// baseCheck contains BASE, CHECK and Extra flags.
|
||||
// From the top, 22bits of BASE, 2bits of Extra flags and 8bits of CHECK.
|
||||
//
|
||||
// BASE (22bit) | Extra flags (2bit) | CHECK (8bit)
|
||||
// |----------------------|--|--------|
|
||||
// 32 10 8 0
|
||||
type baseCheck uint32
|
||||
|
||||
func (bc baseCheck) Base() int {
|
||||
return int(bc >> 10)
|
||||
}
|
||||
|
||||
func (bc *baseCheck) SetBase(base int) {
|
||||
*bc |= baseCheck(base) << 10
|
||||
}
|
||||
|
||||
func (bc baseCheck) Check() byte {
|
||||
return byte(bc)
|
||||
}
|
||||
|
||||
func (bc *baseCheck) SetCheck(check byte) {
|
||||
*bc |= baseCheck(check)
|
||||
}
|
||||
|
||||
func (bc baseCheck) IsEmpty() bool {
|
||||
return bc&0xfffffcff == 0
|
||||
}
|
||||
|
||||
func (bc baseCheck) IsSingleParam() bool {
|
||||
return bc¶mTypeSingle == paramTypeSingle
|
||||
}
|
||||
|
||||
func (bc baseCheck) IsWildcardParam() bool {
|
||||
return bc¶mTypeWildcard == paramTypeWildcard
|
||||
}
|
||||
|
||||
func (bc baseCheck) IsAnyParam() bool {
|
||||
return bc¶mTypeAny != 0
|
||||
}
|
||||
|
||||
func (bc *baseCheck) SetSingleParam() {
|
||||
*bc |= (1 << 8)
|
||||
}
|
||||
|
||||
func (bc *baseCheck) SetWildcardParam() {
|
||||
*bc |= (1 << 9)
|
||||
}
|
||||
|
||||
const (
|
||||
paramTypeSingle = 0x0100
|
||||
paramTypeWildcard = 0x0200
|
||||
paramTypeAny = 0x0300
|
||||
)
|
||||
|
||||
func (da *doubleArray) lookup(path string, params []Param, idx int) (*node, []Param, bool) {
|
||||
indices := make([]uint64, 0, 1)
|
||||
for i := 0; i < len(path); i++ {
|
||||
if da.bc[idx].IsAnyParam() {
|
||||
indices = append(indices, (uint64(i)<<32)|(uint64(idx)&0xffffffff))
|
||||
}
|
||||
c := path[i]
|
||||
if idx = nextIndex(da.bc[idx].Base(), c); idx >= len(da.bc) || da.bc[idx].Check() != c {
|
||||
goto BACKTRACKING
|
||||
}
|
||||
}
|
||||
if next := nextIndex(da.bc[idx].Base(), TerminationCharacter); next < len(da.bc) && da.bc[next].Check() == TerminationCharacter {
|
||||
return da.node[da.bc[next].Base()], params, true
|
||||
}
|
||||
BACKTRACKING:
|
||||
for j := len(indices) - 1; j >= 0; j-- {
|
||||
i, idx := int(indices[j]>>32), int(indices[j]&0xffffffff)
|
||||
if da.bc[idx].IsSingleParam() {
|
||||
idx := nextIndex(da.bc[idx].Base(), ParamCharacter)
|
||||
if idx >= len(da.bc) {
|
||||
break
|
||||
}
|
||||
next := NextSeparator(path, i)
|
||||
params := append(params, Param{Value: path[i:next]})
|
||||
if nd, params, found := da.lookup(path[next:], params, idx); found {
|
||||
return nd, params, true
|
||||
}
|
||||
}
|
||||
if da.bc[idx].IsWildcardParam() {
|
||||
idx := nextIndex(da.bc[idx].Base(), WildcardCharacter)
|
||||
params := append(params, Param{Value: path[i:]})
|
||||
return da.node[da.bc[idx].Base()], params, true
|
||||
}
|
||||
}
|
||||
return nil, nil, false
|
||||
}
|
||||
|
||||
// build builds double-array from records.
|
||||
func (da *doubleArray) build(srcs []*record, idx, depth int, usedBase map[int]struct{}) error {
|
||||
sort.Stable(recordSlice(srcs))
|
||||
base, siblings, leaf, err := da.arrange(srcs, idx, depth, usedBase)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if leaf != nil {
|
||||
nd, err := makeNode(leaf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
da.bc[idx].SetBase(len(da.node))
|
||||
da.node = append(da.node, nd)
|
||||
}
|
||||
for _, sib := range siblings {
|
||||
da.setCheck(nextIndex(base, sib.c), sib.c)
|
||||
}
|
||||
for _, sib := range siblings {
|
||||
records := srcs[sib.start:sib.end]
|
||||
switch sib.c {
|
||||
case ParamCharacter:
|
||||
for _, r := range records {
|
||||
next := NextSeparator(r.Key, depth+1)
|
||||
name := r.Key[depth+1 : next]
|
||||
r.paramNames = append(r.paramNames, name)
|
||||
r.Key = r.Key[next:]
|
||||
}
|
||||
da.bc[idx].SetSingleParam()
|
||||
if err := da.build(records, nextIndex(base, sib.c), 0, usedBase); err != nil {
|
||||
return err
|
||||
}
|
||||
case WildcardCharacter:
|
||||
r := records[0]
|
||||
name := r.Key[depth+1 : len(r.Key)-1]
|
||||
r.paramNames = append(r.paramNames, name)
|
||||
r.Key = ""
|
||||
da.bc[idx].SetWildcardParam()
|
||||
if err := da.build(records, nextIndex(base, sib.c), 0, usedBase); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
if err := da.build(records, nextIndex(base, sib.c), depth+1, usedBase); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// setBase sets BASE.
|
||||
func (da *doubleArray) setBase(i, base int) {
|
||||
da.bc[i].SetBase(base)
|
||||
}
|
||||
|
||||
// setCheck sets CHECK.
|
||||
func (da *doubleArray) setCheck(i int, check byte) {
|
||||
da.bc[i].SetCheck(check)
|
||||
}
|
||||
|
||||
// findEmptyIndex returns an index of unused BASE/CHECK node.
|
||||
func (da *doubleArray) findEmptyIndex(start int) int {
|
||||
i := start
|
||||
for ; i < len(da.bc); i++ {
|
||||
if da.bc[i].IsEmpty() {
|
||||
break
|
||||
}
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
// findBase returns good BASE.
|
||||
func (da *doubleArray) findBase(siblings []sibling, start int, usedBase map[int]struct{}) (base int) {
|
||||
for idx, firstChar := start+1, siblings[0].c; ; idx = da.findEmptyIndex(idx + 1) {
|
||||
base = nextIndex(idx, firstChar)
|
||||
if _, used := usedBase[base]; used {
|
||||
continue
|
||||
}
|
||||
i := 0
|
||||
for ; i < len(siblings); i++ {
|
||||
next := nextIndex(base, siblings[i].c)
|
||||
if len(da.bc) <= next {
|
||||
da.bc = append(da.bc, make([]baseCheck, next-len(da.bc)+1)...)
|
||||
}
|
||||
if !da.bc[next].IsEmpty() {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i == len(siblings) {
|
||||
break
|
||||
}
|
||||
}
|
||||
usedBase[base] = struct{}{}
|
||||
return base
|
||||
}
|
||||
|
||||
func (da *doubleArray) arrange(records []*record, idx, depth int, usedBase map[int]struct{}) (base int, siblings []sibling, leaf *record, err error) {
|
||||
siblings, leaf, err = makeSiblings(records, depth)
|
||||
if err != nil {
|
||||
return -1, nil, nil, err
|
||||
}
|
||||
if len(siblings) < 1 {
|
||||
return -1, nil, leaf, nil
|
||||
}
|
||||
base = da.findBase(siblings, idx, usedBase)
|
||||
if base > MaxSize {
|
||||
return -1, nil, nil, fmt.Errorf("denco: too many elements of internal slice")
|
||||
}
|
||||
da.setBase(idx, base)
|
||||
return base, siblings, leaf, err
|
||||
}
|
||||
|
||||
// node represents a node of Double-Array.
|
||||
type node struct {
|
||||
data interface{}
|
||||
|
||||
// Names of path parameters.
|
||||
paramNames []string
|
||||
}
|
||||
|
||||
// makeNode returns a new node from record.
|
||||
func makeNode(r *record) (*node, error) {
|
||||
dups := make(map[string]bool)
|
||||
for _, name := range r.paramNames {
|
||||
if dups[name] {
|
||||
return nil, fmt.Errorf("denco: path parameter `%v' is duplicated in the key `%v'", name, r.Key)
|
||||
}
|
||||
dups[name] = true
|
||||
}
|
||||
return &node{data: r.Value, paramNames: r.paramNames}, nil
|
||||
}
|
||||
|
||||
// sibling represents an intermediate data of build for Double-Array.
|
||||
type sibling struct {
|
||||
// An index of start of duplicated characters.
|
||||
start int
|
||||
|
||||
// An index of end of duplicated characters.
|
||||
end int
|
||||
|
||||
// A character of sibling.
|
||||
c byte
|
||||
}
|
||||
|
||||
// nextIndex returns a next index of array of BASE/CHECK.
|
||||
func nextIndex(base int, c byte) int {
|
||||
return base ^ int(c)
|
||||
}
|
||||
|
||||
// makeSiblings returns slice of sibling.
|
||||
func makeSiblings(records []*record, depth int) (sib []sibling, leaf *record, err error) {
|
||||
var (
|
||||
pc byte
|
||||
n int
|
||||
)
|
||||
for i, r := range records {
|
||||
if len(r.Key) <= depth {
|
||||
leaf = r
|
||||
continue
|
||||
}
|
||||
c := r.Key[depth]
|
||||
switch {
|
||||
case pc < c:
|
||||
sib = append(sib, sibling{start: i, c: c})
|
||||
case pc == c:
|
||||
continue
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("denco: BUG: routing table hasn't been sorted")
|
||||
}
|
||||
if n > 0 {
|
||||
sib[n-1].end = i
|
||||
}
|
||||
pc = c
|
||||
n++
|
||||
}
|
||||
if n == 0 {
|
||||
return nil, leaf, nil
|
||||
}
|
||||
sib[n-1].end = len(records)
|
||||
return sib, leaf, nil
|
||||
}
|
||||
|
||||
// Record represents a record data for router construction.
|
||||
type Record struct {
|
||||
// Key for router construction.
|
||||
Key string
|
||||
|
||||
// Result value for Key.
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
// NewRecord returns a new Record.
|
||||
func NewRecord(key string, value interface{}) Record {
|
||||
return Record{
|
||||
Key: key,
|
||||
Value: value,
|
||||
}
|
||||
}
|
||||
|
||||
// record represents a record that use to build the Double-Array.
|
||||
type record struct {
|
||||
Record
|
||||
paramNames []string
|
||||
}
|
||||
|
||||
// makeRecords returns the records that use to build Double-Arrays.
|
||||
func makeRecords(srcs []Record) (statics, params []*record) {
|
||||
spChars := string([]byte{ParamCharacter, WildcardCharacter})
|
||||
termChar := string(TerminationCharacter)
|
||||
for _, r := range srcs {
|
||||
if strings.ContainsAny(r.Key, spChars) {
|
||||
r.Key += termChar
|
||||
params = append(params, &record{Record: r})
|
||||
} else {
|
||||
statics = append(statics, &record{Record: r})
|
||||
}
|
||||
}
|
||||
return statics, params
|
||||
}
|
||||
|
||||
// recordSlice represents a slice of Record for sort and implements the sort.Interface.
|
||||
type recordSlice []*record
|
||||
|
||||
// Len implements the sort.Interface.Len.
|
||||
func (rs recordSlice) Len() int {
|
||||
return len(rs)
|
||||
}
|
||||
|
||||
// Less implements the sort.Interface.Less.
|
||||
func (rs recordSlice) Less(i, j int) bool {
|
||||
return rs[i].Key < rs[j].Key
|
||||
}
|
||||
|
||||
// Swap implements the sort.Interface.Swap.
|
||||
func (rs recordSlice) Swap(i, j int) {
|
||||
rs[i], rs[j] = rs[j], rs[i]
|
||||
}
|
||||
178
vendor/github.com/go-openapi/runtime/middleware/denco/router_bench_test.go
generated
vendored
178
vendor/github.com/go-openapi/runtime/middleware/denco/router_bench_test.go
generated
vendored
@@ -1,178 +0,0 @@
|
||||
package denco_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware/denco"
|
||||
)
|
||||
|
||||
func BenchmarkRouterLookupStatic100(b *testing.B) {
|
||||
benchmarkRouterLookupStatic(b, 100)
|
||||
}
|
||||
|
||||
func BenchmarkRouterLookupStatic300(b *testing.B) {
|
||||
benchmarkRouterLookupStatic(b, 300)
|
||||
}
|
||||
|
||||
func BenchmarkRouterLookupStatic700(b *testing.B) {
|
||||
benchmarkRouterLookupStatic(b, 700)
|
||||
}
|
||||
|
||||
func BenchmarkRouterLookupSingleParam100(b *testing.B) {
|
||||
records := makeTestSingleParamRecords(100)
|
||||
benchmarkRouterLookupSingleParam(b, records)
|
||||
}
|
||||
|
||||
func BenchmarkRouterLookupSingleParam300(b *testing.B) {
|
||||
records := makeTestSingleParamRecords(300)
|
||||
benchmarkRouterLookupSingleParam(b, records)
|
||||
}
|
||||
|
||||
func BenchmarkRouterLookupSingleParam700(b *testing.B) {
|
||||
records := makeTestSingleParamRecords(700)
|
||||
benchmarkRouterLookupSingleParam(b, records)
|
||||
}
|
||||
|
||||
func BenchmarkRouterLookupSingle2Param100(b *testing.B) {
|
||||
records := makeTestSingle2ParamRecords(100)
|
||||
benchmarkRouterLookupSingleParam(b, records)
|
||||
}
|
||||
|
||||
func BenchmarkRouterLookupSingle2Param300(b *testing.B) {
|
||||
records := makeTestSingle2ParamRecords(300)
|
||||
benchmarkRouterLookupSingleParam(b, records)
|
||||
}
|
||||
|
||||
func BenchmarkRouterLookupSingle2Param700(b *testing.B) {
|
||||
records := makeTestSingle2ParamRecords(700)
|
||||
benchmarkRouterLookupSingleParam(b, records)
|
||||
}
|
||||
|
||||
func BenchmarkRouterBuildStatic100(b *testing.B) {
|
||||
records := makeTestStaticRecords(100)
|
||||
benchmarkRouterBuild(b, records)
|
||||
}
|
||||
|
||||
func BenchmarkRouterBuildStatic300(b *testing.B) {
|
||||
records := makeTestStaticRecords(300)
|
||||
benchmarkRouterBuild(b, records)
|
||||
}
|
||||
|
||||
func BenchmarkRouterBuildStatic700(b *testing.B) {
|
||||
records := makeTestStaticRecords(700)
|
||||
benchmarkRouterBuild(b, records)
|
||||
}
|
||||
|
||||
func BenchmarkRouterBuildSingleParam100(b *testing.B) {
|
||||
records := makeTestSingleParamRecords(100)
|
||||
benchmarkRouterBuild(b, records)
|
||||
}
|
||||
|
||||
func BenchmarkRouterBuildSingleParam300(b *testing.B) {
|
||||
records := makeTestSingleParamRecords(300)
|
||||
benchmarkRouterBuild(b, records)
|
||||
}
|
||||
|
||||
func BenchmarkRouterBuildSingleParam700(b *testing.B) {
|
||||
records := makeTestSingleParamRecords(700)
|
||||
benchmarkRouterBuild(b, records)
|
||||
}
|
||||
|
||||
func BenchmarkRouterBuildSingle2Param100(b *testing.B) {
|
||||
records := makeTestSingle2ParamRecords(100)
|
||||
benchmarkRouterBuild(b, records)
|
||||
}
|
||||
|
||||
func BenchmarkRouterBuildSingle2Param300(b *testing.B) {
|
||||
records := makeTestSingle2ParamRecords(300)
|
||||
benchmarkRouterBuild(b, records)
|
||||
}
|
||||
|
||||
func BenchmarkRouterBuildSingle2Param700(b *testing.B) {
|
||||
records := makeTestSingle2ParamRecords(700)
|
||||
benchmarkRouterBuild(b, records)
|
||||
}
|
||||
|
||||
func benchmarkRouterLookupStatic(b *testing.B, n int) {
|
||||
b.StopTimer()
|
||||
router := denco.New()
|
||||
records := makeTestStaticRecords(n)
|
||||
if err := router.Build(records); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
record := pickTestRecord(records)
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if r, _, _ := router.Lookup(record.Key); r != record.Value {
|
||||
b.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func benchmarkRouterLookupSingleParam(b *testing.B, records []denco.Record) {
|
||||
router := denco.New()
|
||||
if err := router.Build(records); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
record := pickTestRecord(records)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, _, found := router.Lookup(record.Key); !found {
|
||||
b.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func benchmarkRouterBuild(b *testing.B, records []denco.Record) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
router := denco.New()
|
||||
if err := router.Build(records); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func makeTestStaticRecords(n int) []denco.Record {
|
||||
records := make([]denco.Record, n)
|
||||
for i := 0; i < n; i++ {
|
||||
records[i] = denco.NewRecord("/"+randomString(50), fmt.Sprintf("testroute%d", i))
|
||||
}
|
||||
return records
|
||||
}
|
||||
|
||||
func makeTestSingleParamRecords(n int) []denco.Record {
|
||||
records := make([]denco.Record, n)
|
||||
for i := 0; i < len(records); i++ {
|
||||
records[i] = denco.NewRecord(fmt.Sprintf("/user%d/:name", i), fmt.Sprintf("testroute%d", i))
|
||||
}
|
||||
return records
|
||||
}
|
||||
|
||||
func makeTestSingle2ParamRecords(n int) []denco.Record {
|
||||
records := make([]denco.Record, n)
|
||||
for i := 0; i < len(records); i++ {
|
||||
records[i] = denco.NewRecord(fmt.Sprintf("/user%d/:name/comment/:id", i), fmt.Sprintf("testroute%d", i))
|
||||
}
|
||||
return records
|
||||
}
|
||||
|
||||
func pickTestRecord(records []denco.Record) denco.Record {
|
||||
return records[len(records)/2]
|
||||
}
|
||||
|
||||
func randomString(n int) string {
|
||||
const srcStrings = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/"
|
||||
var buf bytes.Buffer
|
||||
for i := 0; i < n; i++ {
|
||||
num, err := rand.Int(rand.Reader, big.NewInt(int64(len(srcStrings)-1)))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
buf.WriteByte(srcStrings[num.Int64()])
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
524
vendor/github.com/go-openapi/runtime/middleware/denco/router_test.go
generated
vendored
524
vendor/github.com/go-openapi/runtime/middleware/denco/router_test.go
generated
vendored
@@ -1,524 +0,0 @@
|
||||
package denco_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware/denco"
|
||||
)
|
||||
|
||||
func routes() []denco.Record {
|
||||
return []denco.Record{
|
||||
{"/", "testroute0"},
|
||||
{"/path/to/route", "testroute1"},
|
||||
{"/path/to/other", "testroute2"},
|
||||
{"/path/to/route/a", "testroute3"},
|
||||
{"/path/to/:param", "testroute4"},
|
||||
{"/gists/:param1/foo/:param2", "testroute12"},
|
||||
{"/gists/:param1/foo/bar", "testroute11"},
|
||||
{"/:param1/:param2/foo/:param3", "testroute13"},
|
||||
{"/path/to/wildcard/*routepath", "testroute5"},
|
||||
{"/path/to/:param1/:param2", "testroute6"},
|
||||
{"/path/to/:param1/sep/:param2", "testroute7"},
|
||||
{"/:year/:month/:day", "testroute8"},
|
||||
{"/user/:id", "testroute9"},
|
||||
{"/a/to/b/:param/*routepath", "testroute10"},
|
||||
}
|
||||
}
|
||||
|
||||
var realURIs = []denco.Record{
|
||||
{"/authorizations", "/authorizations"},
|
||||
{"/authorizations/:id", "/authorizations/:id"},
|
||||
{"/applications/:client_id/tokens/:access_token", "/applications/:client_id/tokens/:access_token"},
|
||||
{"/events", "/events"},
|
||||
{"/repos/:owner/:repo/events", "/repos/:owner/:repo/events"},
|
||||
{"/networks/:owner/:repo/events", "/networks/:owner/:repo/events"},
|
||||
{"/orgs/:org/events", "/orgs/:org/events"},
|
||||
{"/users/:user/received_events", "/users/:user/received_events"},
|
||||
{"/users/:user/received_events/public", "/users/:user/received_events/public"},
|
||||
{"/users/:user/events", "/users/:user/events"},
|
||||
{"/users/:user/events/public", "/users/:user/events/public"},
|
||||
{"/users/:user/events/orgs/:org", "/users/:user/events/orgs/:org"},
|
||||
{"/feeds", "/feeds"},
|
||||
{"/notifications", "/notifications"},
|
||||
{"/repos/:owner/:repo/notifications", "/repos/:owner/:repo/notifications"},
|
||||
{"/notifications/threads/:id", "/notifications/threads/:id"},
|
||||
{"/notifications/threads/:id/subscription", "/notifications/threads/:id/subscription"},
|
||||
{"/repos/:owner/:repo/stargazers", "/repos/:owner/:repo/stargazers"},
|
||||
{"/users/:user/starred", "/users/:user/starred"},
|
||||
{"/user/starred", "/user/starred"},
|
||||
{"/user/starred/:owner/:repo", "/user/starred/:owner/:repo"},
|
||||
{"/repos/:owner/:repo/subscribers", "/repos/:owner/:repo/subscribers"},
|
||||
{"/users/:user/subscriptions", "/users/:user/subscriptions"},
|
||||
{"/user/subscriptions", "/user/subscriptions"},
|
||||
{"/repos/:owner/:repo/subscription", "/repos/:owner/:repo/subscription"},
|
||||
{"/user/subscriptions/:owner/:repo", "/user/subscriptions/:owner/:repo"},
|
||||
{"/users/:user/gists", "/users/:user/gists"},
|
||||
{"/gists", "/gists"},
|
||||
{"/gists/:id", "/gists/:id"},
|
||||
{"/gists/:id/star", "/gists/:id/star"},
|
||||
{"/repos/:owner/:repo/git/blobs/:sha", "/repos/:owner/:repo/git/blobs/:sha"},
|
||||
{"/repos/:owner/:repo/git/commits/:sha", "/repos/:owner/:repo/git/commits/:sha"},
|
||||
{"/repos/:owner/:repo/git/refs", "/repos/:owner/:repo/git/refs"},
|
||||
{"/repos/:owner/:repo/git/tags/:sha", "/repos/:owner/:repo/git/tags/:sha"},
|
||||
{"/repos/:owner/:repo/git/trees/:sha", "/repos/:owner/:repo/git/trees/:sha"},
|
||||
{"/issues", "/issues"},
|
||||
{"/user/issues", "/user/issues"},
|
||||
{"/orgs/:org/issues", "/orgs/:org/issues"},
|
||||
{"/repos/:owner/:repo/issues", "/repos/:owner/:repo/issues"},
|
||||
{"/repos/:owner/:repo/issues/:number", "/repos/:owner/:repo/issues/:number"},
|
||||
{"/repos/:owner/:repo/assignees", "/repos/:owner/:repo/assignees"},
|
||||
{"/repos/:owner/:repo/assignees/:assignee", "/repos/:owner/:repo/assignees/:assignee"},
|
||||
{"/repos/:owner/:repo/issues/:number/comments", "/repos/:owner/:repo/issues/:number/comments"},
|
||||
{"/repos/:owner/:repo/issues/:number/events", "/repos/:owner/:repo/issues/:number/events"},
|
||||
{"/repos/:owner/:repo/labels", "/repos/:owner/:repo/labels"},
|
||||
{"/repos/:owner/:repo/labels/:name", "/repos/:owner/:repo/labels/:name"},
|
||||
{"/repos/:owner/:repo/issues/:number/labels", "/repos/:owner/:repo/issues/:number/labels"},
|
||||
{"/repos/:owner/:repo/milestones/:number/labels", "/repos/:owner/:repo/milestones/:number/labels"},
|
||||
{"/repos/:owner/:repo/milestones", "/repos/:owner/:repo/milestones"},
|
||||
{"/repos/:owner/:repo/milestones/:number", "/repos/:owner/:repo/milestones/:number"},
|
||||
{"/emojis", "/emojis"},
|
||||
{"/gitignore/templates", "/gitignore/templates"},
|
||||
{"/gitignore/templates/:name", "/gitignore/templates/:name"},
|
||||
{"/meta", "/meta"},
|
||||
{"/rate_limit", "/rate_limit"},
|
||||
{"/users/:user/orgs", "/users/:user/orgs"},
|
||||
{"/user/orgs", "/user/orgs"},
|
||||
{"/orgs/:org", "/orgs/:org"},
|
||||
{"/orgs/:org/members", "/orgs/:org/members"},
|
||||
{"/orgs/:org/members/:user", "/orgs/:org/members/:user"},
|
||||
{"/orgs/:org/public_members", "/orgs/:org/public_members"},
|
||||
{"/orgs/:org/public_members/:user", "/orgs/:org/public_members/:user"},
|
||||
{"/orgs/:org/teams", "/orgs/:org/teams"},
|
||||
{"/teams/:id", "/teams/:id"},
|
||||
{"/teams/:id/members", "/teams/:id/members"},
|
||||
{"/teams/:id/members/:user", "/teams/:id/members/:user"},
|
||||
{"/teams/:id/repos", "/teams/:id/repos"},
|
||||
{"/teams/:id/repos/:owner/:repo", "/teams/:id/repos/:owner/:repo"},
|
||||
{"/user/teams", "/user/teams"},
|
||||
{"/repos/:owner/:repo/pulls", "/repos/:owner/:repo/pulls"},
|
||||
{"/repos/:owner/:repo/pulls/:number", "/repos/:owner/:repo/pulls/:number"},
|
||||
{"/repos/:owner/:repo/pulls/:number/commits", "/repos/:owner/:repo/pulls/:number/commits"},
|
||||
{"/repos/:owner/:repo/pulls/:number/files", "/repos/:owner/:repo/pulls/:number/files"},
|
||||
{"/repos/:owner/:repo/pulls/:number/merge", "/repos/:owner/:repo/pulls/:number/merge"},
|
||||
{"/repos/:owner/:repo/pulls/:number/comments", "/repos/:owner/:repo/pulls/:number/comments"},
|
||||
{"/user/repos", "/user/repos"},
|
||||
{"/users/:user/repos", "/users/:user/repos"},
|
||||
{"/orgs/:org/repos", "/orgs/:org/repos"},
|
||||
{"/repositories", "/repositories"},
|
||||
{"/repos/:owner/:repo", "/repos/:owner/:repo"},
|
||||
{"/repos/:owner/:repo/contributors", "/repos/:owner/:repo/contributors"},
|
||||
{"/repos/:owner/:repo/languages", "/repos/:owner/:repo/languages"},
|
||||
{"/repos/:owner/:repo/teams", "/repos/:owner/:repo/teams"},
|
||||
{"/repos/:owner/:repo/tags", "/repos/:owner/:repo/tags"},
|
||||
{"/repos/:owner/:repo/branches", "/repos/:owner/:repo/branches"},
|
||||
{"/repos/:owner/:repo/branches/:branch", "/repos/:owner/:repo/branches/:branch"},
|
||||
{"/repos/:owner/:repo/collaborators", "/repos/:owner/:repo/collaborators"},
|
||||
{"/repos/:owner/:repo/collaborators/:user", "/repos/:owner/:repo/collaborators/:user"},
|
||||
{"/repos/:owner/:repo/comments", "/repos/:owner/:repo/comments"},
|
||||
{"/repos/:owner/:repo/commits/:sha/comments", "/repos/:owner/:repo/commits/:sha/comments"},
|
||||
{"/repos/:owner/:repo/comments/:id", "/repos/:owner/:repo/comments/:id"},
|
||||
{"/repos/:owner/:repo/commits", "/repos/:owner/:repo/commits"},
|
||||
{"/repos/:owner/:repo/commits/:sha", "/repos/:owner/:repo/commits/:sha"},
|
||||
{"/repos/:owner/:repo/readme", "/repos/:owner/:repo/readme"},
|
||||
{"/repos/:owner/:repo/keys", "/repos/:owner/:repo/keys"},
|
||||
{"/repos/:owner/:repo/keys/:id", "/repos/:owner/:repo/keys/:id"},
|
||||
{"/repos/:owner/:repo/downloads", "/repos/:owner/:repo/downloads"},
|
||||
{"/repos/:owner/:repo/downloads/:id", "/repos/:owner/:repo/downloads/:id"},
|
||||
{"/repos/:owner/:repo/forks", "/repos/:owner/:repo/forks"},
|
||||
{"/repos/:owner/:repo/hooks", "/repos/:owner/:repo/hooks"},
|
||||
{"/repos/:owner/:repo/hooks/:id", "/repos/:owner/:repo/hooks/:id"},
|
||||
{"/repos/:owner/:repo/releases", "/repos/:owner/:repo/releases"},
|
||||
{"/repos/:owner/:repo/releases/:id", "/repos/:owner/:repo/releases/:id"},
|
||||
{"/repos/:owner/:repo/releases/:id/assets", "/repos/:owner/:repo/releases/:id/assets"},
|
||||
{"/repos/:owner/:repo/stats/contributors", "/repos/:owner/:repo/stats/contributors"},
|
||||
{"/repos/:owner/:repo/stats/commit_activity", "/repos/:owner/:repo/stats/commit_activity"},
|
||||
{"/repos/:owner/:repo/stats/code_frequency", "/repos/:owner/:repo/stats/code_frequency"},
|
||||
{"/repos/:owner/:repo/stats/participation", "/repos/:owner/:repo/stats/participation"},
|
||||
{"/repos/:owner/:repo/stats/punch_card", "/repos/:owner/:repo/stats/punch_card"},
|
||||
{"/repos/:owner/:repo/statuses/:ref", "/repos/:owner/:repo/statuses/:ref"},
|
||||
{"/search/repositories", "/search/repositories"},
|
||||
{"/search/code", "/search/code"},
|
||||
{"/search/issues", "/search/issues"},
|
||||
{"/search/users", "/search/users"},
|
||||
{"/legacy/issues/search/:owner/:repository/:state/:keyword", "/legacy/issues/search/:owner/:repository/:state/:keyword"},
|
||||
{"/legacy/repos/search/:keyword", "/legacy/repos/search/:keyword"},
|
||||
{"/legacy/user/search/:keyword", "/legacy/user/search/:keyword"},
|
||||
{"/legacy/user/email/:email", "/legacy/user/email/:email"},
|
||||
{"/users/:user", "/users/:user"},
|
||||
{"/user", "/user"},
|
||||
{"/users", "/users"},
|
||||
{"/user/emails", "/user/emails"},
|
||||
{"/users/:user/followers", "/users/:user/followers"},
|
||||
{"/user/followers", "/user/followers"},
|
||||
{"/users/:user/following", "/users/:user/following"},
|
||||
{"/user/following", "/user/following"},
|
||||
{"/user/following/:user", "/user/following/:user"},
|
||||
{"/users/:user/following/:target_user", "/users/:user/following/:target_user"},
|
||||
{"/users/:user/keys", "/users/:user/keys"},
|
||||
{"/user/keys", "/user/keys"},
|
||||
{"/user/keys/:id", "/user/keys/:id"},
|
||||
{"/people/:userId", "/people/:userId"},
|
||||
{"/people", "/people"},
|
||||
{"/activities/:activityId/people/:collection", "/activities/:activityId/people/:collection"},
|
||||
{"/people/:userId/people/:collection", "/people/:userId/people/:collection"},
|
||||
{"/people/:userId/openIdConnect", "/people/:userId/openIdConnect"},
|
||||
{"/people/:userId/activities/:collection", "/people/:userId/activities/:collection"},
|
||||
{"/activities/:activityId", "/activities/:activityId"},
|
||||
{"/activities", "/activities"},
|
||||
{"/activities/:activityId/comments", "/activities/:activityId/comments"},
|
||||
{"/comments/:commentId", "/comments/:commentId"},
|
||||
{"/people/:userId/moments/:collection", "/people/:userId/moments/:collection"},
|
||||
}
|
||||
|
||||
type testcase struct {
|
||||
path string
|
||||
value interface{}
|
||||
params []denco.Param
|
||||
found bool
|
||||
}
|
||||
|
||||
func runLookupTest(t *testing.T, records []denco.Record, testcases []testcase) {
|
||||
r := denco.New()
|
||||
if err := r.Build(records); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
data, params, found := r.Lookup(testcase.path)
|
||||
if !reflect.DeepEqual(data, testcase.value) || !reflect.DeepEqual(params, denco.Params(testcase.params)) || !reflect.DeepEqual(found, testcase.found) {
|
||||
t.Errorf("Router.Lookup(%q) => (%#v, %#v, %#v), want (%#v, %#v, %#v)", testcase.path, data, params, found, testcase.value, denco.Params(testcase.params), testcase.found)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRouter_Lookup(t *testing.T) {
|
||||
testcases := []testcase{
|
||||
{"/", "testroute0", nil, true},
|
||||
{"/gists/1323/foo/bar", "testroute11", []denco.Param{{"param1", "1323"}}, true},
|
||||
{"/gists/1323/foo/133", "testroute12", []denco.Param{{"param1", "1323"}, {"param2", "133"}}, true},
|
||||
{"/234/1323/foo/133", "testroute13", []denco.Param{{"param1", "234"}, {"param2", "1323"}, {"param3", "133"}}, true},
|
||||
{"/path/to/route", "testroute1", nil, true},
|
||||
{"/path/to/other", "testroute2", nil, true},
|
||||
{"/path/to/route/a", "testroute3", nil, true},
|
||||
{"/path/to/hoge", "testroute4", []denco.Param{{"param", "hoge"}}, true},
|
||||
{"/path/to/wildcard/some/params", "testroute5", []denco.Param{{"routepath", "some/params"}}, true},
|
||||
{"/path/to/o1/o2", "testroute6", []denco.Param{{"param1", "o1"}, {"param2", "o2"}}, true},
|
||||
{"/path/to/p1/sep/p2", "testroute7", []denco.Param{{"param1", "p1"}, {"param2", "p2"}}, true},
|
||||
{"/2014/01/06", "testroute8", []denco.Param{{"year", "2014"}, {"month", "01"}, {"day", "06"}}, true},
|
||||
{"/user/777", "testroute9", []denco.Param{{"id", "777"}}, true},
|
||||
{"/a/to/b/p1/some/wildcard/params", "testroute10", []denco.Param{{"param", "p1"}, {"routepath", "some/wildcard/params"}}, true},
|
||||
{"/missing", nil, nil, false},
|
||||
}
|
||||
runLookupTest(t, routes(), testcases)
|
||||
|
||||
records := []denco.Record{
|
||||
{"/", "testroute0"},
|
||||
{"/:b", "testroute1"},
|
||||
{"/*wildcard", "testroute2"},
|
||||
}
|
||||
testcases = []testcase{
|
||||
{"/", "testroute0", nil, true},
|
||||
{"/true", "testroute1", []denco.Param{{"b", "true"}}, true},
|
||||
{"/foo/bar", "testroute2", []denco.Param{{"wildcard", "foo/bar"}}, true},
|
||||
}
|
||||
runLookupTest(t, records, testcases)
|
||||
|
||||
records = []denco.Record{
|
||||
{"/networks/:owner/:repo/events", "testroute0"},
|
||||
{"/orgs/:org/events", "testroute1"},
|
||||
{"/notifications/threads/:id", "testroute2"},
|
||||
}
|
||||
testcases = []testcase{
|
||||
{"/networks/:owner/:repo/events", "testroute0", []denco.Param{{"owner", ":owner"}, {"repo", ":repo"}}, true},
|
||||
{"/orgs/:org/events", "testroute1", []denco.Param{{"org", ":org"}}, true},
|
||||
{"/notifications/threads/:id", "testroute2", []denco.Param{{"id", ":id"}}, true},
|
||||
}
|
||||
runLookupTest(t, records, testcases)
|
||||
|
||||
runLookupTest(t, []denco.Record{
|
||||
{"/", "route2"},
|
||||
}, []testcase{
|
||||
{"/user/alice", nil, nil, false},
|
||||
})
|
||||
|
||||
runLookupTest(t, []denco.Record{
|
||||
{"/user/:name", "route1"},
|
||||
}, []testcase{
|
||||
{"/", nil, nil, false},
|
||||
})
|
||||
|
||||
runLookupTest(t, []denco.Record{
|
||||
{"/*wildcard", "testroute0"},
|
||||
{"/a/:b", "testroute1"},
|
||||
}, []testcase{
|
||||
{"/a", "testroute0", []denco.Param{{"wildcard", "a"}}, true},
|
||||
})
|
||||
}
|
||||
|
||||
func TestRouter_Lookup_withManyRoutes(t *testing.T) {
|
||||
n := 1000
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
records := make([]denco.Record, n)
|
||||
for i := 0; i < n; i++ {
|
||||
records[i] = denco.Record{Key: "/" + randomString(rand.Intn(50)+10), Value: fmt.Sprintf("route%d", i)}
|
||||
}
|
||||
router := denco.New()
|
||||
if err := router.Build(records); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, r := range records {
|
||||
data, params, found := router.Lookup(r.Key)
|
||||
if !reflect.DeepEqual(data, r.Value) || len(params) != 0 || !reflect.DeepEqual(found, true) {
|
||||
t.Errorf("Router.Lookup(%q) => (%#v, %#v, %#v), want (%#v, %#v, %#v)", r.Key, data, len(params), found, r.Value, 0, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRouter_Lookup_realURIs(t *testing.T) {
|
||||
testcases := []testcase{
|
||||
{"/authorizations", "/authorizations", nil, true},
|
||||
{"/authorizations/1", "/authorizations/:id", []denco.Param{{"id", "1"}}, true},
|
||||
{"/applications/1/tokens/zohRoo7e", "/applications/:client_id/tokens/:access_token", []denco.Param{{"client_id", "1"}, {"access_token", "zohRoo7e"}}, true},
|
||||
{"/events", "/events", nil, true},
|
||||
{"/repos/naoina/denco/events", "/repos/:owner/:repo/events", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/networks/naoina/denco/events", "/networks/:owner/:repo/events", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/orgs/something/events", "/orgs/:org/events", []denco.Param{{"org", "something"}}, true},
|
||||
{"/users/naoina/received_events", "/users/:user/received_events", []denco.Param{{"user", "naoina"}}, true},
|
||||
{"/users/naoina/received_events/public", "/users/:user/received_events/public", []denco.Param{{"user", "naoina"}}, true},
|
||||
{"/users/naoina/events", "/users/:user/events", []denco.Param{{"user", "naoina"}}, true},
|
||||
{"/users/naoina/events/public", "/users/:user/events/public", []denco.Param{{"user", "naoina"}}, true},
|
||||
{"/users/naoina/events/orgs/something", "/users/:user/events/orgs/:org", []denco.Param{{"user", "naoina"}, {"org", "something"}}, true},
|
||||
{"/feeds", "/feeds", nil, true},
|
||||
{"/notifications", "/notifications", nil, true},
|
||||
{"/repos/naoina/denco/notifications", "/repos/:owner/:repo/notifications", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/notifications/threads/1", "/notifications/threads/:id", []denco.Param{{"id", "1"}}, true},
|
||||
{"/notifications/threads/2/subscription", "/notifications/threads/:id/subscription", []denco.Param{{"id", "2"}}, true},
|
||||
{"/repos/naoina/denco/stargazers", "/repos/:owner/:repo/stargazers", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/users/naoina/starred", "/users/:user/starred", []denco.Param{{"user", "naoina"}}, true},
|
||||
{"/user/starred", "/user/starred", nil, true},
|
||||
{"/user/starred/naoina/denco", "/user/starred/:owner/:repo", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/subscribers", "/repos/:owner/:repo/subscribers", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/users/naoina/subscriptions", "/users/:user/subscriptions", []denco.Param{{"user", "naoina"}}, true},
|
||||
{"/user/subscriptions", "/user/subscriptions", nil, true},
|
||||
{"/repos/naoina/denco/subscription", "/repos/:owner/:repo/subscription", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/user/subscriptions/naoina/denco", "/user/subscriptions/:owner/:repo", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/users/naoina/gists", "/users/:user/gists", []denco.Param{{"user", "naoina"}}, true},
|
||||
{"/gists", "/gists", nil, true},
|
||||
{"/gists/1", "/gists/:id", []denco.Param{{"id", "1"}}, true},
|
||||
{"/gists/2/star", "/gists/:id/star", []denco.Param{{"id", "2"}}, true},
|
||||
{"/repos/naoina/denco/git/blobs/03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9", "/repos/:owner/:repo/git/blobs/:sha", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"sha", "03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9"}}, true},
|
||||
{"/repos/naoina/denco/git/commits/03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9", "/repos/:owner/:repo/git/commits/:sha", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"sha", "03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9"}}, true},
|
||||
{"/repos/naoina/denco/git/refs", "/repos/:owner/:repo/git/refs", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/git/tags/03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9", "/repos/:owner/:repo/git/tags/:sha", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"sha", "03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9"}}, true},
|
||||
{"/repos/naoina/denco/git/trees/03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9", "/repos/:owner/:repo/git/trees/:sha", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"sha", "03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9"}}, true},
|
||||
{"/issues", "/issues", nil, true},
|
||||
{"/user/issues", "/user/issues", nil, true},
|
||||
{"/orgs/something/issues", "/orgs/:org/issues", []denco.Param{{"org", "something"}}, true},
|
||||
{"/repos/naoina/denco/issues", "/repos/:owner/:repo/issues", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/issues/1", "/repos/:owner/:repo/issues/:number", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true},
|
||||
{"/repos/naoina/denco/assignees", "/repos/:owner/:repo/assignees", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/assignees/foo", "/repos/:owner/:repo/assignees/:assignee", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"assignee", "foo"}}, true},
|
||||
{"/repos/naoina/denco/issues/1/comments", "/repos/:owner/:repo/issues/:number/comments", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true},
|
||||
{"/repos/naoina/denco/issues/1/events", "/repos/:owner/:repo/issues/:number/events", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true},
|
||||
{"/repos/naoina/denco/labels", "/repos/:owner/:repo/labels", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/labels/bug", "/repos/:owner/:repo/labels/:name", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"name", "bug"}}, true},
|
||||
{"/repos/naoina/denco/issues/1/labels", "/repos/:owner/:repo/issues/:number/labels", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true},
|
||||
{"/repos/naoina/denco/milestones/1/labels", "/repos/:owner/:repo/milestones/:number/labels", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true},
|
||||
{"/repos/naoina/denco/milestones", "/repos/:owner/:repo/milestones", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/milestones/1", "/repos/:owner/:repo/milestones/:number", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true},
|
||||
{"/emojis", "/emojis", nil, true},
|
||||
{"/gitignore/templates", "/gitignore/templates", nil, true},
|
||||
{"/gitignore/templates/Go", "/gitignore/templates/:name", []denco.Param{{"name", "Go"}}, true},
|
||||
{"/meta", "/meta", nil, true},
|
||||
{"/rate_limit", "/rate_limit", nil, true},
|
||||
{"/users/naoina/orgs", "/users/:user/orgs", []denco.Param{{"user", "naoina"}}, true},
|
||||
{"/user/orgs", "/user/orgs", nil, true},
|
||||
{"/orgs/something", "/orgs/:org", []denco.Param{{"org", "something"}}, true},
|
||||
{"/orgs/something/members", "/orgs/:org/members", []denco.Param{{"org", "something"}}, true},
|
||||
{"/orgs/something/members/naoina", "/orgs/:org/members/:user", []denco.Param{{"org", "something"}, {"user", "naoina"}}, true},
|
||||
{"/orgs/something/public_members", "/orgs/:org/public_members", []denco.Param{{"org", "something"}}, true},
|
||||
{"/orgs/something/public_members/naoina", "/orgs/:org/public_members/:user", []denco.Param{{"org", "something"}, {"user", "naoina"}}, true},
|
||||
{"/orgs/something/teams", "/orgs/:org/teams", []denco.Param{{"org", "something"}}, true},
|
||||
{"/teams/1", "/teams/:id", []denco.Param{{"id", "1"}}, true},
|
||||
{"/teams/2/members", "/teams/:id/members", []denco.Param{{"id", "2"}}, true},
|
||||
{"/teams/3/members/naoina", "/teams/:id/members/:user", []denco.Param{{"id", "3"}, {"user", "naoina"}}, true},
|
||||
{"/teams/4/repos", "/teams/:id/repos", []denco.Param{{"id", "4"}}, true},
|
||||
{"/teams/5/repos/naoina/denco", "/teams/:id/repos/:owner/:repo", []denco.Param{{"id", "5"}, {"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/user/teams", "/user/teams", nil, true},
|
||||
{"/repos/naoina/denco/pulls", "/repos/:owner/:repo/pulls", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/pulls/1", "/repos/:owner/:repo/pulls/:number", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true},
|
||||
{"/repos/naoina/denco/pulls/1/commits", "/repos/:owner/:repo/pulls/:number/commits", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true},
|
||||
{"/repos/naoina/denco/pulls/1/files", "/repos/:owner/:repo/pulls/:number/files", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true},
|
||||
{"/repos/naoina/denco/pulls/1/merge", "/repos/:owner/:repo/pulls/:number/merge", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true},
|
||||
{"/repos/naoina/denco/pulls/1/comments", "/repos/:owner/:repo/pulls/:number/comments", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true},
|
||||
{"/user/repos", "/user/repos", nil, true},
|
||||
{"/users/naoina/repos", "/users/:user/repos", []denco.Param{{"user", "naoina"}}, true},
|
||||
{"/orgs/something/repos", "/orgs/:org/repos", []denco.Param{{"org", "something"}}, true},
|
||||
{"/repositories", "/repositories", nil, true},
|
||||
{"/repos/naoina/denco", "/repos/:owner/:repo", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/contributors", "/repos/:owner/:repo/contributors", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/languages", "/repos/:owner/:repo/languages", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/teams", "/repos/:owner/:repo/teams", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/tags", "/repos/:owner/:repo/tags", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/branches", "/repos/:owner/:repo/branches", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/branches/master", "/repos/:owner/:repo/branches/:branch", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"branch", "master"}}, true},
|
||||
{"/repos/naoina/denco/collaborators", "/repos/:owner/:repo/collaborators", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/collaborators/something", "/repos/:owner/:repo/collaborators/:user", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"user", "something"}}, true},
|
||||
{"/repos/naoina/denco/comments", "/repos/:owner/:repo/comments", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/commits/03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9/comments", "/repos/:owner/:repo/commits/:sha/comments", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"sha", "03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9"}}, true},
|
||||
{"/repos/naoina/denco/comments/1", "/repos/:owner/:repo/comments/:id", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"id", "1"}}, true},
|
||||
{"/repos/naoina/denco/commits", "/repos/:owner/:repo/commits", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/commits/03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9", "/repos/:owner/:repo/commits/:sha", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"sha", "03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9"}}, true},
|
||||
{"/repos/naoina/denco/readme", "/repos/:owner/:repo/readme", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/keys", "/repos/:owner/:repo/keys", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/keys/1", "/repos/:owner/:repo/keys/:id", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"id", "1"}}, true},
|
||||
{"/repos/naoina/denco/downloads", "/repos/:owner/:repo/downloads", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/downloads/2", "/repos/:owner/:repo/downloads/:id", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"id", "2"}}, true},
|
||||
{"/repos/naoina/denco/forks", "/repos/:owner/:repo/forks", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/hooks", "/repos/:owner/:repo/hooks", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/hooks/2", "/repos/:owner/:repo/hooks/:id", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"id", "2"}}, true},
|
||||
{"/repos/naoina/denco/releases", "/repos/:owner/:repo/releases", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/releases/1", "/repos/:owner/:repo/releases/:id", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"id", "1"}}, true},
|
||||
{"/repos/naoina/denco/releases/1/assets", "/repos/:owner/:repo/releases/:id/assets", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"id", "1"}}, true},
|
||||
{"/repos/naoina/denco/stats/contributors", "/repos/:owner/:repo/stats/contributors", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/stats/commit_activity", "/repos/:owner/:repo/stats/commit_activity", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/stats/code_frequency", "/repos/:owner/:repo/stats/code_frequency", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/stats/participation", "/repos/:owner/:repo/stats/participation", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/stats/punch_card", "/repos/:owner/:repo/stats/punch_card", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true},
|
||||
{"/repos/naoina/denco/statuses/master", "/repos/:owner/:repo/statuses/:ref", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"ref", "master"}}, true},
|
||||
{"/search/repositories", "/search/repositories", nil, true},
|
||||
{"/search/code", "/search/code", nil, true},
|
||||
{"/search/issues", "/search/issues", nil, true},
|
||||
{"/search/users", "/search/users", nil, true},
|
||||
{"/legacy/issues/search/naoina/denco/closed/test", "/legacy/issues/search/:owner/:repository/:state/:keyword", []denco.Param{{"owner", "naoina"}, {"repository", "denco"}, {"state", "closed"}, {"keyword", "test"}}, true},
|
||||
{"/legacy/repos/search/test", "/legacy/repos/search/:keyword", []denco.Param{{"keyword", "test"}}, true},
|
||||
{"/legacy/user/search/test", "/legacy/user/search/:keyword", []denco.Param{{"keyword", "test"}}, true},
|
||||
{"/legacy/user/email/naoina@kuune.org", "/legacy/user/email/:email", []denco.Param{{"email", "naoina@kuune.org"}}, true},
|
||||
{"/users/naoina", "/users/:user", []denco.Param{{"user", "naoina"}}, true},
|
||||
{"/user", "/user", nil, true},
|
||||
{"/users", "/users", nil, true},
|
||||
{"/user/emails", "/user/emails", nil, true},
|
||||
{"/users/naoina/followers", "/users/:user/followers", []denco.Param{{"user", "naoina"}}, true},
|
||||
{"/user/followers", "/user/followers", nil, true},
|
||||
{"/users/naoina/following", "/users/:user/following", []denco.Param{{"user", "naoina"}}, true},
|
||||
{"/user/following", "/user/following", nil, true},
|
||||
{"/user/following/naoina", "/user/following/:user", []denco.Param{{"user", "naoina"}}, true},
|
||||
{"/users/naoina/following/target", "/users/:user/following/:target_user", []denco.Param{{"user", "naoina"}, {"target_user", "target"}}, true},
|
||||
{"/users/naoina/keys", "/users/:user/keys", []denco.Param{{"user", "naoina"}}, true},
|
||||
{"/user/keys", "/user/keys", nil, true},
|
||||
{"/user/keys/1", "/user/keys/:id", []denco.Param{{"id", "1"}}, true},
|
||||
{"/people/me", "/people/:userId", []denco.Param{{"userId", "me"}}, true},
|
||||
{"/people", "/people", nil, true},
|
||||
{"/activities/foo/people/vault", "/activities/:activityId/people/:collection", []denco.Param{{"activityId", "foo"}, {"collection", "vault"}}, true},
|
||||
{"/people/me/people/vault", "/people/:userId/people/:collection", []denco.Param{{"userId", "me"}, {"collection", "vault"}}, true},
|
||||
{"/people/me/openIdConnect", "/people/:userId/openIdConnect", []denco.Param{{"userId", "me"}}, true},
|
||||
{"/people/me/activities/vault", "/people/:userId/activities/:collection", []denco.Param{{"userId", "me"}, {"collection", "vault"}}, true},
|
||||
{"/activities/foo", "/activities/:activityId", []denco.Param{{"activityId", "foo"}}, true},
|
||||
{"/activities", "/activities", nil, true},
|
||||
{"/activities/foo/comments", "/activities/:activityId/comments", []denco.Param{{"activityId", "foo"}}, true},
|
||||
{"/comments/hoge", "/comments/:commentId", []denco.Param{{"commentId", "hoge"}}, true},
|
||||
{"/people/me/moments/vault", "/people/:userId/moments/:collection", []denco.Param{{"userId", "me"}, {"collection", "vault"}}, true},
|
||||
}
|
||||
runLookupTest(t, realURIs, testcases)
|
||||
}
|
||||
|
||||
func TestRouter_Build(t *testing.T) {
|
||||
// test for duplicate name of path parameters.
|
||||
func() {
|
||||
r := denco.New()
|
||||
if err := r.Build([]denco.Record{
|
||||
{"/:user/:id/:id", "testroute0"},
|
||||
{"/:user/:user/:id", "testroute0"},
|
||||
}); err == nil {
|
||||
t.Errorf("no error returned by duplicate name of path parameters")
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func TestRouter_Build_withoutSizeHint(t *testing.T) {
|
||||
for _, v := range []struct {
|
||||
keys []string
|
||||
sizeHint int
|
||||
}{
|
||||
{[]string{"/user"}, 0},
|
||||
{[]string{"/user/:id"}, 1},
|
||||
{[]string{"/user/:id/post"}, 1},
|
||||
{[]string{"/user/:id/:group"}, 2},
|
||||
{[]string{"/user/:id/post/:cid"}, 2},
|
||||
{[]string{"/user/:id/post/:cid", "/admin/:id/post/:cid"}, 2},
|
||||
{[]string{"/user/:id", "/admin/:id/post/:cid"}, 2},
|
||||
{[]string{"/user/:id/post/:cid", "/admin/:id/post/:cid/:type"}, 3},
|
||||
} {
|
||||
r := denco.New()
|
||||
actual := r.SizeHint
|
||||
expect := -1
|
||||
if !reflect.DeepEqual(actual, expect) {
|
||||
t.Errorf(`before Build; Router.SizeHint => (%[1]T=%#[1]v); want (%[2]T=%#[2]v)`, actual, expect)
|
||||
}
|
||||
records := make([]denco.Record, len(v.keys))
|
||||
for i, k := range v.keys {
|
||||
records[i] = denco.Record{Key: k, Value: "value"}
|
||||
}
|
||||
if err := r.Build(records); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
actual = r.SizeHint
|
||||
expect = v.sizeHint
|
||||
if !reflect.DeepEqual(actual, expect) {
|
||||
t.Errorf(`Router.Build(%#v); Router.SizeHint => (%[2]T=%#[2]v); want (%[3]T=%#[3]v)`, records, actual, expect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRouter_Build_withSizeHint(t *testing.T) {
|
||||
for _, v := range []struct {
|
||||
key string
|
||||
sizeHint int
|
||||
expect int
|
||||
}{
|
||||
{"/user", 0, 0},
|
||||
{"/user", 1, 1},
|
||||
{"/user", 2, 2},
|
||||
{"/user/:id", 3, 3},
|
||||
{"/user/:id/:group", 0, 0},
|
||||
{"/user/:id/:group", 1, 1},
|
||||
} {
|
||||
r := denco.New()
|
||||
r.SizeHint = v.sizeHint
|
||||
records := []denco.Record{
|
||||
{v.key, "value"},
|
||||
}
|
||||
if err := r.Build(records); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
actual := r.SizeHint
|
||||
expect := v.expect
|
||||
if !reflect.DeepEqual(actual, expect) {
|
||||
t.Errorf(`Router.Build(%#v); Router.SizeHint => (%[2]T=%#[2]v); want (%[3]T=%#[3]v)`, records, actual, expect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParams_Get(t *testing.T) {
|
||||
params := denco.Params([]denco.Param{
|
||||
{"name1", "value1"},
|
||||
{"name2", "value2"},
|
||||
{"name3", "value3"},
|
||||
{"name1", "value4"},
|
||||
})
|
||||
for _, v := range []struct{ value, expected string }{
|
||||
{"name1", "value1"},
|
||||
{"name2", "value2"},
|
||||
{"name3", "value3"},
|
||||
{"name4", ""},
|
||||
} {
|
||||
actual := params.Get(v.value)
|
||||
expected := v.expected
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Errorf("Params.Get(%q) => %#v, want %#v", v.value, actual, expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
106
vendor/github.com/go-openapi/runtime/middleware/denco/server.go
generated
vendored
106
vendor/github.com/go-openapi/runtime/middleware/denco/server.go
generated
vendored
@@ -1,106 +0,0 @@
|
||||
package denco
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Mux represents a multiplexer for HTTP request.
|
||||
type Mux struct{}
|
||||
|
||||
// NewMux returns a new Mux.
|
||||
func NewMux() *Mux {
|
||||
return &Mux{}
|
||||
}
|
||||
|
||||
// GET is shorthand of Mux.Handler("GET", path, handler).
|
||||
func (m *Mux) GET(path string, handler HandlerFunc) Handler {
|
||||
return m.Handler("GET", path, handler)
|
||||
}
|
||||
|
||||
// POST is shorthand of Mux.Handler("POST", path, handler).
|
||||
func (m *Mux) POST(path string, handler HandlerFunc) Handler {
|
||||
return m.Handler("POST", path, handler)
|
||||
}
|
||||
|
||||
// PUT is shorthand of Mux.Handler("PUT", path, handler).
|
||||
func (m *Mux) PUT(path string, handler HandlerFunc) Handler {
|
||||
return m.Handler("PUT", path, handler)
|
||||
}
|
||||
|
||||
// HEAD is shorthand of Mux.Handler("HEAD", path, handler).
|
||||
func (m *Mux) HEAD(path string, handler HandlerFunc) Handler {
|
||||
return m.Handler("HEAD", path, handler)
|
||||
}
|
||||
|
||||
// Handler returns a handler for HTTP method.
|
||||
func (m *Mux) Handler(method, path string, handler HandlerFunc) Handler {
|
||||
return Handler{
|
||||
Method: method,
|
||||
Path: path,
|
||||
Func: handler,
|
||||
}
|
||||
}
|
||||
|
||||
// Build builds a http.Handler.
|
||||
func (m *Mux) Build(handlers []Handler) (http.Handler, error) {
|
||||
recordMap := make(map[string][]Record)
|
||||
for _, h := range handlers {
|
||||
recordMap[h.Method] = append(recordMap[h.Method], NewRecord(h.Path, h.Func))
|
||||
}
|
||||
mux := newServeMux()
|
||||
for m, records := range recordMap {
|
||||
router := New()
|
||||
if err := router.Build(records); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mux.routers[m] = router
|
||||
}
|
||||
return mux, nil
|
||||
}
|
||||
|
||||
// Handler represents a handler of HTTP request.
|
||||
type Handler struct {
|
||||
// Method is an HTTP method.
|
||||
Method string
|
||||
|
||||
// Path is a routing path for handler.
|
||||
Path string
|
||||
|
||||
// Func is a function of handler of HTTP request.
|
||||
Func HandlerFunc
|
||||
}
|
||||
|
||||
// The HandlerFunc type is aliased to type of handler function.
|
||||
type HandlerFunc func(w http.ResponseWriter, r *http.Request, params Params)
|
||||
|
||||
type serveMux struct {
|
||||
routers map[string]*Router
|
||||
}
|
||||
|
||||
func newServeMux() *serveMux {
|
||||
return &serveMux{
|
||||
routers: make(map[string]*Router),
|
||||
}
|
||||
}
|
||||
|
||||
// ServeHTTP implements http.Handler interface.
|
||||
func (mux *serveMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
handler, params := mux.handler(r.Method, r.URL.Path)
|
||||
handler(w, r, params)
|
||||
}
|
||||
|
||||
func (mux *serveMux) handler(method, path string) (HandlerFunc, []Param) {
|
||||
if router, found := mux.routers[method]; found {
|
||||
if handler, params, found := router.Lookup(path); found {
|
||||
return handler.(HandlerFunc), params
|
||||
}
|
||||
}
|
||||
return NotFound, nil
|
||||
}
|
||||
|
||||
// NotFound replies to the request with an HTTP 404 not found error.
|
||||
// NotFound is called when unknown HTTP method or a handler not found.
|
||||
// If you want to use the your own NotFound handler, please overwrite this variable.
|
||||
var NotFound = func(w http.ResponseWriter, r *http.Request, _ Params) {
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
106
vendor/github.com/go-openapi/runtime/middleware/denco/server_test.go
generated
vendored
106
vendor/github.com/go-openapi/runtime/middleware/denco/server_test.go
generated
vendored
@@ -1,106 +0,0 @@
|
||||
package denco_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware/denco"
|
||||
)
|
||||
|
||||
func testHandlerFunc(w http.ResponseWriter, r *http.Request, params denco.Params) {
|
||||
fmt.Fprintf(w, "method: %s, path: %s, params: %v", r.Method, r.URL.Path, params)
|
||||
}
|
||||
|
||||
func TestMux(t *testing.T) {
|
||||
mux := denco.NewMux()
|
||||
handler, err := mux.Build([]denco.Handler{
|
||||
mux.GET("/", testHandlerFunc),
|
||||
mux.GET("/user/:name", testHandlerFunc),
|
||||
mux.POST("/user/:name", testHandlerFunc),
|
||||
mux.HEAD("/user/:name", testHandlerFunc),
|
||||
mux.PUT("/user/:name", testHandlerFunc),
|
||||
mux.Handler("GET", "/user/handler", testHandlerFunc),
|
||||
mux.Handler("POST", "/user/handler", testHandlerFunc),
|
||||
{"PUT", "/user/inference", testHandlerFunc},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
for _, v := range []struct {
|
||||
status int
|
||||
method, path, expected string
|
||||
}{
|
||||
{200, "GET", "/", "method: GET, path: /, params: []"},
|
||||
{200, "GET", "/user/alice", "method: GET, path: /user/alice, params: [{name alice}]"},
|
||||
{200, "POST", "/user/bob", "method: POST, path: /user/bob, params: [{name bob}]"},
|
||||
{200, "HEAD", "/user/alice", ""},
|
||||
{200, "PUT", "/user/bob", "method: PUT, path: /user/bob, params: [{name bob}]"},
|
||||
{404, "POST", "/", "404 page not found\n"},
|
||||
{404, "GET", "/unknown", "404 page not found\n"},
|
||||
{404, "POST", "/user/alice/1", "404 page not found\n"},
|
||||
{200, "GET", "/user/handler", "method: GET, path: /user/handler, params: []"},
|
||||
{200, "POST", "/user/handler", "method: POST, path: /user/handler, params: []"},
|
||||
{200, "PUT", "/user/inference", "method: PUT, path: /user/inference, params: []"},
|
||||
} {
|
||||
req, err := http.NewRequest(v.method, server.URL+v.path, nil)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
continue
|
||||
}
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
continue
|
||||
}
|
||||
defer res.Body.Close()
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
continue
|
||||
}
|
||||
actual := string(body)
|
||||
expected := v.expected
|
||||
if res.StatusCode != v.status || actual != expected {
|
||||
t.Errorf(`%s "%s" => %#v %#v, want %#v %#v`, v.method, v.path, res.StatusCode, actual, v.status, expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotFound(t *testing.T) {
|
||||
mux := denco.NewMux()
|
||||
handler, err := mux.Build([]denco.Handler{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
origNotFound := denco.NotFound
|
||||
defer func() {
|
||||
denco.NotFound = origNotFound
|
||||
}()
|
||||
denco.NotFound = func(w http.ResponseWriter, r *http.Request, params denco.Params) {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
fmt.Fprintf(w, "method: %s, path: %s, params: %v", r.Method, r.URL.Path, params)
|
||||
}
|
||||
res, err := http.Get(server.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
actual := string(body)
|
||||
expected := "method: GET, path: /, params: []"
|
||||
if res.StatusCode != http.StatusServiceUnavailable || actual != expected {
|
||||
t.Errorf(`GET "/" => %#v %#v, want %#v %#v`, res.StatusCode, actual, http.StatusServiceUnavailable, expected)
|
||||
}
|
||||
}
|
||||
12
vendor/github.com/go-openapi/runtime/middleware/denco/util.go
generated
vendored
12
vendor/github.com/go-openapi/runtime/middleware/denco/util.go
generated
vendored
@@ -1,12 +0,0 @@
|
||||
package denco
|
||||
|
||||
// NextSeparator returns an index of next separator in path.
|
||||
func NextSeparator(path string, start int) int {
|
||||
for start < len(path) {
|
||||
if c := path[start]; c == '/' || c == TerminationCharacter {
|
||||
break
|
||||
}
|
||||
start++
|
||||
}
|
||||
return start
|
||||
}
|
||||
31
vendor/github.com/go-openapi/runtime/middleware/denco/util_test.go
generated
vendored
31
vendor/github.com/go-openapi/runtime/middleware/denco/util_test.go
generated
vendored
@@ -1,31 +0,0 @@
|
||||
package denco_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware/denco"
|
||||
)
|
||||
|
||||
func TestNextSeparator(t *testing.T) {
|
||||
for _, testcase := range []struct {
|
||||
path string
|
||||
start int
|
||||
expected interface{}
|
||||
}{
|
||||
{"/path/to/route", 0, 0},
|
||||
{"/path/to/route", 1, 5},
|
||||
{"/path/to/route", 9, 14},
|
||||
{"/path.html", 1, 10},
|
||||
{"/foo/bar.html", 1, 4},
|
||||
{"/foo/bar.html/baz.png", 5, 13},
|
||||
{"/foo/bar.html/baz.png", 14, 21},
|
||||
{"path#", 0, 4},
|
||||
} {
|
||||
actual := denco.NextSeparator(testcase.path, testcase.start)
|
||||
expected := testcase.expected
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Errorf("path = %q, start = %v expect %v, but %v", testcase.path, testcase.start, expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
65
vendor/github.com/go-openapi/runtime/middleware/doc.go
generated
vendored
65
vendor/github.com/go-openapi/runtime/middleware/doc.go
generated
vendored
@@ -1,65 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*Package middleware provides the library with helper functions for serving swagger APIs.
|
||||
|
||||
Pseudo middleware handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/gorilla/context"
|
||||
)
|
||||
|
||||
func newCompleteMiddleware(ctx *Context) http.Handler {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
defer context.Clear(r)
|
||||
|
||||
// use context to lookup routes
|
||||
if matched, ok := ctx.RouteInfo(r); ok {
|
||||
|
||||
if len(matched.Authenticators) > 0 {
|
||||
if _, err := ctx.Authorize(r, matched); err != nil {
|
||||
ctx.Respond(rw, r, matched.Produces, matched, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
bound, validation := ctx.BindAndValidate(r, matched)
|
||||
if validation != nil {
|
||||
ctx.Respond(rw, r, matched.Produces, matched, validation)
|
||||
return
|
||||
}
|
||||
|
||||
result, err := matched.Handler.Handle(bound)
|
||||
if err != nil {
|
||||
ctx.Respond(rw, r, matched.Produces, matched, err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Respond(rw, r, matched.Produces, matched, result)
|
||||
return
|
||||
}
|
||||
|
||||
// Not found, check if it exists in the other methods first
|
||||
if others := ctx.AllowedMethods(r); len(others) > 0 {
|
||||
ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.MethodNotAllowed(r.Method, others))
|
||||
return
|
||||
}
|
||||
ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.NotFound("path %s was not found", r.URL.Path))
|
||||
})
|
||||
}
|
||||
*/
|
||||
package middleware
|
||||
299
vendor/github.com/go-openapi/runtime/middleware/header/header.go
generated
vendored
299
vendor/github.com/go-openapi/runtime/middleware/header/header.go
generated
vendored
@@ -1,299 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd.
|
||||
|
||||
// this file was taken from the github.com/golang/gddo repository
|
||||
|
||||
// Package header provides functions for parsing HTTP headers.
|
||||
package header
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Octet types from RFC 2616.
|
||||
var octetTypes [256]octetType
|
||||
|
||||
type octetType byte
|
||||
|
||||
const (
|
||||
isToken octetType = 1 << iota
|
||||
isSpace
|
||||
)
|
||||
|
||||
func init() {
|
||||
// OCTET = <any 8-bit sequence of data>
|
||||
// CHAR = <any US-ASCII character (octets 0 - 127)>
|
||||
// CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
|
||||
// CR = <US-ASCII CR, carriage return (13)>
|
||||
// LF = <US-ASCII LF, linefeed (10)>
|
||||
// SP = <US-ASCII SP, space (32)>
|
||||
// HT = <US-ASCII HT, horizontal-tab (9)>
|
||||
// <"> = <US-ASCII double-quote mark (34)>
|
||||
// CRLF = CR LF
|
||||
// LWS = [CRLF] 1*( SP | HT )
|
||||
// TEXT = <any OCTET except CTLs, but including LWS>
|
||||
// separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <">
|
||||
// | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT
|
||||
// token = 1*<any CHAR except CTLs or separators>
|
||||
// qdtext = <any TEXT except <">>
|
||||
|
||||
for c := 0; c < 256; c++ {
|
||||
var t octetType
|
||||
isCtl := c <= 31 || c == 127
|
||||
isChar := 0 <= c && c <= 127
|
||||
isSeparator := strings.IndexRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) >= 0
|
||||
if strings.IndexRune(" \t\r\n", rune(c)) >= 0 {
|
||||
t |= isSpace
|
||||
}
|
||||
if isChar && !isCtl && !isSeparator {
|
||||
t |= isToken
|
||||
}
|
||||
octetTypes[c] = t
|
||||
}
|
||||
}
|
||||
|
||||
// Copy returns a shallow copy of the header.
|
||||
func Copy(header http.Header) http.Header {
|
||||
h := make(http.Header)
|
||||
for k, vs := range header {
|
||||
h[k] = vs
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
var timeLayouts = []string{"Mon, 02 Jan 2006 15:04:05 GMT", time.RFC850, time.ANSIC}
|
||||
|
||||
// ParseTime parses the header as time. The zero value is returned if the
|
||||
// header is not present or there is an error parsing the
|
||||
// header.
|
||||
func ParseTime(header http.Header, key string) time.Time {
|
||||
if s := header.Get(key); s != "" {
|
||||
for _, layout := range timeLayouts {
|
||||
if t, err := time.Parse(layout, s); err == nil {
|
||||
return t.UTC()
|
||||
}
|
||||
}
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
// ParseList parses a comma separated list of values. Commas are ignored in
|
||||
// quoted strings. Quoted values are not unescaped or unquoted. Whitespace is
|
||||
// trimmed.
|
||||
func ParseList(header http.Header, key string) []string {
|
||||
var result []string
|
||||
for _, s := range header[http.CanonicalHeaderKey(key)] {
|
||||
begin := 0
|
||||
end := 0
|
||||
escape := false
|
||||
quote := false
|
||||
for i := 0; i < len(s); i++ {
|
||||
b := s[i]
|
||||
switch {
|
||||
case escape:
|
||||
escape = false
|
||||
end = i + 1
|
||||
case quote:
|
||||
switch b {
|
||||
case '\\':
|
||||
escape = true
|
||||
case '"':
|
||||
quote = false
|
||||
}
|
||||
end = i + 1
|
||||
case b == '"':
|
||||
quote = true
|
||||
end = i + 1
|
||||
case octetTypes[b]&isSpace != 0:
|
||||
if begin == end {
|
||||
begin = i + 1
|
||||
end = begin
|
||||
}
|
||||
case b == ',':
|
||||
if begin < end {
|
||||
result = append(result, s[begin:end])
|
||||
}
|
||||
begin = i + 1
|
||||
end = begin
|
||||
default:
|
||||
end = i + 1
|
||||
}
|
||||
}
|
||||
if begin < end {
|
||||
result = append(result, s[begin:end])
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ParseValueAndParams parses a comma separated list of values with optional
|
||||
// semicolon separated name-value pairs. Content-Type and Content-Disposition
|
||||
// headers are in this format.
|
||||
func ParseValueAndParams(header http.Header, key string) (value string, params map[string]string) {
|
||||
params = make(map[string]string)
|
||||
s := header.Get(key)
|
||||
value, s = expectTokenSlash(s)
|
||||
if value == "" {
|
||||
return
|
||||
}
|
||||
value = strings.ToLower(value)
|
||||
s = skipSpace(s)
|
||||
for strings.HasPrefix(s, ";") {
|
||||
var pkey string
|
||||
pkey, s = expectToken(skipSpace(s[1:]))
|
||||
if pkey == "" {
|
||||
return
|
||||
}
|
||||
if !strings.HasPrefix(s, "=") {
|
||||
return
|
||||
}
|
||||
var pvalue string
|
||||
pvalue, s = expectTokenOrQuoted(s[1:])
|
||||
if pvalue == "" {
|
||||
return
|
||||
}
|
||||
pkey = strings.ToLower(pkey)
|
||||
params[pkey] = pvalue
|
||||
s = skipSpace(s)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type AcceptSpec struct {
|
||||
Value string
|
||||
Q float64
|
||||
}
|
||||
|
||||
// ParseAccept parses Accept* headers.
|
||||
func ParseAccept(header http.Header, key string) (specs []AcceptSpec) {
|
||||
loop:
|
||||
for _, s := range header[key] {
|
||||
for {
|
||||
var spec AcceptSpec
|
||||
spec.Value, s = expectTokenSlash(s)
|
||||
if spec.Value == "" {
|
||||
continue loop
|
||||
}
|
||||
spec.Q = 1.0
|
||||
s = skipSpace(s)
|
||||
if strings.HasPrefix(s, ";") {
|
||||
s = skipSpace(s[1:])
|
||||
if !strings.HasPrefix(s, "q=") {
|
||||
continue loop
|
||||
}
|
||||
spec.Q, s = expectQuality(s[2:])
|
||||
if spec.Q < 0.0 {
|
||||
continue loop
|
||||
}
|
||||
}
|
||||
specs = append(specs, spec)
|
||||
s = skipSpace(s)
|
||||
if !strings.HasPrefix(s, ",") {
|
||||
continue loop
|
||||
}
|
||||
s = skipSpace(s[1:])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func skipSpace(s string) (rest string) {
|
||||
i := 0
|
||||
for ; i < len(s); i++ {
|
||||
if octetTypes[s[i]]&isSpace == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return s[i:]
|
||||
}
|
||||
|
||||
func expectToken(s string) (token, rest string) {
|
||||
i := 0
|
||||
for ; i < len(s); i++ {
|
||||
if octetTypes[s[i]]&isToken == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return s[:i], s[i:]
|
||||
}
|
||||
|
||||
func expectTokenSlash(s string) (token, rest string) {
|
||||
i := 0
|
||||
for ; i < len(s); i++ {
|
||||
b := s[i]
|
||||
if (octetTypes[b]&isToken == 0) && b != '/' {
|
||||
break
|
||||
}
|
||||
}
|
||||
return s[:i], s[i:]
|
||||
}
|
||||
|
||||
func expectQuality(s string) (q float64, rest string) {
|
||||
switch {
|
||||
case len(s) == 0:
|
||||
return -1, ""
|
||||
case s[0] == '0':
|
||||
q = 0
|
||||
case s[0] == '1':
|
||||
q = 1
|
||||
default:
|
||||
return -1, ""
|
||||
}
|
||||
s = s[1:]
|
||||
if !strings.HasPrefix(s, ".") {
|
||||
return q, s
|
||||
}
|
||||
s = s[1:]
|
||||
i := 0
|
||||
n := 0
|
||||
d := 1
|
||||
for ; i < len(s); i++ {
|
||||
b := s[i]
|
||||
if b < '0' || b > '9' {
|
||||
break
|
||||
}
|
||||
n = n*10 + int(b) - '0'
|
||||
d *= 10
|
||||
}
|
||||
return q + float64(n)/float64(d), s[i:]
|
||||
}
|
||||
|
||||
func expectTokenOrQuoted(s string) (value string, rest string) {
|
||||
if !strings.HasPrefix(s, "\"") {
|
||||
return expectToken(s)
|
||||
}
|
||||
s = s[1:]
|
||||
for i := 0; i < len(s); i++ {
|
||||
switch s[i] {
|
||||
case '"':
|
||||
return s[:i], s[i+1:]
|
||||
case '\\':
|
||||
p := make([]byte, len(s)-1)
|
||||
j := copy(p, s[:i])
|
||||
escape := true
|
||||
for i = i + 1; i < len(s); i++ {
|
||||
b := s[i]
|
||||
switch {
|
||||
case escape:
|
||||
escape = false
|
||||
p[j] = b
|
||||
j += 1
|
||||
case b == '\\':
|
||||
escape = true
|
||||
case b == '"':
|
||||
return string(p[:j]), s[i+1:]
|
||||
default:
|
||||
p[j] = b
|
||||
j += 1
|
||||
}
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
82
vendor/github.com/go-openapi/runtime/middleware/negotiate.go
generated
vendored
82
vendor/github.com/go-openapi/runtime/middleware/negotiate.go
generated
vendored
@@ -1,82 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd.
|
||||
|
||||
// this file was taken from the github.com/golang/gddo repository
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware/header"
|
||||
)
|
||||
|
||||
// NegotiateContentEncoding returns the best offered content encoding for the
|
||||
// request's Accept-Encoding header. If two offers match with equal weight and
|
||||
// then the offer earlier in the list is preferred. If no offers are
|
||||
// acceptable, then "" is returned.
|
||||
func NegotiateContentEncoding(r *http.Request, offers []string) string {
|
||||
bestOffer := "identity"
|
||||
bestQ := -1.0
|
||||
specs := header.ParseAccept(r.Header, "Accept-Encoding")
|
||||
for _, offer := range offers {
|
||||
for _, spec := range specs {
|
||||
if spec.Q > bestQ &&
|
||||
(spec.Value == "*" || spec.Value == offer) {
|
||||
bestQ = spec.Q
|
||||
bestOffer = offer
|
||||
}
|
||||
}
|
||||
}
|
||||
if bestQ == 0 {
|
||||
bestOffer = ""
|
||||
}
|
||||
return bestOffer
|
||||
}
|
||||
|
||||
// NegotiateContentType returns the best offered content type for the request's
|
||||
// Accept header. If two offers match with equal weight, then the more specific
|
||||
// offer is preferred. For example, text/* trumps */*. If two offers match
|
||||
// with equal weight and specificity, then the offer earlier in the list is
|
||||
// preferred. If no offers match, then defaultOffer is returned.
|
||||
func NegotiateContentType(r *http.Request, offers []string, defaultOffer string) string {
|
||||
bestOffer := defaultOffer
|
||||
bestQ := -1.0
|
||||
bestWild := 3
|
||||
specs := header.ParseAccept(r.Header, "Accept")
|
||||
for _, offer := range offers {
|
||||
for _, spec := range specs {
|
||||
switch {
|
||||
case spec.Q == 0.0:
|
||||
// ignore
|
||||
case spec.Q < bestQ:
|
||||
// better match found
|
||||
case spec.Value == "*/*":
|
||||
if spec.Q > bestQ || bestWild > 2 {
|
||||
bestQ = spec.Q
|
||||
bestWild = 2
|
||||
bestOffer = offer
|
||||
}
|
||||
case strings.HasSuffix(spec.Value, "/*"):
|
||||
if strings.HasPrefix(offer, spec.Value[:len(spec.Value)-1]) &&
|
||||
(spec.Q > bestQ || bestWild > 1) {
|
||||
bestQ = spec.Q
|
||||
bestWild = 1
|
||||
bestOffer = offer
|
||||
}
|
||||
default:
|
||||
if spec.Value == offer &&
|
||||
(spec.Q > bestQ || bestWild > 0) {
|
||||
bestQ = spec.Q
|
||||
bestWild = 0
|
||||
bestOffer = offer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bestOffer
|
||||
}
|
||||
70
vendor/github.com/go-openapi/runtime/middleware/negotiate_test.go
generated
vendored
70
vendor/github.com/go-openapi/runtime/middleware/negotiate_test.go
generated
vendored
@@ -1,70 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var negotiateContentEncodingTests = []struct {
|
||||
s string
|
||||
offers []string
|
||||
expect string
|
||||
}{
|
||||
{"", []string{"identity", "gzip"}, "identity"},
|
||||
{"*;q=0", []string{"identity", "gzip"}, ""},
|
||||
{"gzip", []string{"identity", "gzip"}, "gzip"},
|
||||
}
|
||||
|
||||
func TestNegotiateContentEnoding(t *testing.T) {
|
||||
for _, tt := range negotiateContentEncodingTests {
|
||||
r := &http.Request{Header: http.Header{"Accept-Encoding": {tt.s}}}
|
||||
actual := NegotiateContentEncoding(r, tt.offers)
|
||||
if actual != tt.expect {
|
||||
t.Errorf("NegotiateContentEncoding(%q, %#v)=%q, want %q", tt.s, tt.offers, actual, tt.expect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var negotiateContentTypeTests = []struct {
|
||||
s string
|
||||
offers []string
|
||||
defaultOffer string
|
||||
expect string
|
||||
}{
|
||||
{"text/html, */*;q=0", []string{"x/y"}, "", ""},
|
||||
{"text/html, */*", []string{"x/y"}, "", "x/y"},
|
||||
{"text/html, image/png", []string{"text/html", "image/png"}, "", "text/html"},
|
||||
{"text/html, image/png", []string{"image/png", "text/html"}, "", "image/png"},
|
||||
{"text/html, image/png; q=0.5", []string{"image/png"}, "", "image/png"},
|
||||
{"text/html, image/png; q=0.5", []string{"text/html"}, "", "text/html"},
|
||||
{"text/html, image/png; q=0.5", []string{"foo/bar"}, "", ""},
|
||||
{"text/html, image/png; q=0.5", []string{"image/png", "text/html"}, "", "text/html"},
|
||||
{"text/html, image/png; q=0.5", []string{"text/html", "image/png"}, "", "text/html"},
|
||||
{"text/html;q=0.5, image/png", []string{"image/png"}, "", "image/png"},
|
||||
{"text/html;q=0.5, image/png", []string{"text/html"}, "", "text/html"},
|
||||
{"text/html;q=0.5, image/png", []string{"image/png", "text/html"}, "", "image/png"},
|
||||
{"text/html;q=0.5, image/png", []string{"text/html", "image/png"}, "", "image/png"},
|
||||
{"image/png, image/*;q=0.5", []string{"image/jpg", "image/png"}, "", "image/png"},
|
||||
{"image/png, image/*;q=0.5", []string{"image/jpg"}, "", "image/jpg"},
|
||||
{"image/png, image/*;q=0.5", []string{"image/jpg", "image/gif"}, "", "image/jpg"},
|
||||
{"image/png, image/*", []string{"image/jpg", "image/gif"}, "", "image/jpg"},
|
||||
{"image/png, image/*", []string{"image/gif", "image/jpg"}, "", "image/gif"},
|
||||
{"image/png, image/*", []string{"image/gif", "image/png"}, "", "image/png"},
|
||||
{"image/png, image/*", []string{"image/png", "image/gif"}, "", "image/png"},
|
||||
}
|
||||
|
||||
func TestNegotiateContentType(t *testing.T) {
|
||||
for _, tt := range negotiateContentTypeTests {
|
||||
r := &http.Request{Header: http.Header{"Accept": {tt.s}}}
|
||||
actual := NegotiateContentType(r, tt.offers, tt.defaultOffer)
|
||||
if actual != tt.expect {
|
||||
t.Errorf("NegotiateContentType(%q, %#v, %q)=%q, want %q", tt.s, tt.offers, tt.defaultOffer, actual, tt.expect)
|
||||
}
|
||||
}
|
||||
}
|
||||
48
vendor/github.com/go-openapi/runtime/middleware/not_implemented.go
generated
vendored
48
vendor/github.com/go-openapi/runtime/middleware/not_implemented.go
generated
vendored
@@ -1,48 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
)
|
||||
|
||||
type errorResp struct {
|
||||
code int
|
||||
response interface{}
|
||||
headers http.Header
|
||||
}
|
||||
|
||||
func (e *errorResp) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
for k, v := range e.headers {
|
||||
for _, val := range v {
|
||||
rw.Header().Add(k, val)
|
||||
}
|
||||
}
|
||||
if e.code > 0 {
|
||||
rw.WriteHeader(e.code)
|
||||
} else {
|
||||
rw.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
if err := producer.Produce(rw, e.response); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// NotImplemented the error response when the response is not implemented
|
||||
func NotImplemented(message string) Responder {
|
||||
return &errorResp{http.StatusNotImplemented, message, make(http.Header)}
|
||||
}
|
||||
26
vendor/github.com/go-openapi/runtime/middleware/operation.go
generated
vendored
26
vendor/github.com/go-openapi/runtime/middleware/operation.go
generated
vendored
@@ -1,26 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import "net/http"
|
||||
|
||||
// NewOperationExecutor creates a context aware middleware that handles the operations after routing
|
||||
func NewOperationExecutor(ctx *Context) http.Handler {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
// use context to lookup routes
|
||||
route, _ := ctx.RouteInfo(r)
|
||||
route.Handler.ServeHTTP(rw, r)
|
||||
})
|
||||
}
|
||||
64
vendor/github.com/go-openapi/runtime/middleware/operation_test.go
generated
vendored
64
vendor/github.com/go-openapi/runtime/middleware/operation_test.go
generated
vendored
@@ -1,64 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/internal/testing/petstore"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestOperationExecutor(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
api.RegisterOperation("get", "/pets", runtime.OperationHandlerFunc(func(params interface{}) (interface{}, error) {
|
||||
return []interface{}{
|
||||
map[string]interface{}{"id": 1, "name": "a dog"},
|
||||
}, nil
|
||||
}))
|
||||
|
||||
context := NewContext(spec, api, nil)
|
||||
context.router = DefaultRouter(spec, context.api)
|
||||
mw := NewOperationExecutor(context)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
request, _ := http.NewRequest("GET", "/api/pets", nil)
|
||||
request.Header.Add("Accept", "application/json")
|
||||
request.SetBasicAuth("admin", "admin")
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Equal(t, `[{"id":1,"name":"a dog"}]`+"\n", recorder.Body.String())
|
||||
|
||||
spec, api = petstore.NewAPI(t)
|
||||
api.RegisterOperation("get", "/pets", runtime.OperationHandlerFunc(func(params interface{}) (interface{}, error) {
|
||||
return nil, errors.New(422, "expected")
|
||||
}))
|
||||
|
||||
context = NewContext(spec, api, nil)
|
||||
context.router = DefaultRouter(spec, context.api)
|
||||
mw = NewOperationExecutor(context)
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("GET", "/api/pets", nil)
|
||||
request.Header.Add("Accept", "application/json")
|
||||
request.SetBasicAuth("admin", "admin")
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 422, recorder.Code)
|
||||
assert.Equal(t, `{"code":422,"message":"expected"}`, recorder.Body.String())
|
||||
}
|
||||
480
vendor/github.com/go-openapi/runtime/middleware/parameter.go
generated
vendored
480
vendor/github.com/go-openapi/runtime/middleware/parameter.go
generated
vendored
@@ -1,480 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
const defaultMaxMemory = 32 << 20
|
||||
|
||||
var textUnmarshalType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
|
||||
|
||||
func newUntypedParamBinder(param spec.Parameter, spec *spec.Swagger, formats strfmt.Registry) *untypedParamBinder {
|
||||
binder := new(untypedParamBinder)
|
||||
binder.Name = param.Name
|
||||
binder.parameter = ¶m
|
||||
binder.formats = formats
|
||||
if param.In != "body" {
|
||||
binder.validator = validate.NewParamValidator(¶m, formats)
|
||||
} else {
|
||||
binder.validator = validate.NewSchemaValidator(param.Schema, spec, param.Name, formats)
|
||||
}
|
||||
|
||||
return binder
|
||||
}
|
||||
|
||||
type untypedParamBinder struct {
|
||||
parameter *spec.Parameter
|
||||
formats strfmt.Registry
|
||||
Name string
|
||||
validator validate.EntityValidator
|
||||
}
|
||||
|
||||
func (p *untypedParamBinder) Type() reflect.Type {
|
||||
return p.typeForSchema(p.parameter.Type, p.parameter.Format, p.parameter.Items)
|
||||
}
|
||||
|
||||
func (p *untypedParamBinder) typeForSchema(tpe, format string, items *spec.Items) reflect.Type {
|
||||
switch tpe {
|
||||
case "boolean":
|
||||
return reflect.TypeOf(true)
|
||||
|
||||
case "string":
|
||||
if tt, ok := p.formats.GetType(format); ok {
|
||||
return tt
|
||||
}
|
||||
return reflect.TypeOf("")
|
||||
|
||||
case "integer":
|
||||
switch format {
|
||||
case "int8":
|
||||
return reflect.TypeOf(int8(0))
|
||||
case "int16":
|
||||
return reflect.TypeOf(int16(0))
|
||||
case "int32":
|
||||
return reflect.TypeOf(int32(0))
|
||||
case "int64":
|
||||
return reflect.TypeOf(int64(0))
|
||||
default:
|
||||
return reflect.TypeOf(int64(0))
|
||||
}
|
||||
|
||||
case "number":
|
||||
switch format {
|
||||
case "float":
|
||||
return reflect.TypeOf(float32(0))
|
||||
case "double":
|
||||
return reflect.TypeOf(float64(0))
|
||||
}
|
||||
|
||||
case "array":
|
||||
if items == nil {
|
||||
return nil
|
||||
}
|
||||
itemsType := p.typeForSchema(items.Type, items.Format, items.Items)
|
||||
if itemsType == nil {
|
||||
return nil
|
||||
}
|
||||
return reflect.MakeSlice(reflect.SliceOf(itemsType), 0, 0).Type()
|
||||
|
||||
case "file":
|
||||
return reflect.TypeOf(&runtime.File{}).Elem()
|
||||
|
||||
case "object":
|
||||
return reflect.TypeOf(map[string]interface{}{})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *untypedParamBinder) allowsMulti() bool {
|
||||
return p.parameter.In == "query" || p.parameter.In == "formData"
|
||||
}
|
||||
|
||||
func (p *untypedParamBinder) readValue(values runtime.Gettable, target reflect.Value) ([]string, bool, bool, error) {
|
||||
name, in, cf, tpe := p.parameter.Name, p.parameter.In, p.parameter.CollectionFormat, p.parameter.Type
|
||||
if tpe == "array" {
|
||||
if cf == "multi" {
|
||||
if !p.allowsMulti() {
|
||||
return nil, false, false, errors.InvalidCollectionFormat(name, in, cf)
|
||||
}
|
||||
vv, hasKey, _ := values.GetOK(name)
|
||||
return vv, false, hasKey, nil
|
||||
}
|
||||
|
||||
v, hk, hv := values.GetOK(name)
|
||||
if !hv {
|
||||
return nil, false, hk, nil
|
||||
}
|
||||
d, c, e := p.readFormattedSliceFieldValue(v[len(v)-1], target)
|
||||
return d, c, hk, e
|
||||
}
|
||||
|
||||
vv, hk, _ := values.GetOK(name)
|
||||
return vv, false, hk, nil
|
||||
}
|
||||
|
||||
func (p *untypedParamBinder) Bind(request *http.Request, routeParams RouteParams, consumer runtime.Consumer, target reflect.Value) error {
|
||||
// fmt.Println("binding", p.name, "as", p.Type())
|
||||
switch p.parameter.In {
|
||||
case "query":
|
||||
data, custom, hasKey, err := p.readValue(runtime.Values(request.URL.Query()), target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if custom {
|
||||
return nil
|
||||
}
|
||||
|
||||
return p.bindValue(data, hasKey, target)
|
||||
|
||||
case "header":
|
||||
data, custom, hasKey, err := p.readValue(runtime.Values(request.Header), target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if custom {
|
||||
return nil
|
||||
}
|
||||
return p.bindValue(data, hasKey, target)
|
||||
|
||||
case "path":
|
||||
data, custom, hasKey, err := p.readValue(routeParams, target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if custom {
|
||||
return nil
|
||||
}
|
||||
return p.bindValue(data, hasKey, target)
|
||||
|
||||
case "formData":
|
||||
var err error
|
||||
var mt string
|
||||
|
||||
mt, _, e := runtime.ContentType(request.Header)
|
||||
if e != nil {
|
||||
// because of the interface conversion go thinks the error is not nil
|
||||
// so we first check for nil and then set the err var if it's not nil
|
||||
err = e
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return errors.InvalidContentType("", []string{"multipart/form-data", "application/x-www-form-urlencoded"})
|
||||
}
|
||||
|
||||
if mt != "multipart/form-data" && mt != "application/x-www-form-urlencoded" {
|
||||
return errors.InvalidContentType(mt, []string{"multipart/form-data", "application/x-www-form-urlencoded"})
|
||||
}
|
||||
|
||||
if mt == "multipart/form-data" {
|
||||
if err := request.ParseMultipartForm(defaultMaxMemory); err != nil {
|
||||
return errors.NewParseError(p.Name, p.parameter.In, "", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := request.ParseForm(); err != nil {
|
||||
return errors.NewParseError(p.Name, p.parameter.In, "", err)
|
||||
}
|
||||
|
||||
if p.parameter.Type == "file" {
|
||||
file, header, err := request.FormFile(p.parameter.Name)
|
||||
if err != nil {
|
||||
return errors.NewParseError(p.Name, p.parameter.In, "", err)
|
||||
}
|
||||
target.Set(reflect.ValueOf(runtime.File{Data: file, Header: header}))
|
||||
return nil
|
||||
}
|
||||
|
||||
if request.MultipartForm != nil {
|
||||
data, custom, hasKey, err := p.readValue(runtime.Values(request.MultipartForm.Value), target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if custom {
|
||||
return nil
|
||||
}
|
||||
return p.bindValue(data, hasKey, target)
|
||||
}
|
||||
data, custom, hasKey, err := p.readValue(runtime.Values(request.PostForm), target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if custom {
|
||||
return nil
|
||||
}
|
||||
return p.bindValue(data, hasKey, target)
|
||||
|
||||
case "body":
|
||||
newValue := reflect.New(target.Type())
|
||||
if !runtime.HasBody(request) {
|
||||
if p.parameter.Default != nil {
|
||||
target.Set(reflect.ValueOf(p.parameter.Default))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
if err := consumer.Consume(request.Body, newValue.Interface()); err != nil {
|
||||
if err == io.EOF && p.parameter.Default != nil {
|
||||
target.Set(reflect.ValueOf(p.parameter.Default))
|
||||
return nil
|
||||
}
|
||||
tpe := p.parameter.Type
|
||||
if p.parameter.Format != "" {
|
||||
tpe = p.parameter.Format
|
||||
}
|
||||
return errors.InvalidType(p.Name, p.parameter.In, tpe, nil)
|
||||
}
|
||||
target.Set(reflect.Indirect(newValue))
|
||||
return nil
|
||||
default:
|
||||
return errors.New(500, fmt.Sprintf("invalid parameter location %q", p.parameter.In))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *untypedParamBinder) bindValue(data []string, hasKey bool, target reflect.Value) error {
|
||||
if p.parameter.Type == "array" {
|
||||
return p.setSliceFieldValue(target, p.parameter.Default, data, hasKey)
|
||||
}
|
||||
var d string
|
||||
if len(data) > 0 {
|
||||
d = data[len(data)-1]
|
||||
}
|
||||
return p.setFieldValue(target, p.parameter.Default, d, hasKey)
|
||||
}
|
||||
|
||||
func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue interface{}, data string, hasKey bool) error {
|
||||
tpe := p.parameter.Type
|
||||
if p.parameter.Format != "" {
|
||||
tpe = p.parameter.Format
|
||||
}
|
||||
|
||||
if (!hasKey || (!p.parameter.AllowEmptyValue && data == "")) && p.parameter.Required && p.parameter.Default == nil {
|
||||
return errors.Required(p.Name, p.parameter.In)
|
||||
}
|
||||
|
||||
ok, err := p.tryUnmarshaler(target, defaultValue, data)
|
||||
if err != nil {
|
||||
return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
|
||||
}
|
||||
if ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
defVal := reflect.Zero(target.Type())
|
||||
if defaultValue != nil {
|
||||
defVal = reflect.ValueOf(defaultValue)
|
||||
}
|
||||
|
||||
if tpe == "byte" {
|
||||
if data == "" {
|
||||
if target.CanSet() {
|
||||
target.SetBytes(defVal.Bytes())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
b, err := base64.StdEncoding.DecodeString(data)
|
||||
if err != nil {
|
||||
b, err = base64.URLEncoding.DecodeString(data)
|
||||
if err != nil {
|
||||
return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
|
||||
}
|
||||
}
|
||||
if target.CanSet() {
|
||||
target.SetBytes(b)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
switch target.Kind() {
|
||||
case reflect.Bool:
|
||||
if data == "" {
|
||||
if target.CanSet() {
|
||||
target.SetBool(defVal.Bool())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
b, err := swag.ConvertBool(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if target.CanSet() {
|
||||
target.SetBool(b)
|
||||
}
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if data == "" {
|
||||
if target.CanSet() {
|
||||
rd := defVal.Convert(reflect.TypeOf(int64(0)))
|
||||
target.SetInt(rd.Int())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
i, err := strconv.ParseInt(data, 10, 64)
|
||||
if err != nil {
|
||||
return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
|
||||
}
|
||||
if target.OverflowInt(i) {
|
||||
return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
|
||||
}
|
||||
if target.CanSet() {
|
||||
target.SetInt(i)
|
||||
}
|
||||
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
if data == "" {
|
||||
if target.CanSet() {
|
||||
rd := defVal.Convert(reflect.TypeOf(uint64(0)))
|
||||
target.SetUint(rd.Uint())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
u, err := strconv.ParseUint(data, 10, 64)
|
||||
if err != nil {
|
||||
return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
|
||||
}
|
||||
if target.OverflowUint(u) {
|
||||
return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
|
||||
}
|
||||
if target.CanSet() {
|
||||
target.SetUint(u)
|
||||
}
|
||||
|
||||
case reflect.Float32, reflect.Float64:
|
||||
if data == "" {
|
||||
if target.CanSet() {
|
||||
rd := defVal.Convert(reflect.TypeOf(float64(0)))
|
||||
target.SetFloat(rd.Float())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
f, err := strconv.ParseFloat(data, 64)
|
||||
if err != nil {
|
||||
return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
|
||||
}
|
||||
if target.OverflowFloat(f) {
|
||||
return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
|
||||
}
|
||||
if target.CanSet() {
|
||||
target.SetFloat(f)
|
||||
}
|
||||
|
||||
case reflect.String:
|
||||
value := data
|
||||
if value == "" {
|
||||
value = defVal.String()
|
||||
}
|
||||
// validate string
|
||||
if target.CanSet() {
|
||||
target.SetString(value)
|
||||
}
|
||||
|
||||
case reflect.Ptr:
|
||||
if data == "" && defVal.Kind() == reflect.Ptr {
|
||||
if target.CanSet() {
|
||||
target.Set(defVal)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
newVal := reflect.New(target.Type().Elem())
|
||||
if err := p.setFieldValue(reflect.Indirect(newVal), defVal, data, hasKey); err != nil {
|
||||
return err
|
||||
}
|
||||
if target.CanSet() {
|
||||
target.Set(newVal)
|
||||
}
|
||||
|
||||
default:
|
||||
return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *untypedParamBinder) tryUnmarshaler(target reflect.Value, defaultValue interface{}, data string) (bool, error) {
|
||||
if !target.CanSet() {
|
||||
return false, nil
|
||||
}
|
||||
// When a type implements encoding.TextUnmarshaler we'll use that instead of reflecting some more
|
||||
if reflect.PtrTo(target.Type()).Implements(textUnmarshalType) {
|
||||
if defaultValue != nil && len(data) == 0 {
|
||||
target.Set(reflect.ValueOf(defaultValue))
|
||||
return true, nil
|
||||
}
|
||||
value := reflect.New(target.Type())
|
||||
if err := value.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(data)); err != nil {
|
||||
return true, err
|
||||
}
|
||||
target.Set(reflect.Indirect(value))
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (p *untypedParamBinder) readFormattedSliceFieldValue(data string, target reflect.Value) ([]string, bool, error) {
|
||||
ok, err := p.tryUnmarshaler(target, p.parameter.Default, data)
|
||||
if err != nil {
|
||||
return nil, true, err
|
||||
}
|
||||
if ok {
|
||||
return nil, true, nil
|
||||
}
|
||||
|
||||
return swag.SplitByFormat(data, p.parameter.CollectionFormat), false, nil
|
||||
}
|
||||
|
||||
func (p *untypedParamBinder) setSliceFieldValue(target reflect.Value, defaultValue interface{}, data []string, hasKey bool) error {
|
||||
sz := len(data)
|
||||
if (!hasKey || (!p.parameter.AllowEmptyValue && (sz == 0 || (sz == 1 && data[0] == "")))) && p.parameter.Required && defaultValue == nil {
|
||||
return errors.Required(p.Name, p.parameter.In)
|
||||
}
|
||||
|
||||
defVal := reflect.Zero(target.Type())
|
||||
if defaultValue != nil {
|
||||
defVal = reflect.ValueOf(defaultValue)
|
||||
}
|
||||
|
||||
if !target.CanSet() {
|
||||
return nil
|
||||
}
|
||||
if sz == 0 {
|
||||
target.Set(defVal)
|
||||
return nil
|
||||
}
|
||||
|
||||
value := reflect.MakeSlice(reflect.SliceOf(target.Type().Elem()), sz, sz)
|
||||
|
||||
for i := 0; i < sz; i++ {
|
||||
if err := p.setFieldValue(value.Index(i), nil, data[i], hasKey); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
target.Set(value)
|
||||
|
||||
return nil
|
||||
}
|
||||
340
vendor/github.com/go-openapi/runtime/middleware/parameter_test.go
generated
vendored
340
vendor/github.com/go-openapi/runtime/middleware/parameter_test.go
generated
vendored
@@ -1,340 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"math"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type email struct {
|
||||
Address string
|
||||
}
|
||||
|
||||
type paramFactory func(string) *spec.Parameter
|
||||
|
||||
var paramFactories = []paramFactory{
|
||||
spec.QueryParam,
|
||||
spec.HeaderParam,
|
||||
spec.PathParam,
|
||||
spec.FormDataParam,
|
||||
}
|
||||
|
||||
func np(param *spec.Parameter) *untypedParamBinder {
|
||||
return newUntypedParamBinder(*param, new(spec.Swagger), strfmt.Default)
|
||||
}
|
||||
|
||||
var stringItems = new(spec.Items)
|
||||
|
||||
func init() {
|
||||
stringItems.Type = "string"
|
||||
}
|
||||
|
||||
func testCollectionFormat(t *testing.T, param *spec.Parameter, valid bool) {
|
||||
binder := &untypedParamBinder{
|
||||
parameter: param,
|
||||
}
|
||||
_, _, _, err := binder.readValue(runtime.Values(nil), reflect.ValueOf(nil))
|
||||
if valid {
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, errors.InvalidCollectionFormat(param.Name, param.In, param.CollectionFormat), err)
|
||||
}
|
||||
}
|
||||
|
||||
func requiredError(param *spec.Parameter) *errors.Validation {
|
||||
return errors.Required(param.Name, param.In)
|
||||
}
|
||||
|
||||
func validateRequiredTest(t *testing.T, param *spec.Parameter, value reflect.Value) {
|
||||
|
||||
binder := np(param)
|
||||
err := binder.bindValue([]string{}, true, value)
|
||||
assert.Error(t, err)
|
||||
assert.NotNil(t, param)
|
||||
assert.EqualError(t, requiredError(param), err.Error())
|
||||
err = binder.bindValue([]string{""}, true, value)
|
||||
if assert.Error(t, err) {
|
||||
assert.EqualError(t, requiredError(param), err.Error())
|
||||
}
|
||||
|
||||
// should be impossible data, but let's go with it
|
||||
err = binder.bindValue([]string{"a"}, false, value)
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, requiredError(param), err.Error())
|
||||
err = binder.bindValue([]string{""}, false, value)
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, requiredError(param), err.Error())
|
||||
}
|
||||
|
||||
func validateRequiredAllowEmptyTest(t *testing.T, param *spec.Parameter, value reflect.Value) {
|
||||
param.AllowEmptyValue = true
|
||||
binder := np(param)
|
||||
err := binder.bindValue([]string{}, true, value)
|
||||
assert.NoError(t, err)
|
||||
if assert.NotNil(t, param) {
|
||||
err = binder.bindValue([]string{""}, true, value)
|
||||
assert.NoError(t, err)
|
||||
err = binder.bindValue([]string{"1"}, false, value)
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, requiredError(param), err.Error())
|
||||
err = binder.bindValue([]string{""}, false, value)
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, requiredError(param), err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRequiredValidation(t *testing.T) {
|
||||
strParam := spec.QueryParam("name").Typed("string", "").AsRequired()
|
||||
validateRequiredTest(t, strParam, reflect.ValueOf(""))
|
||||
validateRequiredAllowEmptyTest(t, strParam, reflect.ValueOf(""))
|
||||
|
||||
intParam := spec.QueryParam("id").Typed("integer", "int32").AsRequired()
|
||||
validateRequiredTest(t, intParam, reflect.ValueOf(int32(0)))
|
||||
validateRequiredAllowEmptyTest(t, intParam, reflect.ValueOf(int32(0)))
|
||||
longParam := spec.QueryParam("id").Typed("integer", "int64").AsRequired()
|
||||
validateRequiredTest(t, longParam, reflect.ValueOf(int64(0)))
|
||||
validateRequiredAllowEmptyTest(t, longParam, reflect.ValueOf(int64(0)))
|
||||
|
||||
floatParam := spec.QueryParam("score").Typed("number", "float").AsRequired()
|
||||
validateRequiredTest(t, floatParam, reflect.ValueOf(float32(0)))
|
||||
validateRequiredAllowEmptyTest(t, floatParam, reflect.ValueOf(float32(0)))
|
||||
doubleParam := spec.QueryParam("score").Typed("number", "double").AsRequired()
|
||||
validateRequiredTest(t, doubleParam, reflect.ValueOf(float64(0)))
|
||||
validateRequiredAllowEmptyTest(t, doubleParam, reflect.ValueOf(float64(0)))
|
||||
|
||||
dateTimeParam := spec.QueryParam("registered").Typed("string", "date-time").AsRequired()
|
||||
validateRequiredTest(t, dateTimeParam, reflect.ValueOf(strfmt.DateTime{}))
|
||||
// validateRequiredAllowEmptyTest(t, dateTimeParam, reflect.ValueOf(strfmt.DateTime{}))
|
||||
|
||||
dateParam := spec.QueryParam("registered").Typed("string", "date").AsRequired()
|
||||
validateRequiredTest(t, dateParam, reflect.ValueOf(strfmt.Date{}))
|
||||
// validateRequiredAllowEmptyTest(t, dateParam, reflect.ValueOf(strfmt.DateTime{}))
|
||||
|
||||
sliceParam := spec.QueryParam("tags").CollectionOf(stringItems, "").AsRequired()
|
||||
validateRequiredTest(t, sliceParam, reflect.MakeSlice(reflect.TypeOf([]string{}), 0, 0))
|
||||
validateRequiredAllowEmptyTest(t, sliceParam, reflect.MakeSlice(reflect.TypeOf([]string{}), 0, 0))
|
||||
}
|
||||
|
||||
func TestInvalidCollectionFormat(t *testing.T) {
|
||||
validCf1 := spec.QueryParam("validFmt").CollectionOf(stringItems, "multi")
|
||||
validCf2 := spec.FormDataParam("validFmt2").CollectionOf(stringItems, "multi")
|
||||
invalidCf1 := spec.HeaderParam("invalidHdr").CollectionOf(stringItems, "multi")
|
||||
invalidCf2 := spec.PathParam("invalidPath").CollectionOf(stringItems, "multi")
|
||||
|
||||
testCollectionFormat(t, validCf1, true)
|
||||
testCollectionFormat(t, validCf2, true)
|
||||
testCollectionFormat(t, invalidCf1, false)
|
||||
testCollectionFormat(t, invalidCf2, false)
|
||||
}
|
||||
|
||||
func invalidTypeError(param *spec.Parameter, data interface{}) *errors.Validation {
|
||||
tpe := param.Type
|
||||
if param.Format != "" {
|
||||
tpe = param.Format
|
||||
}
|
||||
return errors.InvalidType(param.Name, param.In, tpe, data)
|
||||
}
|
||||
|
||||
func TestTypeValidation(t *testing.T) {
|
||||
for _, newParam := range paramFactories {
|
||||
intParam := newParam("badInt").Typed("integer", "int32")
|
||||
value := reflect.ValueOf(int32(0))
|
||||
binder := np(intParam)
|
||||
err := binder.bindValue([]string{"yada"}, true, value)
|
||||
// fails for invalid string
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, invalidTypeError(intParam, "yada"), err)
|
||||
// fails for overflow
|
||||
val := int64(math.MaxInt32)
|
||||
str := strconv.FormatInt(val, 10) + "0"
|
||||
v := int32(0)
|
||||
value = reflect.ValueOf(&v).Elem()
|
||||
binder = np(intParam)
|
||||
err = binder.bindValue([]string{str}, true, value)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, invalidTypeError(intParam, str), err)
|
||||
|
||||
longParam := newParam("badLong").Typed("integer", "int64")
|
||||
value = reflect.ValueOf(int64(0))
|
||||
binder = np(longParam)
|
||||
err = binder.bindValue([]string{"yada"}, true, value)
|
||||
// fails for invalid string
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, invalidTypeError(longParam, "yada"), err)
|
||||
// fails for overflow
|
||||
str2 := strconv.FormatInt(math.MaxInt64, 10) + "0"
|
||||
v2 := int64(0)
|
||||
vv2 := reflect.ValueOf(&v2).Elem()
|
||||
binder = np(longParam)
|
||||
err = binder.bindValue([]string{str2}, true, vv2)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, invalidTypeError(longParam, str2), err)
|
||||
|
||||
floatParam := newParam("badFloat").Typed("number", "float")
|
||||
value = reflect.ValueOf(float64(0))
|
||||
binder = np(floatParam)
|
||||
err = binder.bindValue([]string{"yada"}, true, value)
|
||||
// fails for invalid string
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, invalidTypeError(floatParam, "yada"), err)
|
||||
// fails for overflow
|
||||
str3 := strconv.FormatFloat(math.MaxFloat64, 'f', 5, 64)
|
||||
v3 := reflect.TypeOf(float32(0))
|
||||
value = reflect.New(v3).Elem()
|
||||
binder = np(floatParam)
|
||||
err = binder.bindValue([]string{str3}, true, value)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, invalidTypeError(floatParam, str3), err)
|
||||
|
||||
doubleParam := newParam("badDouble").Typed("number", "double")
|
||||
value = reflect.ValueOf(float64(0))
|
||||
binder = np(doubleParam)
|
||||
err = binder.bindValue([]string{"yada"}, true, value)
|
||||
// fails for invalid string
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, invalidTypeError(doubleParam, "yada"), err)
|
||||
// fails for overflow
|
||||
str4 := "9" + strconv.FormatFloat(math.MaxFloat64, 'f', 5, 64)
|
||||
v4 := reflect.TypeOf(float64(0))
|
||||
value = reflect.New(v4).Elem()
|
||||
binder = np(doubleParam)
|
||||
err = binder.bindValue([]string{str4}, true, value)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, invalidTypeError(doubleParam, str4), err)
|
||||
|
||||
dateParam := newParam("badDate").Typed("string", "date")
|
||||
value = reflect.ValueOf(strfmt.Date{})
|
||||
binder = np(dateParam)
|
||||
err = binder.bindValue([]string{"yada"}, true, value)
|
||||
// fails for invalid string
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, invalidTypeError(dateParam, "yada"), err)
|
||||
|
||||
dateTimeParam := newParam("badDateTime").Typed("string", "date-time")
|
||||
value = reflect.ValueOf(strfmt.DateTime{})
|
||||
binder = np(dateTimeParam)
|
||||
err = binder.bindValue([]string{"yada"}, true, value)
|
||||
// fails for invalid string
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, invalidTypeError(dateTimeParam, "yada"), err)
|
||||
|
||||
byteParam := newParam("badByte").Typed("string", "byte")
|
||||
values := url.Values(map[string][]string{})
|
||||
values.Add("badByte", "yaüda")
|
||||
v5 := []byte{}
|
||||
value = reflect.ValueOf(&v5).Elem()
|
||||
binder = np(byteParam)
|
||||
err = binder.bindValue([]string{"yaüda"}, true, value)
|
||||
// fails for invalid string
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, invalidTypeError(byteParam, "yaüda"), err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTypeDetectionInvalidItems(t *testing.T) {
|
||||
withoutItems := spec.QueryParam("without").CollectionOf(nil, "")
|
||||
binder := &untypedParamBinder{
|
||||
Name: "without",
|
||||
parameter: withoutItems,
|
||||
}
|
||||
assert.Nil(t, binder.Type())
|
||||
|
||||
items := new(spec.Items)
|
||||
items.Type = "array"
|
||||
withInvalidItems := spec.QueryParam("invalidItems").CollectionOf(items, "")
|
||||
binder = &untypedParamBinder{
|
||||
Name: "invalidItems",
|
||||
parameter: withInvalidItems,
|
||||
}
|
||||
assert.Nil(t, binder.Type())
|
||||
|
||||
noType := spec.QueryParam("invalidType")
|
||||
noType.Type = "invalid"
|
||||
binder = &untypedParamBinder{
|
||||
Name: "invalidType",
|
||||
parameter: noType,
|
||||
}
|
||||
assert.Nil(t, binder.Type())
|
||||
}
|
||||
|
||||
// type emailStrFmt struct {
|
||||
// name string
|
||||
// tpe reflect.Type
|
||||
// validator FormatValidator
|
||||
// }
|
||||
//
|
||||
// func (e *emailStrFmt) Name() string {
|
||||
// return e.name
|
||||
// }
|
||||
//
|
||||
// func (e *emailStrFmt) Type() reflect.Type {
|
||||
// return e.tpe
|
||||
// }
|
||||
//
|
||||
// func (e *emailStrFmt) Matches(str string) bool {
|
||||
// return e.validator(str)
|
||||
// }
|
||||
//
|
||||
// func TestTypeDetectionValid(t *testing.T) {
|
||||
// // emlFmt := &emailStrFmt{
|
||||
// // name: "email",
|
||||
// // tpe: reflect.TypeOf(email{}),
|
||||
// // }
|
||||
// // formats := []StringFormat{emlFmt}
|
||||
//
|
||||
// expected := map[string]reflect.Type{
|
||||
// "name": reflect.TypeOf(""),
|
||||
// "id": reflect.TypeOf(int64(0)),
|
||||
// "age": reflect.TypeOf(int32(0)),
|
||||
// "score": reflect.TypeOf(float32(0)),
|
||||
// "factor": reflect.TypeOf(float64(0)),
|
||||
// "friend": reflect.TypeOf(map[string]interface{}{}),
|
||||
// "X-Request-Id": reflect.TypeOf(int64(0)),
|
||||
// "tags": reflect.TypeOf([]string{}),
|
||||
// "confirmed": reflect.TypeOf(true),
|
||||
// "planned": reflect.TypeOf(swagger.Date{}),
|
||||
// "delivered": reflect.TypeOf(swagger.DateTime{}),
|
||||
// "email": reflect.TypeOf(email{}),
|
||||
// "picture": reflect.TypeOf([]byte{}),
|
||||
// "file": reflect.TypeOf(&swagger.File{}).Elem(),
|
||||
// }
|
||||
//
|
||||
// params := parametersForAllTypes("")
|
||||
// emailParam := spec.QueryParam("email").Typed("string", "email")
|
||||
// params["email"] = *emailParam
|
||||
//
|
||||
// fileParam := spec.FileParam("file")
|
||||
// params["file"] = *fileParam
|
||||
//
|
||||
// for _, v := range params {
|
||||
// binder := ¶mBinder{
|
||||
// formats: formats,
|
||||
// name: v.Name,
|
||||
// parameter: &v,
|
||||
// }
|
||||
// assert.Equal(t, expected[v.Name], binder.Type(), "name: %s", v.Name)
|
||||
// }
|
||||
// }
|
||||
101
vendor/github.com/go-openapi/runtime/middleware/redoc.go
generated
vendored
101
vendor/github.com/go-openapi/runtime/middleware/redoc.go
generated
vendored
@@ -1,101 +0,0 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"path"
|
||||
)
|
||||
|
||||
// RedocOpts configures the Redoc middlewares
|
||||
type RedocOpts struct {
|
||||
// BasePath for the UI path, defaults to: /
|
||||
BasePath string
|
||||
// Path combines with BasePath for the full UI path, defaults to: docs
|
||||
Path string
|
||||
// SpecURL the url to find the spec for
|
||||
SpecURL string
|
||||
// RedocURL for the js that generates the redoc site, defaults to: https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js
|
||||
RedocURL string
|
||||
// Title for the documentation site, default to: API documentation
|
||||
Title string
|
||||
}
|
||||
|
||||
// EnsureDefaults in case some options are missing
|
||||
func (r *RedocOpts) EnsureDefaults() {
|
||||
if r.BasePath == "" {
|
||||
r.BasePath = "/"
|
||||
}
|
||||
if r.Path == "" {
|
||||
r.Path = "docs"
|
||||
}
|
||||
if r.SpecURL == "" {
|
||||
r.SpecURL = "/swagger.json"
|
||||
}
|
||||
if r.RedocURL == "" {
|
||||
r.RedocURL = redocLatest
|
||||
}
|
||||
if r.Title == "" {
|
||||
r.Title = "API documentation"
|
||||
}
|
||||
}
|
||||
|
||||
// Redoc creates a middleware to serve a documentation site for a swagger spec.
|
||||
// This allows for altering the spec before starting the http listener.
|
||||
//
|
||||
func Redoc(opts RedocOpts, next http.Handler) http.Handler {
|
||||
opts.EnsureDefaults()
|
||||
|
||||
pth := path.Join(opts.BasePath, opts.Path)
|
||||
tmpl := template.Must(template.New("redoc").Parse(redocTemplate))
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
tmpl.Execute(buf, opts)
|
||||
b := buf.Bytes()
|
||||
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == pth {
|
||||
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
|
||||
rw.Write(b)
|
||||
return
|
||||
}
|
||||
|
||||
if next == nil {
|
||||
rw.Header().Set("Content-Type", "text/plain")
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
rw.Write([]byte(fmt.Sprintf("%q not found", pth)))
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(rw, r)
|
||||
})
|
||||
}
|
||||
|
||||
const (
|
||||
redocLatest = "https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js"
|
||||
redocTemplate = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ .Title }}</title>
|
||||
<!-- needed for adaptive design -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<!--
|
||||
ReDoc doesn't change outer page styles
|
||||
-->
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<redoc spec-url='{{ .SpecURL }}'></redoc>
|
||||
<script src="{{ .RedocURL }}"> </script>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
)
|
||||
22
vendor/github.com/go-openapi/runtime/middleware/redoc_test.go
generated
vendored
22
vendor/github.com/go-openapi/runtime/middleware/redoc_test.go
generated
vendored
@@ -1,22 +0,0 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRedocMiddleware(t *testing.T) {
|
||||
redoc := Redoc(RedocOpts{}, nil)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/docs", nil)
|
||||
recorder := httptest.NewRecorder()
|
||||
redoc.ServeHTTP(recorder, req)
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Equal(t, "text/html; charset=utf-8", recorder.Header().Get("Content-Type"))
|
||||
assert.Contains(t, recorder.Body.String(), "<title>API documentation</title>")
|
||||
assert.Contains(t, recorder.Body.String(), "<redoc spec-url='/swagger.json'></redoc>")
|
||||
assert.Contains(t, recorder.Body.String(), redocLatest)
|
||||
}
|
||||
104
vendor/github.com/go-openapi/runtime/middleware/request.go
generated
vendored
104
vendor/github.com/go-openapi/runtime/middleware/request.go
generated
vendored
@@ -1,104 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
// RequestBinder binds and validates the data from a http request
|
||||
type untypedRequestBinder struct {
|
||||
Spec *spec.Swagger
|
||||
Parameters map[string]spec.Parameter
|
||||
Formats strfmt.Registry
|
||||
paramBinders map[string]*untypedParamBinder
|
||||
}
|
||||
|
||||
// NewRequestBinder creates a new binder for reading a request.
|
||||
func newUntypedRequestBinder(parameters map[string]spec.Parameter, spec *spec.Swagger, formats strfmt.Registry) *untypedRequestBinder {
|
||||
binders := make(map[string]*untypedParamBinder)
|
||||
for fieldName, param := range parameters {
|
||||
binders[fieldName] = newUntypedParamBinder(param, spec, formats)
|
||||
}
|
||||
return &untypedRequestBinder{
|
||||
Parameters: parameters,
|
||||
paramBinders: binders,
|
||||
Spec: spec,
|
||||
Formats: formats,
|
||||
}
|
||||
}
|
||||
|
||||
// Bind perform the databinding and validation
|
||||
func (o *untypedRequestBinder) Bind(request *http.Request, routeParams RouteParams, consumer runtime.Consumer, data interface{}) error {
|
||||
val := reflect.Indirect(reflect.ValueOf(data))
|
||||
isMap := val.Kind() == reflect.Map
|
||||
var result []error
|
||||
debugLog("binding %d parameters for %s %s", len(o.Parameters), request.Method, request.URL.EscapedPath())
|
||||
for fieldName, param := range o.Parameters {
|
||||
binder := o.paramBinders[fieldName]
|
||||
debugLog("binding paramter %s for %s %s", fieldName, request.Method, request.URL.EscapedPath())
|
||||
var target reflect.Value
|
||||
if !isMap {
|
||||
binder.Name = fieldName
|
||||
target = val.FieldByName(fieldName)
|
||||
}
|
||||
|
||||
if isMap {
|
||||
tpe := binder.Type()
|
||||
if tpe == nil {
|
||||
if param.Schema.Type.Contains("array") {
|
||||
tpe = reflect.TypeOf([]interface{}{})
|
||||
} else {
|
||||
tpe = reflect.TypeOf(map[string]interface{}{})
|
||||
}
|
||||
}
|
||||
target = reflect.Indirect(reflect.New(tpe))
|
||||
|
||||
}
|
||||
|
||||
if !target.IsValid() {
|
||||
result = append(result, errors.New(500, "parameter name %q is an unknown field", binder.Name))
|
||||
continue
|
||||
}
|
||||
|
||||
if err := binder.Bind(request, routeParams, consumer, target); err != nil {
|
||||
result = append(result, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if binder.validator != nil {
|
||||
rr := binder.validator.Validate(target.Interface())
|
||||
if rr != nil && rr.HasErrors() {
|
||||
result = append(result, rr.AsError())
|
||||
}
|
||||
}
|
||||
|
||||
if isMap {
|
||||
val.SetMapIndex(reflect.ValueOf(param.Name), target)
|
||||
}
|
||||
}
|
||||
|
||||
if len(result) > 0 {
|
||||
return errors.CompositeValidationError(result...)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
481
vendor/github.com/go-openapi/runtime/middleware/request_test.go
generated
vendored
481
vendor/github.com/go-openapi/runtime/middleware/request_test.go
generated
vendored
@@ -1,481 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type stubConsumer struct {
|
||||
}
|
||||
|
||||
func (s *stubConsumer) Consume(_ io.Reader, _ interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type friend struct {
|
||||
Name string `json:"name"`
|
||||
Age int `json:"age"`
|
||||
}
|
||||
|
||||
type jsonRequestParams struct {
|
||||
ID int64 // path
|
||||
Name string // query
|
||||
Friend friend // body
|
||||
RequestID int64 // header
|
||||
Tags []string // csv
|
||||
}
|
||||
|
||||
type jsonRequestPtr struct {
|
||||
ID int64 // path
|
||||
Name string // query
|
||||
RequestID int64 // header
|
||||
Tags []string // csv
|
||||
Friend *friend
|
||||
}
|
||||
|
||||
type jsonRequestSlice struct {
|
||||
ID int64 // path
|
||||
Name string // query
|
||||
RequestID int64 // header
|
||||
Tags []string // csv
|
||||
Friend []friend
|
||||
}
|
||||
|
||||
type jsonRequestAllTypes struct {
|
||||
Confirmed bool
|
||||
Planned strfmt.Date
|
||||
Delivered strfmt.DateTime
|
||||
Age int32
|
||||
ID int64
|
||||
Score float32
|
||||
Factor float64
|
||||
Friend friend
|
||||
Name string
|
||||
Tags []string
|
||||
Picture []byte
|
||||
RequestID int64
|
||||
}
|
||||
|
||||
func parametersForAllTypes(fmt string) map[string]spec.Parameter {
|
||||
if fmt == "" {
|
||||
fmt = "csv"
|
||||
}
|
||||
nameParam := spec.QueryParam("name").Typed("string", "")
|
||||
idParam := spec.PathParam("id").Typed("integer", "int64")
|
||||
ageParam := spec.QueryParam("age").Typed("integer", "int32")
|
||||
scoreParam := spec.QueryParam("score").Typed("number", "float")
|
||||
factorParam := spec.QueryParam("factor").Typed("number", "double")
|
||||
|
||||
friendSchema := new(spec.Schema).Typed("object", "")
|
||||
friendParam := spec.BodyParam("friend", friendSchema)
|
||||
|
||||
requestIDParam := spec.HeaderParam("X-Request-Id").Typed("integer", "int64")
|
||||
requestIDParam.Extensions = spec.Extensions(map[string]interface{}{})
|
||||
requestIDParam.Extensions.Add("go-name", "RequestID")
|
||||
|
||||
items := new(spec.Items)
|
||||
items.Type = "string"
|
||||
tagsParam := spec.QueryParam("tags").CollectionOf(items, fmt)
|
||||
|
||||
confirmedParam := spec.QueryParam("confirmed").Typed("boolean", "")
|
||||
plannedParam := spec.QueryParam("planned").Typed("string", "date")
|
||||
deliveredParam := spec.QueryParam("delivered").Typed("string", "date-time")
|
||||
pictureParam := spec.QueryParam("picture").Typed("string", "byte") // base64 encoded during transport
|
||||
|
||||
return map[string]spec.Parameter{
|
||||
"ID": *idParam,
|
||||
"Name": *nameParam,
|
||||
"RequestID": *requestIDParam,
|
||||
"Friend": *friendParam,
|
||||
"Tags": *tagsParam,
|
||||
"Age": *ageParam,
|
||||
"Score": *scoreParam,
|
||||
"Factor": *factorParam,
|
||||
"Confirmed": *confirmedParam,
|
||||
"Planned": *plannedParam,
|
||||
"Delivered": *deliveredParam,
|
||||
"Picture": *pictureParam,
|
||||
}
|
||||
}
|
||||
|
||||
func parametersForJSONRequestParams(fmt string) map[string]spec.Parameter {
|
||||
if fmt == "" {
|
||||
fmt = "csv"
|
||||
}
|
||||
nameParam := spec.QueryParam("name").Typed("string", "")
|
||||
idParam := spec.PathParam("id").Typed("integer", "int64")
|
||||
|
||||
friendSchema := new(spec.Schema).Typed("object", "")
|
||||
friendParam := spec.BodyParam("friend", friendSchema)
|
||||
|
||||
requestIDParam := spec.HeaderParam("X-Request-Id").Typed("integer", "int64")
|
||||
requestIDParam.Extensions = spec.Extensions(map[string]interface{}{})
|
||||
requestIDParam.Extensions.Add("go-name", "RequestID")
|
||||
|
||||
items := new(spec.Items)
|
||||
items.Type = "string"
|
||||
tagsParam := spec.QueryParam("tags").CollectionOf(items, fmt)
|
||||
|
||||
return map[string]spec.Parameter{
|
||||
"ID": *idParam,
|
||||
"Name": *nameParam,
|
||||
"RequestID": *requestIDParam,
|
||||
"Friend": *friendParam,
|
||||
"Tags": *tagsParam,
|
||||
}
|
||||
}
|
||||
func parametersForJSONRequestSliceParams(fmt string) map[string]spec.Parameter {
|
||||
if fmt == "" {
|
||||
fmt = "csv"
|
||||
}
|
||||
nameParam := spec.QueryParam("name").Typed("string", "")
|
||||
idParam := spec.PathParam("id").Typed("integer", "int64")
|
||||
|
||||
friendSchema := new(spec.Schema).Typed("object", "")
|
||||
friendParam := spec.BodyParam("friend", spec.ArrayProperty(friendSchema))
|
||||
|
||||
requestIDParam := spec.HeaderParam("X-Request-Id").Typed("integer", "int64")
|
||||
requestIDParam.Extensions = spec.Extensions(map[string]interface{}{})
|
||||
requestIDParam.Extensions.Add("go-name", "RequestID")
|
||||
|
||||
items := new(spec.Items)
|
||||
items.Type = "string"
|
||||
tagsParam := spec.QueryParam("tags").CollectionOf(items, fmt)
|
||||
|
||||
return map[string]spec.Parameter{
|
||||
"ID": *idParam,
|
||||
"Name": *nameParam,
|
||||
"RequestID": *requestIDParam,
|
||||
"Friend": *friendParam,
|
||||
"Tags": *tagsParam,
|
||||
}
|
||||
}
|
||||
|
||||
func TestRequestBindingDefaultValue(t *testing.T) {
|
||||
confirmed := true
|
||||
name := "thomas"
|
||||
friend := map[string]interface{}{"name": "toby", "age": float64(32)}
|
||||
id, age, score, factor := int64(7575), int32(348), float32(5.309), float64(37.403)
|
||||
requestID := 19394858
|
||||
tags := []string{"one", "two", "three"}
|
||||
dt1 := time.Date(2014, 8, 9, 0, 0, 0, 0, time.UTC)
|
||||
planned := strfmt.Date(dt1)
|
||||
dt2 := time.Date(2014, 10, 12, 8, 5, 5, 0, time.UTC)
|
||||
delivered := strfmt.DateTime(dt2)
|
||||
uri, _ := url.Parse("http://localhost:8002/hello")
|
||||
defaults := map[string]interface{}{
|
||||
"id": id,
|
||||
"age": age,
|
||||
"score": score,
|
||||
"factor": factor,
|
||||
"name": name,
|
||||
"friend": friend,
|
||||
"X-Request-Id": requestID,
|
||||
"tags": tags,
|
||||
"confirmed": confirmed,
|
||||
"planned": planned,
|
||||
"delivered": delivered,
|
||||
"picture": []byte("hello"),
|
||||
}
|
||||
op2 := parametersForAllTypes("")
|
||||
op3 := make(map[string]spec.Parameter)
|
||||
for k, p := range op2 {
|
||||
p.Default = defaults[p.Name]
|
||||
op3[k] = p
|
||||
}
|
||||
|
||||
req, _ := http.NewRequest("POST", uri.String(), bytes.NewBuffer(nil))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
binder := newUntypedRequestBinder(op3, new(spec.Swagger), strfmt.Default)
|
||||
|
||||
data := make(map[string]interface{})
|
||||
err := binder.Bind(req, RouteParams(nil), runtime.JSONConsumer(), &data)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, defaults["id"], data["id"])
|
||||
assert.Equal(t, name, data["name"])
|
||||
assert.Equal(t, friend, data["friend"])
|
||||
assert.EqualValues(t, requestID, data["X-Request-Id"])
|
||||
assert.Equal(t, tags, data["tags"])
|
||||
assert.Equal(t, planned, data["planned"])
|
||||
assert.Equal(t, delivered, data["delivered"])
|
||||
assert.Equal(t, confirmed, data["confirmed"])
|
||||
assert.Equal(t, age, data["age"])
|
||||
assert.Equal(t, factor, data["factor"])
|
||||
assert.Equal(t, score, data["score"])
|
||||
assert.Equal(t, "hello", string(data["picture"].(strfmt.Base64)))
|
||||
}
|
||||
|
||||
func TestRequestBindingForInvalid(t *testing.T) {
|
||||
|
||||
invalidParam := spec.QueryParam("some")
|
||||
|
||||
op1 := map[string]spec.Parameter{"Some": *invalidParam}
|
||||
|
||||
binder := newUntypedRequestBinder(op1, new(spec.Swagger), strfmt.Default)
|
||||
req, _ := http.NewRequest("GET", "http://localhost:8002/hello?name=the-name", nil)
|
||||
|
||||
err := binder.Bind(req, nil, new(stubConsumer), new(jsonRequestParams))
|
||||
assert.Error(t, err)
|
||||
|
||||
op2 := parametersForJSONRequestParams("")
|
||||
binder = newUntypedRequestBinder(op2, new(spec.Swagger), strfmt.Default)
|
||||
|
||||
req, _ = http.NewRequest("POST", "http://localhost:8002/hello/1?name=the-name", bytes.NewBuffer([]byte(`{"name":"toby","age":32}`)))
|
||||
req.Header.Set("Content-Type", "application(")
|
||||
data := jsonRequestParams{}
|
||||
err = binder.Bind(req, RouteParams([]RouteParam{{"id", "1"}}), runtime.JSONConsumer(), &data)
|
||||
assert.Error(t, err)
|
||||
|
||||
req, _ = http.NewRequest("POST", "http://localhost:8002/hello/1?name=the-name", bytes.NewBuffer([]byte(`{]`)))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
data = jsonRequestParams{}
|
||||
err = binder.Bind(req, RouteParams([]RouteParam{{"id", "1"}}), runtime.JSONConsumer(), &data)
|
||||
assert.Error(t, err)
|
||||
|
||||
invalidMultiParam := spec.HeaderParam("tags").CollectionOf(new(spec.Items), "multi")
|
||||
op3 := map[string]spec.Parameter{"Tags": *invalidMultiParam}
|
||||
binder = newUntypedRequestBinder(op3, new(spec.Swagger), strfmt.Default)
|
||||
|
||||
req, _ = http.NewRequest("POST", "http://localhost:8002/hello/1?name=the-name", bytes.NewBuffer([]byte(`{}`)))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
data = jsonRequestParams{}
|
||||
err = binder.Bind(req, RouteParams([]RouteParam{{"id", "1"}}), runtime.JSONConsumer(), &data)
|
||||
assert.Error(t, err)
|
||||
|
||||
invalidMultiParam = spec.PathParam("").CollectionOf(new(spec.Items), "multi")
|
||||
|
||||
op4 := map[string]spec.Parameter{"Tags": *invalidMultiParam}
|
||||
binder = newUntypedRequestBinder(op4, new(spec.Swagger), strfmt.Default)
|
||||
|
||||
req, _ = http.NewRequest("POST", "http://localhost:8002/hello/1?name=the-name", bytes.NewBuffer([]byte(`{}`)))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
data = jsonRequestParams{}
|
||||
err = binder.Bind(req, RouteParams([]RouteParam{{"id", "1"}}), runtime.JSONConsumer(), &data)
|
||||
assert.Error(t, err)
|
||||
|
||||
invalidInParam := spec.HeaderParam("tags").Typed("string", "")
|
||||
invalidInParam.In = "invalid"
|
||||
op5 := map[string]spec.Parameter{"Tags": *invalidInParam}
|
||||
binder = newUntypedRequestBinder(op5, new(spec.Swagger), strfmt.Default)
|
||||
|
||||
req, _ = http.NewRequest("POST", "http://localhost:8002/hello/1?name=the-name", bytes.NewBuffer([]byte(`{}`)))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
data = jsonRequestParams{}
|
||||
err = binder.Bind(req, RouteParams([]RouteParam{{"id", "1"}}), runtime.JSONConsumer(), &data)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestRequestBindingForValid(t *testing.T) {
|
||||
|
||||
for _, fmt := range []string{"csv", "pipes", "tsv", "ssv", "multi"} {
|
||||
op1 := parametersForJSONRequestParams(fmt)
|
||||
|
||||
binder := newUntypedRequestBinder(op1, new(spec.Swagger), strfmt.Default)
|
||||
|
||||
lval := []string{"one", "two", "three"}
|
||||
queryString := ""
|
||||
switch fmt {
|
||||
case "multi":
|
||||
queryString = strings.Join(lval, "&tags=")
|
||||
case "ssv":
|
||||
queryString = strings.Join(lval, " ")
|
||||
case "pipes":
|
||||
queryString = strings.Join(lval, "|")
|
||||
case "tsv":
|
||||
queryString = strings.Join(lval, "\t")
|
||||
default:
|
||||
queryString = strings.Join(lval, ",")
|
||||
}
|
||||
|
||||
urlStr := "http://localhost:8002/hello/1?name=the-name&tags=" + queryString
|
||||
|
||||
req, _ := http.NewRequest("POST", urlStr, bytes.NewBuffer([]byte(`{"name":"toby","age":32}`)))
|
||||
req.Header.Set("Content-Type", "application/json;charset=utf-8")
|
||||
req.Header.Set("X-Request-Id", "1325959595")
|
||||
|
||||
data := jsonRequestParams{}
|
||||
err := binder.Bind(req, RouteParams([]RouteParam{{"id", "1"}}), runtime.JSONConsumer(), &data)
|
||||
|
||||
expected := jsonRequestParams{
|
||||
ID: 1,
|
||||
Name: "the-name",
|
||||
Friend: friend{"toby", 32},
|
||||
RequestID: 1325959595,
|
||||
Tags: []string{"one", "two", "three"},
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, data)
|
||||
}
|
||||
|
||||
op1 := parametersForJSONRequestParams("")
|
||||
|
||||
binder := newUntypedRequestBinder(op1, new(spec.Swagger), strfmt.Default)
|
||||
urlStr := "http://localhost:8002/hello/1?name=the-name&tags=one,two,three"
|
||||
req, _ := http.NewRequest("POST", urlStr, bytes.NewBuffer([]byte(`{"name":"toby","age":32}`)))
|
||||
req.Header.Set("Content-Type", "application/json;charset=utf-8")
|
||||
req.Header.Set("X-Request-Id", "1325959595")
|
||||
|
||||
data2 := jsonRequestPtr{}
|
||||
err := binder.Bind(req, []RouteParam{{"id", "1"}}, runtime.JSONConsumer(), &data2)
|
||||
|
||||
expected2 := jsonRequestPtr{
|
||||
Friend: &friend{"toby", 32},
|
||||
Tags: []string{"one", "two", "three"},
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
if data2.Friend == nil {
|
||||
t.Fatal("friend is nil")
|
||||
}
|
||||
assert.Equal(t, *expected2.Friend, *data2.Friend)
|
||||
assert.Equal(t, expected2.Tags, data2.Tags)
|
||||
|
||||
req, _ = http.NewRequest("POST", urlStr, bytes.NewBuffer([]byte(`[{"name":"toby","age":32}]`)))
|
||||
req.Header.Set("Content-Type", "application/json;charset=utf-8")
|
||||
req.Header.Set("X-Request-Id", "1325959595")
|
||||
op2 := parametersForJSONRequestSliceParams("")
|
||||
binder = newUntypedRequestBinder(op2, new(spec.Swagger), strfmt.Default)
|
||||
data3 := jsonRequestSlice{}
|
||||
err = binder.Bind(req, []RouteParam{{"id", "1"}}, runtime.JSONConsumer(), &data3)
|
||||
|
||||
expected3 := jsonRequestSlice{
|
||||
Friend: []friend{{"toby", 32}},
|
||||
Tags: []string{"one", "two", "three"},
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected3.Friend, data3.Friend)
|
||||
assert.Equal(t, expected3.Tags, data3.Tags)
|
||||
}
|
||||
|
||||
type formRequest struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
|
||||
func parametersForFormUpload() map[string]spec.Parameter {
|
||||
nameParam := spec.FormDataParam("name").Typed("string", "")
|
||||
|
||||
ageParam := spec.FormDataParam("age").Typed("integer", "int32")
|
||||
|
||||
return map[string]spec.Parameter{"Name": *nameParam, "Age": *ageParam}
|
||||
}
|
||||
|
||||
func TestFormUpload(t *testing.T) {
|
||||
params := parametersForFormUpload()
|
||||
binder := newUntypedRequestBinder(params, new(spec.Swagger), strfmt.Default)
|
||||
|
||||
urlStr := "http://localhost:8002/hello"
|
||||
req, _ := http.NewRequest("POST", urlStr, bytes.NewBufferString(`name=the-name&age=32`))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
data := formRequest{}
|
||||
res := binder.Bind(req, nil, runtime.JSONConsumer(), &data)
|
||||
assert.NoError(t, res)
|
||||
assert.Equal(t, "the-name", data.Name)
|
||||
assert.Equal(t, 32, data.Age)
|
||||
|
||||
req, _ = http.NewRequest("POST", urlStr, bytes.NewBufferString(`name=%3&age=32`))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
data = formRequest{}
|
||||
assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data))
|
||||
}
|
||||
|
||||
type fileRequest struct {
|
||||
Name string // body
|
||||
File runtime.File // upload
|
||||
}
|
||||
|
||||
func paramsForFileUpload() *untypedRequestBinder {
|
||||
nameParam := spec.FormDataParam("name").Typed("string", "")
|
||||
|
||||
fileParam := spec.FileParam("file")
|
||||
|
||||
params := map[string]spec.Parameter{"Name": *nameParam, "File": *fileParam}
|
||||
return newUntypedRequestBinder(params, new(spec.Swagger), strfmt.Default)
|
||||
}
|
||||
|
||||
func TestBindingFileUpload(t *testing.T) {
|
||||
binder := paramsForFileUpload()
|
||||
|
||||
body := bytes.NewBuffer(nil)
|
||||
writer := multipart.NewWriter(body)
|
||||
part, err := writer.CreateFormFile("file", "plain-jane.txt")
|
||||
assert.NoError(t, err)
|
||||
|
||||
part.Write([]byte("the file contents"))
|
||||
writer.WriteField("name", "the-name")
|
||||
assert.NoError(t, writer.Close())
|
||||
|
||||
urlStr := "http://localhost:8002/hello"
|
||||
req, _ := http.NewRequest("POST", urlStr, body)
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
data := fileRequest{}
|
||||
assert.NoError(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data))
|
||||
assert.Equal(t, "the-name", data.Name)
|
||||
assert.NotNil(t, data.File)
|
||||
assert.NotNil(t, data.File.Header)
|
||||
assert.Equal(t, "plain-jane.txt", data.File.Header.Filename)
|
||||
|
||||
bb, err := ioutil.ReadAll(data.File.Data)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("the file contents"), bb)
|
||||
|
||||
req, _ = http.NewRequest("POST", urlStr, body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
data = fileRequest{}
|
||||
assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data))
|
||||
|
||||
req, _ = http.NewRequest("POST", urlStr, body)
|
||||
req.Header.Set("Content-Type", "application(")
|
||||
data = fileRequest{}
|
||||
assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data))
|
||||
|
||||
body = bytes.NewBuffer(nil)
|
||||
writer = multipart.NewWriter(body)
|
||||
part, err = writer.CreateFormFile("bad-name", "plain-jane.txt")
|
||||
assert.NoError(t, err)
|
||||
|
||||
part.Write([]byte("the file contents"))
|
||||
writer.WriteField("name", "the-name")
|
||||
assert.NoError(t, writer.Close())
|
||||
req, _ = http.NewRequest("POST", urlStr, body)
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
data = fileRequest{}
|
||||
assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data))
|
||||
|
||||
req, _ = http.NewRequest("POST", urlStr, body)
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
req.MultipartReader()
|
||||
|
||||
data = fileRequest{}
|
||||
assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data))
|
||||
|
||||
}
|
||||
38
vendor/github.com/go-openapi/runtime/middleware/route_param_test.go
generated
vendored
38
vendor/github.com/go-openapi/runtime/middleware/route_param_test.go
generated
vendored
@@ -1,38 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRouteParams(t *testing.T) {
|
||||
coll1 := RouteParams([]RouteParam{
|
||||
{"blah", "foo"},
|
||||
{"abc", "bar"},
|
||||
{"ccc", "efg"},
|
||||
})
|
||||
|
||||
v := coll1.Get("blah")
|
||||
assert.Equal(t, v, "foo")
|
||||
v2 := coll1.Get("abc")
|
||||
assert.Equal(t, v2, "bar")
|
||||
v3 := coll1.Get("ccc")
|
||||
assert.Equal(t, v3, "efg")
|
||||
v4 := coll1.Get("ydkdk")
|
||||
assert.Empty(t, v4)
|
||||
}
|
||||
262
vendor/github.com/go-openapi/runtime/middleware/router.go
generated
vendored
262
vendor/github.com/go-openapi/runtime/middleware/router.go
generated
vendored
@@ -1,262 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
fpath "path"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware/denco"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/gorilla/context"
|
||||
)
|
||||
|
||||
// RouteParam is a object to capture route params in a framework agnostic way.
|
||||
// implementations of the muxer should use these route params to communicate with the
|
||||
// swagger framework
|
||||
type RouteParam struct {
|
||||
Name string
|
||||
Value string
|
||||
}
|
||||
|
||||
// RouteParams the collection of route params
|
||||
type RouteParams []RouteParam
|
||||
|
||||
// Get gets the value for the route param for the specified key
|
||||
func (r RouteParams) Get(name string) string {
|
||||
vv, _, _ := r.GetOK(name)
|
||||
if len(vv) > 0 {
|
||||
return vv[len(vv)-1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetOK gets the value but also returns booleans to indicate if a key or value
|
||||
// is present. This aids in validation and satisfies an interface in use there
|
||||
//
|
||||
// The returned values are: data, has key, has value
|
||||
func (r RouteParams) GetOK(name string) ([]string, bool, bool) {
|
||||
for _, p := range r {
|
||||
if p.Name == name {
|
||||
return []string{p.Value}, true, p.Value != ""
|
||||
}
|
||||
}
|
||||
return nil, false, false
|
||||
}
|
||||
|
||||
// NewRouter creates a new context aware router middleware
|
||||
func NewRouter(ctx *Context, next http.Handler) http.Handler {
|
||||
if ctx.router == nil {
|
||||
ctx.router = DefaultRouter(ctx.spec, ctx.api)
|
||||
}
|
||||
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
defer context.Clear(r)
|
||||
if _, ok := ctx.RouteInfo(r); ok {
|
||||
next.ServeHTTP(rw, r)
|
||||
return
|
||||
}
|
||||
|
||||
// Not found, check if it exists in the other methods first
|
||||
if others := ctx.AllowedMethods(r); len(others) > 0 {
|
||||
ctx.Respond(rw, r, ctx.analyzer.RequiredProduces(), nil, errors.MethodNotAllowed(r.Method, others))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Respond(rw, r, ctx.analyzer.RequiredProduces(), nil, errors.NotFound("path %s was not found", r.URL.EscapedPath()))
|
||||
})
|
||||
}
|
||||
|
||||
// RoutableAPI represents an interface for things that can serve
|
||||
// as a provider of implementations for the swagger router
|
||||
type RoutableAPI interface {
|
||||
HandlerFor(string, string) (http.Handler, bool)
|
||||
ServeErrorFor(string) func(http.ResponseWriter, *http.Request, error)
|
||||
ConsumersFor([]string) map[string]runtime.Consumer
|
||||
ProducersFor([]string) map[string]runtime.Producer
|
||||
AuthenticatorsFor(map[string]spec.SecurityScheme) map[string]runtime.Authenticator
|
||||
Formats() strfmt.Registry
|
||||
DefaultProduces() string
|
||||
DefaultConsumes() string
|
||||
}
|
||||
|
||||
// Router represents a swagger aware router
|
||||
type Router interface {
|
||||
Lookup(method, path string) (*MatchedRoute, bool)
|
||||
OtherMethods(method, path string) []string
|
||||
}
|
||||
|
||||
type defaultRouteBuilder struct {
|
||||
spec *loads.Document
|
||||
analyzer *analysis.Spec
|
||||
api RoutableAPI
|
||||
records map[string][]denco.Record
|
||||
}
|
||||
|
||||
type defaultRouter struct {
|
||||
spec *loads.Document
|
||||
api RoutableAPI
|
||||
routers map[string]*denco.Router
|
||||
}
|
||||
|
||||
func newDefaultRouteBuilder(spec *loads.Document, api RoutableAPI) *defaultRouteBuilder {
|
||||
return &defaultRouteBuilder{
|
||||
spec: spec,
|
||||
analyzer: analysis.New(spec.Spec()),
|
||||
api: api,
|
||||
records: make(map[string][]denco.Record),
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultRouter creates a default implemenation of the router
|
||||
func DefaultRouter(spec *loads.Document, api RoutableAPI) Router {
|
||||
builder := newDefaultRouteBuilder(spec, api)
|
||||
if spec != nil {
|
||||
for method, paths := range builder.analyzer.Operations() {
|
||||
for path, operation := range paths {
|
||||
fp := fpath.Join(spec.BasePath(), path)
|
||||
debugLog("adding route %s %s %q", method, fp, operation.ID)
|
||||
builder.AddRoute(method, fp, operation)
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder.Build()
|
||||
}
|
||||
|
||||
type routeEntry struct {
|
||||
PathPattern string
|
||||
BasePath string
|
||||
Operation *spec.Operation
|
||||
Consumes []string
|
||||
Consumers map[string]runtime.Consumer
|
||||
Produces []string
|
||||
Producers map[string]runtime.Producer
|
||||
Parameters map[string]spec.Parameter
|
||||
Handler http.Handler
|
||||
Formats strfmt.Registry
|
||||
Binder *untypedRequestBinder
|
||||
Authenticators map[string]runtime.Authenticator
|
||||
Scopes map[string][]string
|
||||
}
|
||||
|
||||
// MatchedRoute represents the route that was matched in this request
|
||||
type MatchedRoute struct {
|
||||
routeEntry
|
||||
Params RouteParams
|
||||
Consumer runtime.Consumer
|
||||
Producer runtime.Producer
|
||||
}
|
||||
|
||||
func (d *defaultRouter) Lookup(method, path string) (*MatchedRoute, bool) {
|
||||
mth := strings.ToUpper(method)
|
||||
debugLog("looking up route for %s %s", method, path)
|
||||
if Debug {
|
||||
if len(d.routers) == 0 {
|
||||
debugLog("there are no known routers")
|
||||
}
|
||||
for meth := range d.routers {
|
||||
debugLog("got a router for %s", meth)
|
||||
}
|
||||
}
|
||||
if router, ok := d.routers[mth]; ok {
|
||||
if m, rp, ok := router.Lookup(path); ok && m != nil {
|
||||
if entry, ok := m.(*routeEntry); ok {
|
||||
debugLog("found a route for %s %s with %d parameters", method, path, len(entry.Parameters))
|
||||
var params RouteParams
|
||||
for _, p := range rp {
|
||||
params = append(params, RouteParam{Name: p.Name, Value: p.Value})
|
||||
}
|
||||
return &MatchedRoute{routeEntry: *entry, Params: params}, true
|
||||
}
|
||||
} else {
|
||||
debugLog("couldn't find a route by path for %s %s", method, path)
|
||||
}
|
||||
} else {
|
||||
debugLog("couldn't find a route by method for %s %s", method, path)
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (d *defaultRouter) OtherMethods(method, path string) []string {
|
||||
mn := strings.ToUpper(method)
|
||||
var methods []string
|
||||
for k, v := range d.routers {
|
||||
if k != mn {
|
||||
if _, _, ok := v.Lookup(path); ok {
|
||||
methods = append(methods, k)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return methods
|
||||
}
|
||||
|
||||
var pathConverter = regexp.MustCompile(`{(\w+)}`)
|
||||
|
||||
func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Operation) {
|
||||
mn := strings.ToUpper(method)
|
||||
|
||||
bp := fpath.Clean(d.spec.BasePath())
|
||||
if len(bp) > 0 && bp[len(bp)-1] == '/' {
|
||||
bp = bp[:len(bp)-1]
|
||||
}
|
||||
|
||||
if handler, ok := d.api.HandlerFor(method, strings.TrimPrefix(path, bp)); ok {
|
||||
consumes := d.analyzer.ConsumesFor(operation)
|
||||
produces := d.analyzer.ProducesFor(operation)
|
||||
parameters := d.analyzer.ParamsFor(method, strings.TrimPrefix(path, bp))
|
||||
definitions := d.analyzer.SecurityDefinitionsFor(operation)
|
||||
requirements := d.analyzer.SecurityRequirementsFor(operation)
|
||||
scopes := make(map[string][]string, len(requirements))
|
||||
for _, v := range requirements {
|
||||
scopes[v.Name] = v.Scopes
|
||||
}
|
||||
|
||||
record := denco.NewRecord(pathConverter.ReplaceAllString(path, ":$1"), &routeEntry{
|
||||
Operation: operation,
|
||||
Handler: handler,
|
||||
Consumes: consumes,
|
||||
Produces: produces,
|
||||
Consumers: d.api.ConsumersFor(consumes),
|
||||
Producers: d.api.ProducersFor(produces),
|
||||
Parameters: parameters,
|
||||
Formats: d.api.Formats(),
|
||||
Binder: newUntypedRequestBinder(parameters, d.spec.Spec(), d.api.Formats()),
|
||||
Authenticators: d.api.AuthenticatorsFor(definitions),
|
||||
Scopes: scopes,
|
||||
})
|
||||
d.records[mn] = append(d.records[mn], record)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *defaultRouteBuilder) Build() *defaultRouter {
|
||||
routers := make(map[string]*denco.Router)
|
||||
for method, records := range d.records {
|
||||
router := denco.New()
|
||||
router.Build(records)
|
||||
routers[method] = router
|
||||
}
|
||||
return &defaultRouter{
|
||||
spec: d.spec,
|
||||
routers: routers,
|
||||
}
|
||||
}
|
||||
206
vendor/github.com/go-openapi/runtime/middleware/router_test.go
generated
vendored
206
vendor/github.com/go-openapi/runtime/middleware/router_test.go
generated
vendored
@@ -1,206 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/runtime/internal/testing/petstore"
|
||||
"github.com/go-openapi/runtime/middleware/untyped"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func terminator(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func TestRouterMiddleware(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
context := NewContext(spec, api, nil)
|
||||
mw := NewRouter(context, http.HandlerFunc(terminator))
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
request, _ := http.NewRequest("GET", "/api/pets", nil)
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("DELETE", "/api/pets", nil)
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, http.StatusMethodNotAllowed, recorder.Code)
|
||||
|
||||
methods := strings.Split(recorder.Header().Get("Allow"), ",")
|
||||
sort.Sort(sort.StringSlice(methods))
|
||||
assert.Equal(t, "GET,POST", strings.Join(methods, ","))
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("GET", "/nopets", nil)
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, http.StatusNotFound, recorder.Code)
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("GET", "/pets", nil)
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, http.StatusNotFound, recorder.Code)
|
||||
|
||||
spec, api = petstore.NewRootAPI(t)
|
||||
context = NewContext(spec, api, nil)
|
||||
mw = NewRouter(context, http.HandlerFunc(terminator))
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("GET", "/pets", nil)
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("DELETE", "/pets", nil)
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, http.StatusMethodNotAllowed, recorder.Code)
|
||||
|
||||
methods = strings.Split(recorder.Header().Get("Allow"), ",")
|
||||
sort.Sort(sort.StringSlice(methods))
|
||||
assert.Equal(t, "GET,POST", strings.Join(methods, ","))
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("GET", "/nopets", nil)
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, http.StatusNotFound, recorder.Code)
|
||||
|
||||
}
|
||||
|
||||
func TestRouterBuilder(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
analyzed := analysis.New(spec.Spec())
|
||||
|
||||
assert.Len(t, analyzed.RequiredConsumes(), 3)
|
||||
assert.Len(t, analyzed.RequiredProduces(), 5)
|
||||
assert.Len(t, analyzed.OperationIDs(), 4)
|
||||
|
||||
// context := NewContext(spec, api)
|
||||
builder := petAPIRouterBuilder(spec, api, analyzed)
|
||||
getRecords := builder.records["GET"]
|
||||
postRecords := builder.records["POST"]
|
||||
deleteRecords := builder.records["DELETE"]
|
||||
|
||||
assert.Len(t, getRecords, 2)
|
||||
assert.Len(t, postRecords, 1)
|
||||
assert.Len(t, deleteRecords, 1)
|
||||
|
||||
assert.Empty(t, builder.records["PATCH"])
|
||||
assert.Empty(t, builder.records["OPTIONS"])
|
||||
assert.Empty(t, builder.records["HEAD"])
|
||||
assert.Empty(t, builder.records["PUT"])
|
||||
|
||||
rec := postRecords[0]
|
||||
assert.Equal(t, rec.Key, "/pets")
|
||||
val := rec.Value.(*routeEntry)
|
||||
assert.Len(t, val.Consumers, 1)
|
||||
assert.Len(t, val.Producers, 1)
|
||||
assert.Len(t, val.Consumes, 1)
|
||||
assert.Len(t, val.Produces, 1)
|
||||
|
||||
assert.Len(t, val.Parameters, 1)
|
||||
|
||||
recG := getRecords[0]
|
||||
assert.Equal(t, recG.Key, "/pets")
|
||||
valG := recG.Value.(*routeEntry)
|
||||
assert.Len(t, valG.Consumers, 2)
|
||||
assert.Len(t, valG.Producers, 4)
|
||||
assert.Len(t, valG.Consumes, 2)
|
||||
assert.Len(t, valG.Produces, 4)
|
||||
|
||||
assert.Len(t, valG.Parameters, 2)
|
||||
}
|
||||
|
||||
func TestRouterCanonicalBasePath(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
spec.Spec().BasePath = "/api///"
|
||||
context := NewContext(spec, api, nil)
|
||||
mw := NewRouter(context, http.HandlerFunc(terminator))
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
request, _ := http.NewRequest("GET", "/api/pets", nil)
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
}
|
||||
|
||||
func TestRouter_EscapedPath(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
spec.Spec().BasePath = "/api/"
|
||||
context := NewContext(spec, api, nil)
|
||||
mw := NewRouter(context, http.HandlerFunc(terminator))
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
request, _ := http.NewRequest("GET", "/api/pets/123", nil)
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("GET", "/api/pets/abc%2Fdef", nil)
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
ri, _ := context.RouteInfo(request)
|
||||
if assert.NotNil(t, ri) {
|
||||
if assert.NotNil(t, ri.Params) {
|
||||
assert.Equal(t, "abc%2Fdef", ri.Params.Get("id"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRouterStruct(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
router := DefaultRouter(spec, newRoutableUntypedAPI(spec, api, new(Context)))
|
||||
|
||||
methods := router.OtherMethods("post", "/api/pets/{id}")
|
||||
assert.Len(t, methods, 2)
|
||||
|
||||
entry, ok := router.Lookup("delete", "/api/pets/{id}")
|
||||
assert.True(t, ok)
|
||||
assert.NotNil(t, entry)
|
||||
assert.Len(t, entry.Params, 1)
|
||||
assert.Equal(t, "id", entry.Params[0].Name)
|
||||
|
||||
_, ok = router.Lookup("delete", "/pets")
|
||||
assert.False(t, ok)
|
||||
|
||||
_, ok = router.Lookup("post", "/no-pets")
|
||||
assert.False(t, ok)
|
||||
}
|
||||
|
||||
func petAPIRouterBuilder(spec *loads.Document, api *untyped.API, analyzed *analysis.Spec) *defaultRouteBuilder {
|
||||
builder := newDefaultRouteBuilder(spec, newRoutableUntypedAPI(spec, api, new(Context)))
|
||||
builder.AddRoute("GET", "/pets", analyzed.AllPaths()["/pets"].Get)
|
||||
builder.AddRoute("POST", "/pets", analyzed.AllPaths()["/pets"].Post)
|
||||
builder.AddRoute("DELETE", "/pets/{id}", analyzed.AllPaths()["/pets/{id}"].Delete)
|
||||
builder.AddRoute("GET", "/pets/{id}", analyzed.AllPaths()["/pets/{id}"].Get)
|
||||
|
||||
return builder
|
||||
}
|
||||
34
vendor/github.com/go-openapi/runtime/middleware/security.go
generated
vendored
34
vendor/github.com/go-openapi/runtime/middleware/security.go
generated
vendored
@@ -1,34 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import "net/http"
|
||||
|
||||
func newSecureAPI(ctx *Context, next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
route, _ := ctx.RouteInfo(r)
|
||||
if route != nil && len(route.Authenticators) == 0 {
|
||||
next.ServeHTTP(rw, r)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := ctx.Authorize(r, route); err != nil {
|
||||
ctx.Respond(rw, r, route.Produces, route, err)
|
||||
return
|
||||
}
|
||||
|
||||
next.ServeHTTP(rw, r)
|
||||
})
|
||||
}
|
||||
58
vendor/github.com/go-openapi/runtime/middleware/security_test.go
generated
vendored
58
vendor/github.com/go-openapi/runtime/middleware/security_test.go
generated
vendored
@@ -1,58 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/runtime/internal/testing/petstore"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSecurityMiddleware(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
context := NewContext(spec, api, nil)
|
||||
context.router = DefaultRouter(spec, context.api)
|
||||
mw := newSecureAPI(context, http.HandlerFunc(terminator))
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
request, _ := http.NewRequest("GET", "/api/pets", nil)
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 401, recorder.Code)
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("GET", "/api/pets", nil)
|
||||
request.SetBasicAuth("admin", "wrong")
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 401, recorder.Code)
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("GET", "/api/pets", nil)
|
||||
request.SetBasicAuth("admin", "admin")
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("GET", "//apipets/1", nil)
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
|
||||
}
|
||||
47
vendor/github.com/go-openapi/runtime/middleware/spec.go
generated
vendored
47
vendor/github.com/go-openapi/runtime/middleware/spec.go
generated
vendored
@@ -1,47 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"path"
|
||||
)
|
||||
|
||||
// Spec creates a middleware to serve a swagger spec.
|
||||
// This allows for altering the spec before starting the http listener.
|
||||
// This can be useful if you want to serve the swagger spec from another path than /swagger.json
|
||||
//
|
||||
func Spec(basePath string, b []byte, next http.Handler) http.Handler {
|
||||
if basePath == "" {
|
||||
basePath = "/"
|
||||
}
|
||||
pth := path.Join(basePath, "swagger.json")
|
||||
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == pth {
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
rw.Write(b)
|
||||
return
|
||||
}
|
||||
|
||||
if next == nil {
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(rw, r)
|
||||
})
|
||||
}
|
||||
56
vendor/github.com/go-openapi/runtime/middleware/spec_test.go
generated
vendored
56
vendor/github.com/go-openapi/runtime/middleware/spec_test.go
generated
vendored
@@ -1,56 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/internal/testing/petstore"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestServeSpecMiddleware(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
ctx := NewContext(spec, api, nil)
|
||||
|
||||
handler := Spec("", ctx.spec.Raw(), nil)
|
||||
// serves spec
|
||||
request, _ := http.NewRequest("GET", "/swagger.json", nil)
|
||||
request.Header.Add(runtime.HeaderContentType, runtime.JSONMime)
|
||||
recorder := httptest.NewRecorder()
|
||||
handler.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
|
||||
// returns 404 when no next handler
|
||||
request, _ = http.NewRequest("GET", "/api/pets", nil)
|
||||
request.Header.Add(runtime.HeaderContentType, runtime.JSONMime)
|
||||
recorder = httptest.NewRecorder()
|
||||
handler.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 404, recorder.Code)
|
||||
|
||||
// forwards to next handler for other url
|
||||
handler = Spec("", ctx.spec.Raw(), http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
request, _ = http.NewRequest("GET", "/api/pets", nil)
|
||||
request.Header.Add(runtime.HeaderContentType, runtime.JSONMime)
|
||||
recorder = httptest.NewRecorder()
|
||||
handler.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
|
||||
}
|
||||
301
vendor/github.com/go-openapi/runtime/middleware/string_conversion_test.go
generated
vendored
301
vendor/github.com/go-openapi/runtime/middleware/string_conversion_test.go
generated
vendored
@@ -1,301 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var evaluatesAsTrue = []string{"true", "1", "yes", "ok", "y", "on", "selected", "checked", "t", "enabled"}
|
||||
|
||||
type unmarshallerSlice []string
|
||||
|
||||
func (u *unmarshallerSlice) UnmarshalText(data []byte) error {
|
||||
if len(data) == 0 {
|
||||
return errors.New("an error")
|
||||
}
|
||||
*u = strings.Split(string(data), ",")
|
||||
return nil
|
||||
}
|
||||
|
||||
type SomeOperationParams struct {
|
||||
Name string
|
||||
ID int64
|
||||
Confirmed bool
|
||||
Age int
|
||||
Visits int32
|
||||
Count int16
|
||||
Seq int8
|
||||
UID uint64
|
||||
UAge uint
|
||||
UVisits uint32
|
||||
UCount uint16
|
||||
USeq uint8
|
||||
Score float32
|
||||
Rate float64
|
||||
Timestamp strfmt.DateTime
|
||||
Birthdate strfmt.Date
|
||||
LastFailure *strfmt.DateTime
|
||||
Unsupported struct{}
|
||||
Tags []string
|
||||
Prefs []int32
|
||||
Categories unmarshallerSlice
|
||||
}
|
||||
|
||||
func FloatParamTest(t *testing.T, fName, pName, format string, val reflect.Value, defVal, expectedDef interface{}, actual func() interface{}) {
|
||||
fld := val.FieldByName(pName)
|
||||
binder := &untypedParamBinder{
|
||||
parameter: spec.QueryParam(pName).Typed("number", "double").WithDefault(defVal),
|
||||
Name: pName,
|
||||
}
|
||||
|
||||
err := binder.setFieldValue(fld, defVal, "5", true)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 5, actual())
|
||||
|
||||
err = binder.setFieldValue(fld, defVal, "", true)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, expectedDef, actual())
|
||||
|
||||
err = binder.setFieldValue(fld, defVal, "yada", true)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func IntParamTest(t *testing.T, pName string, val reflect.Value, defVal, expectedDef interface{}, actual func() interface{}) {
|
||||
fld := val.FieldByName(pName)
|
||||
|
||||
binder := &untypedParamBinder{
|
||||
parameter: spec.QueryParam(pName).Typed("integer", "int64").WithDefault(defVal),
|
||||
Name: pName,
|
||||
}
|
||||
err := binder.setFieldValue(fld, defVal, "5", true)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 5, actual())
|
||||
|
||||
err = binder.setFieldValue(fld, defVal, "", true)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, expectedDef, actual())
|
||||
|
||||
err = binder.setFieldValue(fld, defVal, "yada", true)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestParamBinding(t *testing.T) {
|
||||
|
||||
actual := new(SomeOperationParams)
|
||||
val := reflect.ValueOf(actual).Elem()
|
||||
pName := "Name"
|
||||
fld := val.FieldByName(pName)
|
||||
|
||||
binder := &untypedParamBinder{
|
||||
parameter: spec.QueryParam(pName).Typed("string", "").WithDefault("some-name"),
|
||||
Name: pName,
|
||||
}
|
||||
|
||||
err := binder.setFieldValue(fld, "some-name", "the name value", true)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "the name value", actual.Name)
|
||||
|
||||
err = binder.setFieldValue(fld, "some-name", "", true)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "some-name", actual.Name)
|
||||
|
||||
IntParamTest(t, "ID", val, 1, 1, func() interface{} { return actual.ID })
|
||||
IntParamTest(t, "ID", val, nil, 0, func() interface{} { return actual.ID })
|
||||
IntParamTest(t, "Age", val, 1, 1, func() interface{} { return actual.Age })
|
||||
IntParamTest(t, "Age", val, nil, 0, func() interface{} { return actual.Age })
|
||||
IntParamTest(t, "Visits", val, 1, 1, func() interface{} { return actual.Visits })
|
||||
IntParamTest(t, "Visits", val, nil, 0, func() interface{} { return actual.Visits })
|
||||
IntParamTest(t, "Count", val, 1, 1, func() interface{} { return actual.Count })
|
||||
IntParamTest(t, "Count", val, nil, 0, func() interface{} { return actual.Count })
|
||||
IntParamTest(t, "Seq", val, 1, 1, func() interface{} { return actual.Seq })
|
||||
IntParamTest(t, "Seq", val, nil, 0, func() interface{} { return actual.Seq })
|
||||
IntParamTest(t, "UID", val, uint64(1), 1, func() interface{} { return actual.UID })
|
||||
IntParamTest(t, "UID", val, uint64(0), 0, func() interface{} { return actual.UID })
|
||||
IntParamTest(t, "UAge", val, uint(1), 1, func() interface{} { return actual.UAge })
|
||||
IntParamTest(t, "UAge", val, nil, 0, func() interface{} { return actual.UAge })
|
||||
IntParamTest(t, "UVisits", val, uint32(1), 1, func() interface{} { return actual.UVisits })
|
||||
IntParamTest(t, "UVisits", val, nil, 0, func() interface{} { return actual.UVisits })
|
||||
IntParamTest(t, "UCount", val, uint16(1), 1, func() interface{} { return actual.UCount })
|
||||
IntParamTest(t, "UCount", val, nil, 0, func() interface{} { return actual.UCount })
|
||||
IntParamTest(t, "USeq", val, uint8(1), 1, func() interface{} { return actual.USeq })
|
||||
IntParamTest(t, "USeq", val, nil, 0, func() interface{} { return actual.USeq })
|
||||
|
||||
FloatParamTest(t, "score", "Score", "float", val, 1.0, 1, func() interface{} { return actual.Score })
|
||||
FloatParamTest(t, "score", "Score", "float", val, nil, 0, func() interface{} { return actual.Score })
|
||||
FloatParamTest(t, "rate", "Rate", "double", val, 1.0, 1, func() interface{} { return actual.Rate })
|
||||
FloatParamTest(t, "rate", "Rate", "double", val, nil, 0, func() interface{} { return actual.Rate })
|
||||
|
||||
pName = "Confirmed"
|
||||
confirmedField := val.FieldByName(pName)
|
||||
binder = &untypedParamBinder{
|
||||
parameter: spec.QueryParam(pName).Typed("boolean", "").WithDefault(true),
|
||||
Name: pName,
|
||||
}
|
||||
|
||||
for _, tv := range evaluatesAsTrue {
|
||||
err = binder.setFieldValue(confirmedField, true, tv, true)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, actual.Confirmed)
|
||||
}
|
||||
|
||||
err = binder.setFieldValue(confirmedField, true, "", true)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, actual.Confirmed)
|
||||
|
||||
err = binder.setFieldValue(confirmedField, true, "0", true)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, actual.Confirmed)
|
||||
|
||||
pName = "Timestamp"
|
||||
timeField := val.FieldByName(pName)
|
||||
dt := strfmt.DateTime(time.Date(2014, 3, 19, 2, 9, 0, 0, time.UTC))
|
||||
binder = &untypedParamBinder{
|
||||
parameter: spec.QueryParam(pName).Typed("string", "date-time").WithDefault(dt),
|
||||
Name: pName,
|
||||
}
|
||||
exp := strfmt.DateTime(time.Date(2014, 5, 14, 2, 9, 0, 0, time.UTC))
|
||||
|
||||
err = binder.setFieldValue(timeField, dt, exp.String(), true)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, exp, actual.Timestamp)
|
||||
|
||||
err = binder.setFieldValue(timeField, dt, "", true)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, dt, actual.Timestamp)
|
||||
|
||||
err = binder.setFieldValue(timeField, dt, "yada", true)
|
||||
assert.Error(t, err)
|
||||
|
||||
ddt := strfmt.Date(time.Date(2014, 3, 19, 0, 0, 0, 0, time.UTC))
|
||||
pName = "Birthdate"
|
||||
dateField := val.FieldByName(pName)
|
||||
binder = &untypedParamBinder{
|
||||
parameter: spec.QueryParam(pName).Typed("string", "date").WithDefault(ddt),
|
||||
Name: pName,
|
||||
}
|
||||
expd := strfmt.Date(time.Date(2014, 5, 14, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
err = binder.setFieldValue(dateField, ddt, expd.String(), true)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expd, actual.Birthdate)
|
||||
|
||||
err = binder.setFieldValue(dateField, ddt, "", true)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, ddt, actual.Birthdate)
|
||||
|
||||
err = binder.setFieldValue(dateField, ddt, "yada", true)
|
||||
assert.Error(t, err)
|
||||
|
||||
dt = strfmt.DateTime(time.Date(2014, 3, 19, 2, 9, 0, 0, time.UTC))
|
||||
fdt := &dt
|
||||
pName = "LastFailure"
|
||||
ftimeField := val.FieldByName(pName)
|
||||
binder = &untypedParamBinder{
|
||||
parameter: spec.QueryParam(pName).Typed("string", "date").WithDefault(fdt),
|
||||
Name: pName,
|
||||
}
|
||||
exp = strfmt.DateTime(time.Date(2014, 5, 14, 2, 9, 0, 0, time.UTC))
|
||||
fexp := &exp
|
||||
|
||||
err = binder.setFieldValue(ftimeField, fdt, fexp.String(), true)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, fexp, actual.LastFailure)
|
||||
|
||||
err = binder.setFieldValue(ftimeField, fdt, "", true)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, fdt, actual.LastFailure)
|
||||
|
||||
err = binder.setFieldValue(ftimeField, fdt, "", true)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, fdt, actual.LastFailure)
|
||||
|
||||
actual.LastFailure = nil
|
||||
err = binder.setFieldValue(ftimeField, fdt, "yada", true)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, actual.LastFailure)
|
||||
|
||||
pName = "Unsupported"
|
||||
unsupportedField := val.FieldByName(pName)
|
||||
binder = &untypedParamBinder{
|
||||
parameter: spec.QueryParam(pName).Typed("string", ""),
|
||||
Name: pName,
|
||||
}
|
||||
err = binder.setFieldValue(unsupportedField, nil, "", true)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestSliceConversion(t *testing.T) {
|
||||
|
||||
actual := new(SomeOperationParams)
|
||||
val := reflect.ValueOf(actual).Elem()
|
||||
|
||||
// prefsField := val.FieldByName("Prefs")
|
||||
// cData := "yada,2,3"
|
||||
// _, _, err := readFormattedSliceFieldValue("Prefs", prefsField, cData, "csv", nil)
|
||||
// assert.Error(t, err)
|
||||
|
||||
sliced := []string{"some", "string", "values"}
|
||||
seps := map[string]string{"ssv": " ", "tsv": "\t", "pipes": "|", "csv": ",", "": ","}
|
||||
|
||||
tagsField := val.FieldByName("Tags")
|
||||
for k, sep := range seps {
|
||||
binder := &untypedParamBinder{
|
||||
Name: "Tags",
|
||||
parameter: spec.QueryParam("tags").CollectionOf(stringItems, k),
|
||||
}
|
||||
|
||||
actual.Tags = nil
|
||||
cData := strings.Join(sliced, sep)
|
||||
tags, _, err := binder.readFormattedSliceFieldValue(cData, tagsField)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, sliced, tags)
|
||||
cData = strings.Join(sliced, " "+sep+" ")
|
||||
tags, _, err = binder.readFormattedSliceFieldValue(cData, tagsField)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, sliced, tags)
|
||||
tags, _, err = binder.readFormattedSliceFieldValue("", tagsField)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, tags)
|
||||
}
|
||||
|
||||
assert.Nil(t, swag.SplitByFormat("yada", "multi"))
|
||||
assert.Nil(t, swag.SplitByFormat("", ""))
|
||||
|
||||
categoriesField := val.FieldByName("Categories")
|
||||
binder := &untypedParamBinder{
|
||||
Name: "Categories",
|
||||
parameter: spec.QueryParam("categories").CollectionOf(stringItems, "csv"),
|
||||
}
|
||||
cData := strings.Join(sliced, ",")
|
||||
categories, custom, err := binder.readFormattedSliceFieldValue(cData, categoriesField)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, sliced, actual.Categories)
|
||||
assert.True(t, custom)
|
||||
assert.Empty(t, categories)
|
||||
categories, custom, err = binder.readFormattedSliceFieldValue("", categoriesField)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, custom)
|
||||
assert.Empty(t, categories)
|
||||
}
|
||||
275
vendor/github.com/go-openapi/runtime/middleware/untyped/api.go
generated
vendored
275
vendor/github.com/go-openapi/runtime/middleware/untyped/api.go
generated
vendored
@@ -1,275 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package untyped
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
// NewAPI creates the default untyped API
|
||||
func NewAPI(spec *loads.Document) *API {
|
||||
var an *analysis.Spec
|
||||
if spec != nil && spec.Spec() != nil {
|
||||
an = analysis.New(spec.Spec())
|
||||
}
|
||||
api := &API{
|
||||
spec: spec,
|
||||
analyzer: an,
|
||||
consumers: make(map[string]runtime.Consumer, 10),
|
||||
producers: make(map[string]runtime.Producer, 10),
|
||||
authenticators: make(map[string]runtime.Authenticator),
|
||||
operations: make(map[string]map[string]runtime.OperationHandler),
|
||||
ServeError: errors.ServeError,
|
||||
Models: make(map[string]func() interface{}),
|
||||
formats: strfmt.NewFormats(),
|
||||
}
|
||||
return api.WithJSONDefaults()
|
||||
}
|
||||
|
||||
// API represents an untyped mux for a swagger spec
|
||||
type API struct {
|
||||
spec *loads.Document
|
||||
analyzer *analysis.Spec
|
||||
DefaultProduces string
|
||||
DefaultConsumes string
|
||||
consumers map[string]runtime.Consumer
|
||||
producers map[string]runtime.Producer
|
||||
authenticators map[string]runtime.Authenticator
|
||||
operations map[string]map[string]runtime.OperationHandler
|
||||
ServeError func(http.ResponseWriter, *http.Request, error)
|
||||
Models map[string]func() interface{}
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// WithJSONDefaults loads the json defaults for this api
|
||||
func (d *API) WithJSONDefaults() *API {
|
||||
d.DefaultConsumes = runtime.JSONMime
|
||||
d.DefaultProduces = runtime.JSONMime
|
||||
d.consumers[runtime.JSONMime] = runtime.JSONConsumer()
|
||||
d.producers[runtime.JSONMime] = runtime.JSONProducer()
|
||||
return d
|
||||
}
|
||||
|
||||
// WithoutJSONDefaults clears the json defaults for this api
|
||||
func (d *API) WithoutJSONDefaults() *API {
|
||||
d.DefaultConsumes = ""
|
||||
d.DefaultProduces = ""
|
||||
delete(d.consumers, runtime.JSONMime)
|
||||
delete(d.producers, runtime.JSONMime)
|
||||
return d
|
||||
}
|
||||
|
||||
// Formats returns the registered string formats
|
||||
func (d *API) Formats() strfmt.Registry {
|
||||
if d.formats == nil {
|
||||
d.formats = strfmt.NewFormats()
|
||||
}
|
||||
return d.formats
|
||||
}
|
||||
|
||||
// RegisterFormat registers a custom format validator
|
||||
func (d *API) RegisterFormat(name string, format strfmt.Format, validator strfmt.Validator) {
|
||||
if d.formats == nil {
|
||||
d.formats = strfmt.NewFormats()
|
||||
}
|
||||
d.formats.Add(name, format, validator)
|
||||
}
|
||||
|
||||
// RegisterAuth registers an auth handler in this api
|
||||
func (d *API) RegisterAuth(scheme string, handler runtime.Authenticator) {
|
||||
if d.authenticators == nil {
|
||||
d.authenticators = make(map[string]runtime.Authenticator)
|
||||
}
|
||||
d.authenticators[scheme] = handler
|
||||
}
|
||||
|
||||
// RegisterConsumer registers a consumer for a media type.
|
||||
func (d *API) RegisterConsumer(mediaType string, handler runtime.Consumer) {
|
||||
if d.consumers == nil {
|
||||
d.consumers = make(map[string]runtime.Consumer, 10)
|
||||
}
|
||||
d.consumers[strings.ToLower(mediaType)] = handler
|
||||
}
|
||||
|
||||
// RegisterProducer registers a producer for a media type
|
||||
func (d *API) RegisterProducer(mediaType string, handler runtime.Producer) {
|
||||
if d.producers == nil {
|
||||
d.producers = make(map[string]runtime.Producer, 10)
|
||||
}
|
||||
d.producers[strings.ToLower(mediaType)] = handler
|
||||
}
|
||||
|
||||
// RegisterOperation registers an operation handler for an operation name
|
||||
func (d *API) RegisterOperation(method, path string, handler runtime.OperationHandler) {
|
||||
if d.operations == nil {
|
||||
d.operations = make(map[string]map[string]runtime.OperationHandler, 30)
|
||||
}
|
||||
um := strings.ToUpper(method)
|
||||
if b, ok := d.operations[um]; !ok || b == nil {
|
||||
d.operations[um] = make(map[string]runtime.OperationHandler)
|
||||
}
|
||||
d.operations[um][path] = handler
|
||||
}
|
||||
|
||||
// OperationHandlerFor returns the operation handler for the specified id if it can be found
|
||||
func (d *API) OperationHandlerFor(method, path string) (runtime.OperationHandler, bool) {
|
||||
if d.operations == nil {
|
||||
return nil, false
|
||||
}
|
||||
if pi, ok := d.operations[strings.ToUpper(method)]; ok {
|
||||
h, ok := pi[path]
|
||||
return h, ok
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// ConsumersFor gets the consumers for the specified media types
|
||||
func (d *API) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer {
|
||||
result := make(map[string]runtime.Consumer)
|
||||
for _, mt := range mediaTypes {
|
||||
if consumer, ok := d.consumers[mt]; ok {
|
||||
result[mt] = consumer
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ProducersFor gets the producers for the specified media types
|
||||
func (d *API) ProducersFor(mediaTypes []string) map[string]runtime.Producer {
|
||||
result := make(map[string]runtime.Producer)
|
||||
for _, mt := range mediaTypes {
|
||||
if producer, ok := d.producers[mt]; ok {
|
||||
result[mt] = producer
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// AuthenticatorsFor gets the authenticators for the specified security schemes
|
||||
func (d *API) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[string]runtime.Authenticator {
|
||||
result := make(map[string]runtime.Authenticator)
|
||||
for k := range schemes {
|
||||
if a, ok := d.authenticators[k]; ok {
|
||||
result[k] = a
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Validate validates this API for any missing items
|
||||
func (d *API) Validate() error {
|
||||
return d.validate()
|
||||
}
|
||||
|
||||
// validateWith validates the registrations in this API against the provided spec analyzer
|
||||
func (d *API) validate() error {
|
||||
var consumes []string
|
||||
for k := range d.consumers {
|
||||
consumes = append(consumes, k)
|
||||
}
|
||||
|
||||
var produces []string
|
||||
for k := range d.producers {
|
||||
produces = append(produces, k)
|
||||
}
|
||||
|
||||
var authenticators []string
|
||||
for k := range d.authenticators {
|
||||
authenticators = append(authenticators, k)
|
||||
}
|
||||
|
||||
var operations []string
|
||||
for m, v := range d.operations {
|
||||
for p := range v {
|
||||
operations = append(operations, fmt.Sprintf("%s %s", strings.ToUpper(m), p))
|
||||
}
|
||||
}
|
||||
|
||||
var definedAuths []string
|
||||
for k := range d.spec.Spec().SecurityDefinitions {
|
||||
definedAuths = append(definedAuths, k)
|
||||
}
|
||||
|
||||
if err := d.verify("consumes", consumes, d.analyzer.RequiredConsumes()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.verify("produces", produces, d.analyzer.RequiredProduces()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.verify("operation", operations, d.analyzer.OperationMethodPaths()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
requiredAuths := d.analyzer.RequiredSecuritySchemes()
|
||||
if err := d.verify("auth scheme", authenticators, requiredAuths); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.verify("security definitions", definedAuths, requiredAuths); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *API) verify(name string, registrations []string, expectations []string) error {
|
||||
|
||||
sort.Sort(sort.StringSlice(registrations))
|
||||
sort.Sort(sort.StringSlice(expectations))
|
||||
|
||||
expected := map[string]struct{}{}
|
||||
seen := map[string]struct{}{}
|
||||
|
||||
for _, v := range expectations {
|
||||
expected[v] = struct{}{}
|
||||
}
|
||||
|
||||
var unspecified []string
|
||||
for _, v := range registrations {
|
||||
seen[v] = struct{}{}
|
||||
if _, ok := expected[v]; !ok {
|
||||
unspecified = append(unspecified, v)
|
||||
}
|
||||
}
|
||||
|
||||
for k := range seen {
|
||||
delete(expected, k)
|
||||
}
|
||||
|
||||
var unregistered []string
|
||||
for k := range expected {
|
||||
unregistered = append(unregistered, k)
|
||||
}
|
||||
sort.Sort(sort.StringSlice(unspecified))
|
||||
sort.Sort(sort.StringSlice(unregistered))
|
||||
|
||||
if len(unregistered) > 0 || len(unspecified) > 0 {
|
||||
return &errors.APIVerificationFailed{
|
||||
Section: name,
|
||||
MissingSpecification: unspecified,
|
||||
MissingRegistration: unregistered,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
276
vendor/github.com/go-openapi/runtime/middleware/untyped/api_test.go
generated
vendored
276
vendor/github.com/go-openapi/runtime/middleware/untyped/api_test.go
generated
vendored
@@ -1,276 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package untyped
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/runtime"
|
||||
swaggerspec "github.com/go-openapi/spec"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func stubAutenticator() runtime.Authenticator {
|
||||
return runtime.AuthenticatorFunc(func(_ interface{}) (bool, interface{}, error) { return false, nil, nil })
|
||||
}
|
||||
|
||||
type stubConsumer struct {
|
||||
}
|
||||
|
||||
func (s *stubConsumer) Consume(_ io.Reader, _ interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type stubProducer struct {
|
||||
}
|
||||
|
||||
func (s *stubProducer) Produce(_ io.Writer, _ interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type stubOperationHandler struct {
|
||||
}
|
||||
|
||||
func (s *stubOperationHandler) ParameterModel() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stubOperationHandler) Handle(params interface{}) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func TestUntypedAPIRegistrations(t *testing.T) {
|
||||
api := NewAPI(new(loads.Document)).WithJSONDefaults()
|
||||
|
||||
api.RegisterConsumer("application/yada", new(stubConsumer))
|
||||
api.RegisterProducer("application/yada-2", new(stubProducer))
|
||||
api.RegisterOperation("get", "/{someId}", new(stubOperationHandler))
|
||||
api.RegisterAuth("basic", stubAutenticator())
|
||||
|
||||
assert.NotEmpty(t, api.authenticators)
|
||||
|
||||
_, ok := api.authenticators["basic"]
|
||||
assert.True(t, ok)
|
||||
_, ok = api.consumers["application/yada"]
|
||||
assert.True(t, ok)
|
||||
_, ok = api.producers["application/yada-2"]
|
||||
assert.True(t, ok)
|
||||
_, ok = api.consumers["application/json"]
|
||||
assert.True(t, ok)
|
||||
_, ok = api.producers["application/json"]
|
||||
assert.True(t, ok)
|
||||
_, ok = api.operations["GET"]["/{someId}"]
|
||||
assert.True(t, ok)
|
||||
|
||||
h, ok := api.OperationHandlerFor("get", "/{someId}")
|
||||
assert.True(t, ok)
|
||||
assert.NotNil(t, h)
|
||||
|
||||
_, ok = api.OperationHandlerFor("doesntExist", "/{someId}")
|
||||
assert.False(t, ok)
|
||||
}
|
||||
|
||||
func TestUntypedAppValidation(t *testing.T) {
|
||||
invalidSpecStr := `{
|
||||
"consumes": ["application/json"],
|
||||
"produces": ["application/json"],
|
||||
"security": [
|
||||
{"apiKey":[]}
|
||||
],
|
||||
"parameters": {
|
||||
"format": {
|
||||
"in": "query",
|
||||
"name": "format",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"paths": {
|
||||
"/": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "limit",
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"x-go-name": "Limit"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"consumes": ["application/x-yaml"],
|
||||
"produces": ["application/x-yaml"],
|
||||
"security": [
|
||||
{"basic":[]}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "skip",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
specStr := `{
|
||||
"consumes": ["application/json"],
|
||||
"produces": ["application/json"],
|
||||
"security": [
|
||||
{"apiKey":[]}
|
||||
],
|
||||
"securityDefinitions": {
|
||||
"basic": { "type": "basic" },
|
||||
"apiKey": { "type": "apiKey", "in":"header", "name":"X-API-KEY" }
|
||||
},
|
||||
"parameters": {
|
||||
"format": {
|
||||
"in": "query",
|
||||
"name": "format",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"paths": {
|
||||
"/": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "limit",
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"x-go-name": "Limit"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"consumes": ["application/x-yaml"],
|
||||
"produces": ["application/x-yaml"],
|
||||
"security": [
|
||||
{"basic":[]}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "skip",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
validSpec, err := loads.Analyzed([]byte(specStr), "")
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, validSpec)
|
||||
|
||||
spec, err := loads.Analyzed([]byte(invalidSpecStr), "")
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, spec)
|
||||
|
||||
analyzed := analysis.New(spec.Spec())
|
||||
analyzedValid := analysis.New(validSpec.Spec())
|
||||
cons := analyzed.ConsumesFor(analyzed.AllPaths()["/"].Get)
|
||||
assert.Len(t, cons, 1)
|
||||
prods := analyzed.RequiredProduces()
|
||||
assert.Len(t, prods, 2)
|
||||
|
||||
api1 := NewAPI(spec)
|
||||
err = api1.Validate()
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "missing [application/x-yaml] consumes registrations", err.Error())
|
||||
api1.RegisterConsumer("application/x-yaml", new(stubConsumer))
|
||||
err = api1.validate()
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "missing [application/x-yaml] produces registrations", err.Error())
|
||||
api1.RegisterProducer("application/x-yaml", new(stubProducer))
|
||||
err = api1.validate()
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "missing [GET /] operation registrations", err.Error())
|
||||
api1.RegisterOperation("get", "/", new(stubOperationHandler))
|
||||
err = api1.validate()
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "missing [apiKey, basic] auth scheme registrations", err.Error())
|
||||
api1.RegisterAuth("basic", stubAutenticator())
|
||||
api1.RegisterAuth("apiKey", stubAutenticator())
|
||||
err = api1.validate()
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "missing [apiKey, basic] security definitions registrations", err.Error())
|
||||
|
||||
api3 := NewAPI(validSpec)
|
||||
api3.RegisterConsumer("application/x-yaml", new(stubConsumer))
|
||||
api3.RegisterProducer("application/x-yaml", new(stubProducer))
|
||||
api3.RegisterOperation("get", "/", new(stubOperationHandler))
|
||||
api3.RegisterAuth("basic", stubAutenticator())
|
||||
api3.RegisterAuth("apiKey", stubAutenticator())
|
||||
err = api3.validate()
|
||||
assert.NoError(t, err)
|
||||
api3.RegisterConsumer("application/something", new(stubConsumer))
|
||||
err = api3.validate()
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "missing from spec file [application/something] consumes", err.Error())
|
||||
|
||||
api2 := NewAPI(spec)
|
||||
api2.RegisterConsumer("application/something", new(stubConsumer))
|
||||
err = api2.validate()
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "missing [application/x-yaml] consumes registrations\nmissing from spec file [application/something] consumes", err.Error())
|
||||
api2.RegisterConsumer("application/x-yaml", new(stubConsumer))
|
||||
delete(api2.consumers, "application/something")
|
||||
api2.RegisterProducer("application/something", new(stubProducer))
|
||||
err = api2.validate()
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "missing [application/x-yaml] produces registrations\nmissing from spec file [application/something] produces", err.Error())
|
||||
delete(api2.producers, "application/something")
|
||||
api2.RegisterProducer("application/x-yaml", new(stubProducer))
|
||||
|
||||
expected := []string{"application/x-yaml"}
|
||||
sort.Sort(sort.StringSlice(expected))
|
||||
consumes := analyzed.ConsumesFor(analyzed.AllPaths()["/"].Get)
|
||||
sort.Sort(sort.StringSlice(consumes))
|
||||
assert.Equal(t, expected, consumes)
|
||||
consumers := api1.ConsumersFor(consumes)
|
||||
assert.Len(t, consumers, 1)
|
||||
|
||||
produces := analyzed.ProducesFor(analyzed.AllPaths()["/"].Get)
|
||||
sort.Sort(sort.StringSlice(produces))
|
||||
assert.Equal(t, expected, produces)
|
||||
producers := api1.ProducersFor(produces)
|
||||
assert.Len(t, producers, 1)
|
||||
|
||||
definitions := analyzedValid.SecurityDefinitionsFor(analyzedValid.AllPaths()["/"].Get)
|
||||
expectedSchemes := map[string]swaggerspec.SecurityScheme{"basic": *swaggerspec.BasicAuth()}
|
||||
assert.Equal(t, expectedSchemes, definitions)
|
||||
authenticators := api3.AuthenticatorsFor(definitions)
|
||||
assert.Len(t, authenticators, 1)
|
||||
|
||||
opHandler := runtime.OperationHandlerFunc(func(data interface{}) (interface{}, error) {
|
||||
return data, nil
|
||||
})
|
||||
d, err := opHandler.Handle(1)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, d)
|
||||
|
||||
authenticator := runtime.AuthenticatorFunc(func(params interface{}) (bool, interface{}, error) {
|
||||
if str, ok := params.(string); ok {
|
||||
return ok, str, nil
|
||||
}
|
||||
return true, nil, errors.Unauthenticated("authenticator")
|
||||
})
|
||||
ok, p, err := authenticator.Authenticate("hello")
|
||||
assert.True(t, ok)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "hello", p)
|
||||
}
|
||||
164
vendor/github.com/go-openapi/runtime/middleware/untyped_request_test.go
generated
vendored
164
vendor/github.com/go-openapi/runtime/middleware/untyped_request_test.go
generated
vendored
@@ -1,164 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestUntypedFormPost(t *testing.T) {
|
||||
params := parametersForFormUpload()
|
||||
binder := newUntypedRequestBinder(params, nil, strfmt.Default)
|
||||
|
||||
urlStr := "http://localhost:8002/hello"
|
||||
req, _ := http.NewRequest("POST", urlStr, bytes.NewBufferString(`name=the-name&age=32`))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
data := make(map[string]interface{})
|
||||
assert.NoError(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data))
|
||||
assert.Equal(t, "the-name", data["name"])
|
||||
assert.EqualValues(t, 32, data["age"])
|
||||
|
||||
req, _ = http.NewRequest("POST", urlStr, bytes.NewBufferString(`name=%3&age=32`))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
data = make(map[string]interface{})
|
||||
assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data))
|
||||
}
|
||||
|
||||
func TestUntypedFileUpload(t *testing.T) {
|
||||
binder := paramsForFileUpload()
|
||||
|
||||
body := bytes.NewBuffer(nil)
|
||||
writer := multipart.NewWriter(body)
|
||||
part, err := writer.CreateFormFile("file", "plain-jane.txt")
|
||||
assert.NoError(t, err)
|
||||
|
||||
part.Write([]byte("the file contents"))
|
||||
writer.WriteField("name", "the-name")
|
||||
assert.NoError(t, writer.Close())
|
||||
|
||||
urlStr := "http://localhost:8002/hello"
|
||||
req, _ := http.NewRequest("POST", urlStr, body)
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
data := make(map[string]interface{})
|
||||
assert.NoError(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data))
|
||||
assert.Equal(t, "the-name", data["name"])
|
||||
assert.NotNil(t, data["file"])
|
||||
assert.IsType(t, runtime.File{}, data["file"])
|
||||
file := data["file"].(runtime.File)
|
||||
assert.NotNil(t, file.Header)
|
||||
assert.Equal(t, "plain-jane.txt", file.Header.Filename)
|
||||
|
||||
bb, err := ioutil.ReadAll(file.Data)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("the file contents"), bb)
|
||||
|
||||
req, _ = http.NewRequest("POST", urlStr, body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
data = make(map[string]interface{})
|
||||
assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data))
|
||||
|
||||
req, _ = http.NewRequest("POST", urlStr, body)
|
||||
req.Header.Set("Content-Type", "application(")
|
||||
data = make(map[string]interface{})
|
||||
assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data))
|
||||
|
||||
body = bytes.NewBuffer(nil)
|
||||
writer = multipart.NewWriter(body)
|
||||
part, err = writer.CreateFormFile("bad-name", "plain-jane.txt")
|
||||
assert.NoError(t, err)
|
||||
|
||||
part.Write([]byte("the file contents"))
|
||||
writer.WriteField("name", "the-name")
|
||||
assert.NoError(t, writer.Close())
|
||||
req, _ = http.NewRequest("POST", urlStr, body)
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
data = make(map[string]interface{})
|
||||
assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data))
|
||||
|
||||
req, _ = http.NewRequest("POST", urlStr, body)
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
req.MultipartReader()
|
||||
|
||||
data = make(map[string]interface{})
|
||||
assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data))
|
||||
}
|
||||
|
||||
func TestUntypedBindingTypesForValid(t *testing.T) {
|
||||
|
||||
op2 := parametersForAllTypes("")
|
||||
binder := newUntypedRequestBinder(op2, nil, strfmt.Default)
|
||||
|
||||
confirmed := true
|
||||
name := "thomas"
|
||||
friend := map[string]interface{}{"name": "toby", "age": json.Number("32")}
|
||||
id, age, score, factor := int64(7575), int32(348), float32(5.309), float64(37.403)
|
||||
requestID := 19394858
|
||||
tags := []string{"one", "two", "three"}
|
||||
dt1 := time.Date(2014, 8, 9, 0, 0, 0, 0, time.UTC)
|
||||
planned := strfmt.Date(dt1)
|
||||
dt2 := time.Date(2014, 10, 12, 8, 5, 5, 0, time.UTC)
|
||||
delivered := strfmt.DateTime(dt2)
|
||||
picture := base64.URLEncoding.EncodeToString([]byte("hello"))
|
||||
uri, _ := url.Parse("http://localhost:8002/hello/7575")
|
||||
qs := uri.Query()
|
||||
qs.Add("name", name)
|
||||
qs.Add("confirmed", "true")
|
||||
qs.Add("age", "348")
|
||||
qs.Add("score", "5.309")
|
||||
qs.Add("factor", "37.403")
|
||||
qs.Add("tags", strings.Join(tags, ","))
|
||||
qs.Add("planned", planned.String())
|
||||
qs.Add("delivered", delivered.String())
|
||||
qs.Add("picture", picture)
|
||||
|
||||
req, _ := http.NewRequest("POST", uri.String()+"?"+qs.Encode(), bytes.NewBuffer([]byte(`{"name":"toby","age":32}`)))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-Request-Id", "19394858")
|
||||
|
||||
data := make(map[string]interface{})
|
||||
err := binder.Bind(req, RouteParams([]RouteParam{{"id", "7575"}}), runtime.JSONConsumer(), &data)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, id, data["id"])
|
||||
assert.Equal(t, name, data["name"])
|
||||
assert.Equal(t, friend, data["friend"])
|
||||
assert.EqualValues(t, requestID, data["X-Request-Id"])
|
||||
assert.Equal(t, tags, data["tags"])
|
||||
assert.Equal(t, planned, data["planned"])
|
||||
assert.Equal(t, delivered, data["delivered"])
|
||||
assert.Equal(t, confirmed, data["confirmed"])
|
||||
assert.Equal(t, age, data["age"])
|
||||
assert.Equal(t, factor, data["factor"])
|
||||
assert.Equal(t, score, data["score"])
|
||||
pb, _ := base64.URLEncoding.DecodeString(picture)
|
||||
assert.EqualValues(t, pb, data["picture"].(strfmt.Base64))
|
||||
|
||||
}
|
||||
141
vendor/github.com/go-openapi/runtime/middleware/validation.go
generated
vendored
141
vendor/github.com/go-openapi/runtime/middleware/validation.go
generated
vendored
@@ -1,141 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"mime"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// NewValidation starts a new validation middleware
|
||||
func newValidation(ctx *Context, next http.Handler) http.Handler {
|
||||
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
matched, _ := ctx.RouteInfo(r)
|
||||
if matched == nil {
|
||||
ctx.NotFound(rw, r)
|
||||
return
|
||||
}
|
||||
_, result := ctx.BindAndValidate(r, matched)
|
||||
|
||||
if result != nil {
|
||||
ctx.Respond(rw, r, matched.Produces, matched, result)
|
||||
return
|
||||
}
|
||||
|
||||
debugLog("no result for %s %s", r.Method, r.URL.EscapedPath())
|
||||
next.ServeHTTP(rw, r)
|
||||
})
|
||||
}
|
||||
|
||||
type validation struct {
|
||||
context *Context
|
||||
result []error
|
||||
request *http.Request
|
||||
route *MatchedRoute
|
||||
bound map[string]interface{}
|
||||
}
|
||||
|
||||
type untypedBinder map[string]interface{}
|
||||
|
||||
func (ub untypedBinder) BindRequest(r *http.Request, route *MatchedRoute, consumer runtime.Consumer) error {
|
||||
if err := route.Binder.Bind(r, route.Params, consumer, ub); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContentType validates the content type of a request
|
||||
func validateContentType(allowed []string, actual string) error {
|
||||
debugLog("validating content type for %q against [%s]", actual, strings.Join(allowed, ", "))
|
||||
if len(allowed) == 0 {
|
||||
return nil
|
||||
}
|
||||
mt, _, err := mime.ParseMediaType(actual)
|
||||
if err != nil {
|
||||
return errors.InvalidContentType(actual, allowed)
|
||||
}
|
||||
if swag.ContainsStringsCI(allowed, mt) {
|
||||
return nil
|
||||
}
|
||||
return errors.InvalidContentType(actual, allowed)
|
||||
}
|
||||
|
||||
func validateRequest(ctx *Context, request *http.Request, route *MatchedRoute) *validation {
|
||||
debugLog("validating request %s %s", request.Method, request.URL.EscapedPath())
|
||||
validate := &validation{
|
||||
context: ctx,
|
||||
request: request,
|
||||
route: route,
|
||||
bound: make(map[string]interface{}),
|
||||
}
|
||||
|
||||
validate.contentType()
|
||||
if len(validate.result) == 0 {
|
||||
validate.responseFormat()
|
||||
}
|
||||
if len(validate.result) == 0 {
|
||||
validate.parameters()
|
||||
}
|
||||
|
||||
return validate
|
||||
}
|
||||
|
||||
func (v *validation) parameters() {
|
||||
debugLog("validating request parameters for %s %s", v.request.Method, v.request.URL.EscapedPath())
|
||||
if result := v.route.Binder.Bind(v.request, v.route.Params, v.route.Consumer, v.bound); result != nil {
|
||||
if result.Error() == "validation failure list" {
|
||||
for _, e := range result.(*errors.Validation).Value.([]interface{}) {
|
||||
v.result = append(v.result, e.(error))
|
||||
}
|
||||
return
|
||||
}
|
||||
v.result = append(v.result, result)
|
||||
}
|
||||
}
|
||||
|
||||
func (v *validation) contentType() {
|
||||
if len(v.result) == 0 && runtime.HasBody(v.request) {
|
||||
debugLog("validating body content type for %s %s", v.request.Method, v.request.URL.EscapedPath())
|
||||
ct, _, err := v.context.ContentType(v.request)
|
||||
if err != nil {
|
||||
v.result = append(v.result, err)
|
||||
}
|
||||
if len(v.result) == 0 {
|
||||
if err := validateContentType(v.route.Consumes, ct); err != nil {
|
||||
v.result = append(v.result, err)
|
||||
}
|
||||
}
|
||||
if ct != "" && v.route.Consumer == nil {
|
||||
cons, ok := v.route.Consumers[ct]
|
||||
if !ok {
|
||||
v.result = append(v.result, errors.New(500, "no consumer registered for %s", ct))
|
||||
} else {
|
||||
v.route.Consumer = cons
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (v *validation) responseFormat() {
|
||||
if str := v.context.ResponseFormat(v.request, v.route.Produces); str == "" && runtime.HasBody(v.request) {
|
||||
v.result = append(v.result, errors.InvalidResponseFormat(v.request.Header.Get(runtime.HeaderAccept), v.route.Produces))
|
||||
}
|
||||
}
|
||||
130
vendor/github.com/go-openapi/runtime/middleware/validation_test.go
generated
vendored
130
vendor/github.com/go-openapi/runtime/middleware/validation_test.go
generated
vendored
@@ -1,130 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/internal/testing/petstore"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestContentTypeValidation(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
context := NewContext(spec, api, nil)
|
||||
context.router = DefaultRouter(spec, context.api)
|
||||
mw := newValidation(context, http.HandlerFunc(terminator))
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
request, _ := http.NewRequest("GET", "/api/pets", nil)
|
||||
request.Header.Add("Accept", "*/*")
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, http.StatusOK, recorder.Code)
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("POST", "/api/pets", nil)
|
||||
request.Header.Add("content-type", "application(")
|
||||
request.ContentLength = 1
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, http.StatusBadRequest, recorder.Code)
|
||||
assert.Equal(t, "application/json", recorder.Header().Get("content-type"))
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("POST", "/api/pets", nil)
|
||||
request.Header.Add("Accept", "application/json")
|
||||
request.Header.Add("content-type", "text/html")
|
||||
request.ContentLength = 1
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, http.StatusUnsupportedMediaType, recorder.Code)
|
||||
assert.Equal(t, "application/json", recorder.Header().Get("content-type"))
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("POST", "/api/pets", nil)
|
||||
request.Header.Add("Accept", "application/json")
|
||||
request.Header.Add("content-type", "text/html")
|
||||
request.TransferEncoding = []string{"chunked"}
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, http.StatusUnsupportedMediaType, recorder.Code)
|
||||
assert.Equal(t, "application/json", recorder.Header().Get("content-type"))
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("POST", "/api/pets", nil)
|
||||
request.Header.Add("Accept", "application/json")
|
||||
request.Header.Add("content-type", "text/html")
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 422, recorder.Code)
|
||||
assert.Equal(t, "application/json", recorder.Header().Get("content-type"))
|
||||
}
|
||||
|
||||
func TestResponseFormatValidation(t *testing.T) {
|
||||
spec, api := petstore.NewAPI(t)
|
||||
context := NewContext(spec, api, nil)
|
||||
context.router = DefaultRouter(spec, context.api)
|
||||
mw := newValidation(context, http.HandlerFunc(terminator))
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
request, _ := http.NewRequest("POST", "/api/pets", bytes.NewBuffer([]byte(`name: Dog`)))
|
||||
request.Header.Set(runtime.HeaderContentType, "application/x-yaml")
|
||||
request.Header.Set(runtime.HeaderAccept, "application/x-yaml")
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, 200, recorder.Code, recorder.Body.String())
|
||||
|
||||
recorder = httptest.NewRecorder()
|
||||
request, _ = http.NewRequest("POST", "/api/pets", bytes.NewBuffer([]byte(`name: Dog`)))
|
||||
request.Header.Set(runtime.HeaderContentType, "application/x-yaml")
|
||||
request.Header.Set(runtime.HeaderAccept, "application/sml")
|
||||
|
||||
mw.ServeHTTP(recorder, request)
|
||||
assert.Equal(t, http.StatusNotAcceptable, recorder.Code)
|
||||
}
|
||||
|
||||
func TestValidateContentType(t *testing.T) {
|
||||
data := []struct {
|
||||
hdr string
|
||||
allowed []string
|
||||
err *errors.Validation
|
||||
}{
|
||||
{"application/json", []string{"application/json"}, nil},
|
||||
{"application/json", []string{"application/x-yaml", "text/html"}, errors.InvalidContentType("application/json", []string{"application/x-yaml", "text/html"})},
|
||||
{"text/html; charset=utf-8", []string{"text/html"}, nil},
|
||||
{"text/html;charset=utf-8", []string{"text/html"}, nil},
|
||||
{"", []string{"application/json"}, errors.InvalidContentType("", []string{"application/json"})},
|
||||
{"text/html; charset=utf-8", []string{"application/json"}, errors.InvalidContentType("text/html; charset=utf-8", []string{"application/json"})},
|
||||
{"application(", []string{"application/json"}, errors.InvalidContentType("application(", []string{"application/json"})},
|
||||
{"application/json;char*", []string{"application/json"}, errors.InvalidContentType("application/json;char*", []string{"application/json"})},
|
||||
}
|
||||
|
||||
for _, v := range data {
|
||||
err := validateContentType(v.allowed, v.hdr)
|
||||
if v.err == nil {
|
||||
assert.NoError(t, err, "input: %q", v.hdr)
|
||||
} else {
|
||||
assert.Error(t, err, "input: %q", v.hdr)
|
||||
assert.IsType(t, &errors.Validation{}, err, "input: %q", v.hdr)
|
||||
assert.Equal(t, v.err.Error(), err.Error(), "input: %q", v.hdr)
|
||||
assert.EqualValues(t, http.StatusUnsupportedMediaType, err.(*errors.Validation).Code())
|
||||
}
|
||||
}
|
||||
}
|
||||
122
vendor/github.com/go-openapi/runtime/request_test.go
generated
vendored
122
vendor/github.com/go-openapi/runtime/request_test.go
generated
vendored
@@ -1,122 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
/*
|
||||
type tstreadcloser struct {
|
||||
closed bool
|
||||
}
|
||||
|
||||
func (t *tstreadcloser) Read(p []byte) (int, error) { return 0, nil }
|
||||
func (t *tstreadcloser) Close() error {
|
||||
t.closed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestPeekingReader(t *testing.T) {
|
||||
// just passes to original reader when nothing called
|
||||
exp1 := []byte("original")
|
||||
pr1 := &peekingReader{rdr: ioutil.NopCloser(bytes.NewReader(exp1))}
|
||||
b1, err := ioutil.ReadAll(pr1)
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, exp1, b1)
|
||||
}
|
||||
|
||||
// uses actual when there was some buffering
|
||||
exp2 := []byte("actual")
|
||||
pt1, pt2 := []byte("a"), []byte("ctual")
|
||||
pr2 := &peekingReader{
|
||||
rdr: ioutil.NopCloser(bytes.NewReader(exp1)),
|
||||
actual: io.MultiReader(bytes.NewReader(pt1), bytes.NewReader(pt2)),
|
||||
peeked: pt1,
|
||||
}
|
||||
b2, err := ioutil.ReadAll(pr2)
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, exp2, b2)
|
||||
}
|
||||
|
||||
// closes original reader
|
||||
tr := new(tstreadcloser)
|
||||
pr3 := &peekingReader{
|
||||
rdr: tr,
|
||||
actual: ioutil.NopCloser(bytes.NewBuffer(nil)),
|
||||
peeked: pt1,
|
||||
}
|
||||
|
||||
|
||||
// returns true when peeked previously with data
|
||||
// returns true when peeked with data
|
||||
}
|
||||
*/
|
||||
|
||||
func TestJSONRequest(t *testing.T) {
|
||||
req, err := JSONRequest("GET", "/swagger.json", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "GET", req.Method)
|
||||
assert.Equal(t, JSONMime, req.Header.Get(HeaderContentType))
|
||||
assert.Equal(t, JSONMime, req.Header.Get(HeaderAccept))
|
||||
|
||||
req, err = JSONRequest("GET", "%2", nil)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, req)
|
||||
}
|
||||
|
||||
//func TestCanHaveBody(t *testing.T) {
|
||||
//assert.True(t, CanHaveBody("put"))
|
||||
//assert.True(t, CanHaveBody("post"))
|
||||
//assert.True(t, CanHaveBody("patch"))
|
||||
//assert.True(t, CanHaveBody("delete"))
|
||||
//assert.False(t, CanHaveBody(""))
|
||||
//assert.False(t, CanHaveBody("get"))
|
||||
//assert.False(t, CanHaveBody("options"))
|
||||
//assert.False(t, CanHaveBody("head"))
|
||||
//assert.False(t, CanHaveBody("invalid"))
|
||||
//}
|
||||
|
||||
func TestReadSingle(t *testing.T) {
|
||||
values := url.Values(make(map[string][]string))
|
||||
values.Add("something", "the thing")
|
||||
assert.Equal(t, "the thing", ReadSingleValue(tv(values), "something"))
|
||||
assert.Empty(t, ReadSingleValue(tv(values), "notthere"))
|
||||
}
|
||||
|
||||
func TestReadCollection(t *testing.T) {
|
||||
values := url.Values(make(map[string][]string))
|
||||
values.Add("something", "value1,value2")
|
||||
assert.Equal(t, []string{"value1", "value2"}, ReadCollectionValue(tv(values), "something", "csv"))
|
||||
assert.Empty(t, ReadCollectionValue(tv(values), "notthere", ""))
|
||||
}
|
||||
|
||||
type tv map[string][]string
|
||||
|
||||
func (v tv) GetOK(key string) (value []string, hasKey bool, hasValue bool) {
|
||||
value, hasKey = v[key]
|
||||
if !hasKey {
|
||||
return
|
||||
}
|
||||
if len(value) == 0 {
|
||||
return
|
||||
}
|
||||
hasValue = true
|
||||
return
|
||||
|
||||
}
|
||||
94
vendor/github.com/go-openapi/runtime/security/apikey_auth_test.go
generated
vendored
94
vendor/github.com/go-openapi/runtime/security/apikey_auth_test.go
generated
vendored
@@ -1,94 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package security
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var tokenAuth = TokenAuthentication(func(token string) (interface{}, error) {
|
||||
if token == "token123" {
|
||||
return "admin", nil
|
||||
}
|
||||
return nil, errors.Unauthenticated("token")
|
||||
})
|
||||
|
||||
func TestInvalidApiKeyAuthInitialization(t *testing.T) {
|
||||
assert.Panics(t, func() { APIKeyAuth("api_key", "qery", tokenAuth) })
|
||||
}
|
||||
|
||||
func TestValidApiKeyAuth(t *testing.T) {
|
||||
ta := APIKeyAuth("api_key", "query", tokenAuth)
|
||||
ta2 := APIKeyAuth("X-API-KEY", "header", tokenAuth)
|
||||
|
||||
req1, _ := http.NewRequest("GET", "/blah?api_key=token123", nil)
|
||||
|
||||
ok, usr, err := ta.Authenticate(req1)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "admin", usr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
req2, _ := http.NewRequest("GET", "/blah", nil)
|
||||
req2.Header.Set("X-API-KEY", "token123")
|
||||
|
||||
ok, usr, err = ta2.Authenticate(req2)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "admin", usr)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestInvalidApiKeyAuth(t *testing.T) {
|
||||
ta := APIKeyAuth("api_key", "query", tokenAuth)
|
||||
ta2 := APIKeyAuth("X-API-KEY", "header", tokenAuth)
|
||||
|
||||
req1, _ := http.NewRequest("GET", "/blah?api_key=token124", nil)
|
||||
|
||||
ok, usr, err := ta.Authenticate(req1)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, nil, usr)
|
||||
assert.Error(t, err)
|
||||
|
||||
req2, _ := http.NewRequest("GET", "/blah", nil)
|
||||
req2.Header.Set("X-API-KEY", "token124")
|
||||
|
||||
ok, usr, err = ta2.Authenticate(req2)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, nil, usr)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestMissingApiKeyAuth(t *testing.T) {
|
||||
ta := APIKeyAuth("api_key", "query", tokenAuth)
|
||||
ta2 := APIKeyAuth("X-API-KEY", "header", tokenAuth)
|
||||
|
||||
req1, _ := http.NewRequest("GET", "/blah", nil)
|
||||
req1.Header.Set("X-API-KEY", "token123")
|
||||
|
||||
ok, usr, err := ta.Authenticate(req1)
|
||||
assert.False(t, ok)
|
||||
assert.Equal(t, nil, usr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
req2, _ := http.NewRequest("GET", "/blah?api_key=token123", nil)
|
||||
|
||||
ok, usr, err = ta2.Authenticate(req2)
|
||||
assert.False(t, ok)
|
||||
assert.Equal(t, nil, usr)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
128
vendor/github.com/go-openapi/runtime/security/authenticator.go
generated
vendored
128
vendor/github.com/go-openapi/runtime/security/authenticator.go
generated
vendored
@@ -1,128 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package security
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
)
|
||||
|
||||
// HttpAuthenticator is a function that authenticates a HTTP request
|
||||
func HttpAuthenticator(handler func(*http.Request) (bool, interface{}, error)) runtime.Authenticator {
|
||||
return runtime.AuthenticatorFunc(func(params interface{}) (bool, interface{}, error) {
|
||||
if request, ok := params.(*http.Request); ok {
|
||||
return handler(request)
|
||||
}
|
||||
if scoped, ok := params.(*ScopedAuthRequest); ok {
|
||||
return handler(scoped.Request)
|
||||
}
|
||||
return false, nil, nil
|
||||
})
|
||||
}
|
||||
|
||||
// ScopedAuthenticator is a function that authenticates a HTTP request against a list of valid scopes
|
||||
func ScopedAuthenticator(handler func(*ScopedAuthRequest) (bool, interface{}, error)) runtime.Authenticator {
|
||||
return runtime.AuthenticatorFunc(func(params interface{}) (bool, interface{}, error) {
|
||||
if request, ok := params.(*ScopedAuthRequest); ok {
|
||||
return handler(request)
|
||||
}
|
||||
return false, nil, nil
|
||||
})
|
||||
}
|
||||
|
||||
// UserPassAuthentication authentication function
|
||||
type UserPassAuthentication func(string, string) (interface{}, error)
|
||||
|
||||
// TokenAuthentication authentication function
|
||||
type TokenAuthentication func(string) (interface{}, error)
|
||||
|
||||
// ScopedTokenAuthentication authentication function
|
||||
type ScopedTokenAuthentication func(string, []string) (interface{}, error)
|
||||
|
||||
// BasicAuth creates a basic auth authenticator with the provided authentication function
|
||||
func BasicAuth(authenticate UserPassAuthentication) runtime.Authenticator {
|
||||
return HttpAuthenticator(func(r *http.Request) (bool, interface{}, error) {
|
||||
if usr, pass, ok := r.BasicAuth(); ok {
|
||||
p, err := authenticate(usr, pass)
|
||||
return true, p, err
|
||||
}
|
||||
|
||||
return false, nil, nil
|
||||
})
|
||||
}
|
||||
|
||||
// APIKeyAuth creates an authenticator that uses a token for authorization.
|
||||
// This token can be obtained from either a header or a query string
|
||||
func APIKeyAuth(name, in string, authenticate TokenAuthentication) runtime.Authenticator {
|
||||
inl := strings.ToLower(in)
|
||||
if inl != "query" && inl != "header" {
|
||||
// panic because this is most likely a typo
|
||||
panic(errors.New(500, "api key auth: in value needs to be either \"query\" or \"header\"."))
|
||||
}
|
||||
|
||||
var getToken func(*http.Request) string
|
||||
switch inl {
|
||||
case "header":
|
||||
getToken = func(r *http.Request) string { return r.Header.Get(name) }
|
||||
case "query":
|
||||
getToken = func(r *http.Request) string { return r.URL.Query().Get(name) }
|
||||
}
|
||||
|
||||
return HttpAuthenticator(func(r *http.Request) (bool, interface{}, error) {
|
||||
token := getToken(r)
|
||||
if token == "" {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
p, err := authenticate(token)
|
||||
return true, p, err
|
||||
})
|
||||
}
|
||||
|
||||
// ScopedAuthRequest contains both a http request and the required scopes for a particular operation
|
||||
type ScopedAuthRequest struct {
|
||||
Request *http.Request
|
||||
RequiredScopes []string
|
||||
}
|
||||
|
||||
// BearerAuth for use with oauth2 flows
|
||||
func BearerAuth(name string, authenticate ScopedTokenAuthentication) runtime.Authenticator {
|
||||
const prefix = "Bearer "
|
||||
return ScopedAuthenticator(func(r *ScopedAuthRequest) (bool, interface{}, error) {
|
||||
var token string
|
||||
hdr := r.Request.Header.Get("Authorization")
|
||||
if strings.HasPrefix(hdr, prefix) {
|
||||
token = strings.TrimPrefix(hdr, prefix)
|
||||
}
|
||||
if token == "" {
|
||||
qs := r.Request.URL.Query()
|
||||
token = qs.Get("access_token")
|
||||
}
|
||||
ct, _, _ := runtime.ContentType(r.Request.Header)
|
||||
if token == "" && (ct == "application/x-www-form-urlencoded" || ct == "multipart/form-data") {
|
||||
token = r.Request.FormValue("access_token")
|
||||
}
|
||||
|
||||
if token == "" {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
p, err := authenticate(token, r.RequiredScopes)
|
||||
return true, p, err
|
||||
})
|
||||
}
|
||||
75
vendor/github.com/go-openapi/runtime/security/basic_auth_test.go
generated
vendored
75
vendor/github.com/go-openapi/runtime/security/basic_auth_test.go
generated
vendored
@@ -1,75 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package security
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var basicAuthHandler = UserPassAuthentication(func(user, pass string) (interface{}, error) {
|
||||
if user == "admin" && pass == "123456" {
|
||||
return "admin", nil
|
||||
}
|
||||
return "", errors.Unauthenticated("basic")
|
||||
})
|
||||
|
||||
func TestValidBasicAuth(t *testing.T) {
|
||||
ba := BasicAuth(basicAuthHandler)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/blah", nil)
|
||||
req.SetBasicAuth("admin", "123456")
|
||||
ok, usr, err := ba.Authenticate(req)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "admin", usr)
|
||||
}
|
||||
|
||||
func TestInvalidBasicAuth(t *testing.T) {
|
||||
ba := BasicAuth(basicAuthHandler)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/blah", nil)
|
||||
req.SetBasicAuth("admin", "admin")
|
||||
ok, usr, err := ba.Authenticate(req)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "", usr)
|
||||
}
|
||||
|
||||
func TestMissingbasicAuth(t *testing.T) {
|
||||
ba := BasicAuth(basicAuthHandler)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/blah", nil)
|
||||
|
||||
ok, usr, err := ba.Authenticate(req)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, ok)
|
||||
assert.Equal(t, nil, usr)
|
||||
}
|
||||
|
||||
func TestNoRequestBasicAuth(t *testing.T) {
|
||||
ba := BasicAuth(basicAuthHandler)
|
||||
|
||||
ok, usr, err := ba.Authenticate("token")
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, ok)
|
||||
assert.Nil(t, usr)
|
||||
}
|
||||
143
vendor/github.com/go-openapi/runtime/security/bearer_auth_test.go
generated
vendored
143
vendor/github.com/go-openapi/runtime/security/bearer_auth_test.go
generated
vendored
@@ -1,143 +0,0 @@
|
||||
package security
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var bearerAuth = ScopedTokenAuthentication(func(token string, requiredScopes []string) (interface{}, error) {
|
||||
if token == "token123" {
|
||||
return "admin", nil
|
||||
}
|
||||
return nil, errors.Unauthenticated("bearer")
|
||||
})
|
||||
|
||||
func TestValidBearerAuth(t *testing.T) {
|
||||
ba := BearerAuth("owners_auth", bearerAuth)
|
||||
|
||||
req1, _ := http.NewRequest("GET", "/blah?access_token=token123", nil)
|
||||
|
||||
ok, usr, err := ba.Authenticate(&ScopedAuthRequest{Request: req1})
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "admin", usr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
req2, _ := http.NewRequest("GET", "/blah", nil)
|
||||
req2.Header.Set("Authorization", "Bearer token123")
|
||||
|
||||
ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req2})
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "admin", usr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
body := url.Values(map[string][]string{})
|
||||
body.Set("access_token", "token123")
|
||||
req3, _ := http.NewRequest("POST", "/blah", strings.NewReader(body.Encode()))
|
||||
req3.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req3})
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "admin", usr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
mpbody := bytes.NewBuffer(nil)
|
||||
writer := multipart.NewWriter(mpbody)
|
||||
writer.WriteField("access_token", "token123")
|
||||
writer.Close()
|
||||
req4, _ := http.NewRequest("POST", "/blah", mpbody)
|
||||
req4.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req4})
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "admin", usr)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestInvalidBearerAuth(t *testing.T) {
|
||||
ba := BearerAuth("owners_auth", bearerAuth)
|
||||
|
||||
req1, _ := http.NewRequest("GET", "/blah?access_token=token124", nil)
|
||||
|
||||
ok, usr, err := ba.Authenticate(&ScopedAuthRequest{Request: req1})
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, nil, usr)
|
||||
assert.Error(t, err)
|
||||
|
||||
req2, _ := http.NewRequest("GET", "/blah", nil)
|
||||
req2.Header.Set("Authorization", "Bearer token124")
|
||||
|
||||
ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req2})
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, nil, usr)
|
||||
assert.Error(t, err)
|
||||
|
||||
body := url.Values(map[string][]string{})
|
||||
body.Set("access_token", "token124")
|
||||
req3, _ := http.NewRequest("POST", "/blah", strings.NewReader(body.Encode()))
|
||||
req3.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req3})
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, nil, usr)
|
||||
assert.Error(t, err)
|
||||
|
||||
mpbody := bytes.NewBuffer(nil)
|
||||
writer := multipart.NewWriter(mpbody)
|
||||
writer.WriteField("access_token", "token124")
|
||||
writer.Close()
|
||||
req4, _ := http.NewRequest("POST", "/blah", mpbody)
|
||||
req4.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req4})
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, nil, usr)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestMissingBearerAuth(t *testing.T) {
|
||||
ba := BearerAuth("owners_auth", bearerAuth)
|
||||
|
||||
req1, _ := http.NewRequest("GET", "/blah?access_toke=token123", nil)
|
||||
|
||||
ok, usr, err := ba.Authenticate(&ScopedAuthRequest{Request: req1})
|
||||
assert.False(t, ok)
|
||||
assert.Equal(t, nil, usr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
req2, _ := http.NewRequest("GET", "/blah", nil)
|
||||
req2.Header.Set("Authorization", "Beare token123")
|
||||
|
||||
ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req2})
|
||||
assert.False(t, ok)
|
||||
assert.Equal(t, nil, usr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
body := url.Values(map[string][]string{})
|
||||
body.Set("access_toke", "token123")
|
||||
req3, _ := http.NewRequest("POST", "/blah", strings.NewReader(body.Encode()))
|
||||
req3.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req3})
|
||||
assert.False(t, ok)
|
||||
assert.Equal(t, nil, usr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
mpbody := bytes.NewBuffer(nil)
|
||||
writer := multipart.NewWriter(mpbody)
|
||||
writer.WriteField("access_toke", "token123")
|
||||
writer.Close()
|
||||
req4, _ := http.NewRequest("POST", "/blah", mpbody)
|
||||
req4.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req4})
|
||||
assert.False(t, ok)
|
||||
assert.Equal(t, nil, usr)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
151
vendor/github.com/go-openapi/runtime/text_test.go
generated
vendored
151
vendor/github.com/go-openapi/runtime/text_test.go
generated
vendored
@@ -1,151 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var consProdText = `The quick brown fox jumped over the lazy dog.`
|
||||
|
||||
func TestTextConsumer(t *testing.T) {
|
||||
cons := TextConsumer()
|
||||
|
||||
// can consume as a string
|
||||
var str string
|
||||
err1 := cons.Consume(bytes.NewBuffer([]byte(consProdText)), &str)
|
||||
assert.NoError(t, err1)
|
||||
assert.Equal(t, consProdText, str)
|
||||
|
||||
var tu textUnmarshalDummy
|
||||
|
||||
// can consume as a TextUnmarshaler
|
||||
err3 := cons.Consume(bytes.NewBuffer([]byte(consProdText)), &tu)
|
||||
assert.NoError(t, err3)
|
||||
assert.Equal(t, consProdText, tu.str)
|
||||
|
||||
// text unmarshal objects can return an error as well, this will be propagated
|
||||
assert.Error(t, cons.Consume(bytes.NewBuffer(nil), &tu))
|
||||
|
||||
// when readers can't be read, those errors will be propogated as well
|
||||
assert.Error(t, cons.Consume(new(nopReader), &tu))
|
||||
|
||||
// readers can also not be nil
|
||||
assert.Error(t, cons.Consume(nil, &tu))
|
||||
|
||||
// can't consume nil ptr's or unsupported types
|
||||
assert.Error(t, cons.Consume(bytes.NewBuffer([]byte(consProdText)), nil))
|
||||
assert.Error(t, cons.Consume(bytes.NewBuffer([]byte(consProdText)), 42))
|
||||
assert.Error(t, cons.Consume(bytes.NewBuffer([]byte(consProdText)), &struct{}{}))
|
||||
}
|
||||
|
||||
type textUnmarshalDummy struct {
|
||||
str string
|
||||
}
|
||||
|
||||
func (t *textUnmarshalDummy) UnmarshalText(b []byte) error {
|
||||
if len(b) == 0 {
|
||||
return errors.New("no text given")
|
||||
}
|
||||
|
||||
t.str = string(b)
|
||||
return nil
|
||||
}
|
||||
|
||||
type nopReader struct{}
|
||||
|
||||
func (n *nopReader) Read(p []byte) (int, error) {
|
||||
return 0, errors.New("nop")
|
||||
}
|
||||
|
||||
func TestTextProducer(t *testing.T) {
|
||||
prod := TextProducer()
|
||||
rw := httptest.NewRecorder()
|
||||
err := prod.Produce(rw, consProdText)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, consProdText, rw.Body.String())
|
||||
rw2 := httptest.NewRecorder()
|
||||
err2 := prod.Produce(rw2, &consProdText)
|
||||
assert.NoError(t, err2)
|
||||
assert.Equal(t, consProdText, rw2.Body.String())
|
||||
|
||||
// should always work with type aliases
|
||||
// as an alias is sometimes given by generated go-swagger code
|
||||
type alias string
|
||||
aliasProdText := alias(consProdText)
|
||||
rw3 := httptest.NewRecorder()
|
||||
err3 := prod.Produce(rw3, aliasProdText)
|
||||
assert.NoError(t, err3)
|
||||
assert.Equal(t, consProdText, rw3.Body.String())
|
||||
rw4 := httptest.NewRecorder()
|
||||
err4 := prod.Produce(rw4, &aliasProdText)
|
||||
assert.NoError(t, err4)
|
||||
assert.Equal(t, consProdText, rw4.Body.String())
|
||||
|
||||
const answer = "42"
|
||||
|
||||
// Should always work with objects implementing Stringer interface
|
||||
rw5 := httptest.NewRecorder()
|
||||
err5 := prod.Produce(rw5, &stringerDummy{answer})
|
||||
assert.NoError(t, err5)
|
||||
assert.Equal(t, answer, rw5.Body.String())
|
||||
|
||||
// Should always work with objects implementing TextMarshaler interface
|
||||
rw6 := httptest.NewRecorder()
|
||||
err6 := prod.Produce(rw6, &textMarshalDummy{answer})
|
||||
assert.NoError(t, err6)
|
||||
assert.Equal(t, answer, rw6.Body.String())
|
||||
|
||||
// should not work with anything that's not (indirectly) a string
|
||||
rw7 := httptest.NewRecorder()
|
||||
err7 := prod.Produce(rw7, 42)
|
||||
assert.Error(t, err7)
|
||||
// nil values should also be safely caught with an error
|
||||
rw8 := httptest.NewRecorder()
|
||||
err8 := prod.Produce(rw8, nil)
|
||||
assert.Error(t, err8)
|
||||
|
||||
// writer can not be nil
|
||||
assert.Error(t, prod.Produce(nil, &textMarshalDummy{answer}))
|
||||
|
||||
// should not work for a textMarshaler that returns an error during marshalling
|
||||
rw9 := httptest.NewRecorder()
|
||||
err9 := prod.Produce(rw9, new(textMarshalDummy))
|
||||
assert.Error(t, err9)
|
||||
}
|
||||
|
||||
type stringerDummy struct {
|
||||
str string
|
||||
}
|
||||
|
||||
func (t *stringerDummy) String() string {
|
||||
return t.str
|
||||
}
|
||||
|
||||
type textMarshalDummy struct {
|
||||
str string
|
||||
}
|
||||
|
||||
func (t *textMarshalDummy) MarshalText() ([]byte, error) {
|
||||
if t.str == "" {
|
||||
return nil, errors.New("no text set")
|
||||
}
|
||||
return []byte(t.str), nil
|
||||
}
|
||||
53
vendor/github.com/go-openapi/runtime/xml_test.go
generated
vendored
53
vendor/github.com/go-openapi/runtime/xml_test.go
generated
vendored
@@ -1,53 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var consProdXML = `<person><name>Somebody</name><id>1</id></person>`
|
||||
|
||||
func TestXMLConsumer(t *testing.T) {
|
||||
cons := XMLConsumer()
|
||||
var data struct {
|
||||
XMLName xml.Name `xml:"person"`
|
||||
Name string `xml:"name"`
|
||||
ID int `xml:"id"`
|
||||
}
|
||||
err := cons.Consume(bytes.NewBuffer([]byte(consProdXML)), &data)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Somebody", data.Name)
|
||||
assert.Equal(t, 1, data.ID)
|
||||
}
|
||||
|
||||
func TestXMLProducer(t *testing.T) {
|
||||
prod := XMLProducer()
|
||||
data := struct {
|
||||
XMLName xml.Name `xml:"person"`
|
||||
Name string `xml:"name"`
|
||||
ID int `xml:"id"`
|
||||
}{Name: "Somebody", ID: 1}
|
||||
|
||||
rw := httptest.NewRecorder()
|
||||
err := prod.Produce(rw, data)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, consProdXML, rw.Body.String())
|
||||
}
|
||||
44
vendor/github.com/go-openapi/runtime/yamlpc/yaml.go
generated
vendored
44
vendor/github.com/go-openapi/runtime/yamlpc/yaml.go
generated
vendored
@@ -1,44 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package yamlpc
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// YAMLConsumer creates a consumer for yaml data
|
||||
func YAMLConsumer() runtime.Consumer {
|
||||
return runtime.ConsumerFunc(func(r io.Reader, v interface{}) error {
|
||||
buf, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return yaml.Unmarshal(buf, v)
|
||||
})
|
||||
}
|
||||
|
||||
// YAMLProducer creates a producer for yaml data
|
||||
func YAMLProducer() runtime.Producer {
|
||||
return runtime.ProducerFunc(func(w io.Writer, v interface{}) error {
|
||||
b, _ := yaml.Marshal(v) // can't make this error come up
|
||||
_, err := w.Write(b)
|
||||
return err
|
||||
})
|
||||
}
|
||||
62
vendor/github.com/go-openapi/runtime/yamlpc/yaml_test.go
generated
vendored
62
vendor/github.com/go-openapi/runtime/yamlpc/yaml_test.go
generated
vendored
@@ -1,62 +0,0 @@
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package yamlpc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var consProdYAML = "name: Somebody\nid: 1\n"
|
||||
|
||||
func TestYAMLConsumer(t *testing.T) {
|
||||
cons := YAMLConsumer()
|
||||
var data struct {
|
||||
Name string
|
||||
ID int
|
||||
}
|
||||
err := cons.Consume(bytes.NewBuffer([]byte(consProdYAML)), &data)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Somebody", data.Name)
|
||||
assert.Equal(t, 1, data.ID)
|
||||
}
|
||||
|
||||
func TestYAMLProducer(t *testing.T) {
|
||||
prod := YAMLProducer()
|
||||
data := struct {
|
||||
Name string `yaml:"name"`
|
||||
ID int `yaml:"id"`
|
||||
}{Name: "Somebody", ID: 1}
|
||||
|
||||
rw := httptest.NewRecorder()
|
||||
err := prod.Produce(rw, data)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, consProdYAML, rw.Body.String())
|
||||
}
|
||||
|
||||
type failReader struct {
|
||||
}
|
||||
|
||||
func (f *failReader) Read(p []byte) (n int, err error) {
|
||||
return 0, errors.New("expected")
|
||||
}
|
||||
func TestFailYAMLReader(t *testing.T) {
|
||||
cons := YAMLConsumer()
|
||||
assert.Error(t, cons.Consume(&failReader{}, nil))
|
||||
}
|
||||
Reference in New Issue
Block a user