diff -Nru golang-github-go-openapi-runtime-0.15.0/authinfo_test.go golang-github-go-openapi-runtime-0.21.0/authinfo_test.go --- golang-github-go-openapi-runtime-0.15.0/authinfo_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/authinfo_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -26,7 +26,7 @@ return r.SetHeaderParam("authorization", "Bearer the-token-goes-here") }) - tr := new(trw) + tr := new(TestClientRequest) err := hand.AuthenticateRequest(tr, nil) assert.NoError(t, err) assert.Equal(t, "Bearer the-token-goes-here", tr.Headers.Get("Authorization")) diff -Nru golang-github-go-openapi-runtime-0.15.0/bytestream.go golang-github-go-openapi-runtime-0.21.0/bytestream.go --- golang-github-go-openapi-runtime-0.15.0/bytestream.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/bytestream.go 2021-10-29 03:50:47.000000000 +0000 @@ -109,6 +109,10 @@ } defer close() + if rc, ok := data.(io.ReadCloser); ok { + defer rc.Close() + } + if rdr, ok := data.(io.Reader); ok { _, err := io.Copy(writer, rdr) return err @@ -125,6 +129,11 @@ } if data != nil { + if str, ok := data.(string); ok { + _, err := writer.Write([]byte(str)) + return err + } + if e, ok := data.(error); ok { _, err := writer.Write([]byte(e.Error())) return err diff -Nru golang-github-go-openapi-runtime-0.15.0/bytestream_test.go golang-github-go-openapi-runtime-0.21.0/bytestream_test.go --- golang-github-go-openapi-runtime-0.15.0/bytestream_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/bytestream_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -84,6 +84,12 @@ rdr.Reset() } + // string can also be used to produce + if assert.NoError(t, cons.Produce(&rdr, 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()) @@ -217,4 +223,14 @@ assert.Equal(t, expected, r.String()) assert.EqualValues(t, 0, r.calledClose) } + + cons = ByteStreamProducer() + r = &closingWriter{} + data := &closingReader{b: bytes.NewBufferString(expected)} + // can produce using a readcloser + if assert.NoError(t, cons.Produce(r, data)) { + assert.Equal(t, expected, r.String()) + assert.EqualValues(t, 0, r.calledClose) + assert.EqualValues(t, 1, data.calledClose) + } } diff -Nru golang-github-go-openapi-runtime-0.15.0/client/auth_info.go golang-github-go-openapi-runtime-0.21.0/client/auth_info.go --- golang-github-go-openapi-runtime-0.15.0/client/auth_info.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client/auth_info.go 2021-10-29 03:50:47.000000000 +0000 @@ -17,8 +17,9 @@ import ( "encoding/base64" - "github.com/go-openapi/runtime" "github.com/go-openapi/strfmt" + + "github.com/go-openapi/runtime" ) // PassThroughAuth never manipulates the request @@ -58,3 +59,19 @@ return r.SetHeaderParam("Authorization", "Bearer "+token) }) } + +// Compose combines multiple ClientAuthInfoWriters into a single one. +// Useful when multiple auth headers are needed. +func Compose(auths ...runtime.ClientAuthInfoWriter) runtime.ClientAuthInfoWriter { + return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error { + for _, auth := range auths { + if auth == nil { + continue + } + if err := auth.AuthenticateRequest(r, nil); err != nil { + return err + } + } + return nil + }) +} diff -Nru golang-github-go-openapi-runtime-0.15.0/client/auth_info_test.go golang-github-go-openapi-runtime-0.21.0/client/auth_info_test.go --- golang-github-go-openapi-runtime-0.15.0/client/auth_info_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client/auth_info_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -67,3 +67,14 @@ assert.Equal(t, "Bearer the-shared-token", r.header.Get("Authorization")) } + +func TestCompose(t *testing.T) { + r, _ := newRequest("GET", "/", nil) + + writer := Compose(APIKeyAuth("x-api-key", "header", "the-api-key"), APIKeyAuth("x-secret-key", "header", "the-secret-key")) + err := writer.AuthenticateRequest(r, nil) + assert.NoError(t, err) + + assert.Equal(t, "the-api-key", r.header.Get("x-api-key")) + assert.Equal(t, "the-secret-key", r.header.Get("x-secret-key")) +} diff -Nru golang-github-go-openapi-runtime-0.15.0/client/keepalive_test.go golang-github-go-openapi-runtime-0.21.0/client/keepalive_test.go --- golang-github-go-openapi-runtime-0.15.0/client/keepalive_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client/keepalive_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -7,6 +7,7 @@ "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func newCountingReader(rdr io.Reader, readOnce bool) *countingReadCloser { @@ -45,7 +46,8 @@ buf := make([]byte, 5) ts := &drainingReadCloser{rdr: rdr} - ts.Read(buf) + _, err := ts.Read(buf) + require.NoError(t, err) ts.Close() assert.Equal(t, "There", string(buf)) assert.Equal(t, " are many things to do", disc.String()) @@ -62,8 +64,9 @@ buf := make([]byte, 5) ts := &drainingReadCloser{rdr: rdr} - ts.Read(buf) - _, err := ts.Read(nil) + _, err := ts.Read(buf) + assert.NoError(t, err) + _, err = ts.Read(nil) assert.Equal(t, io.EOF, err) ts.Close() assert.Equal(t, string(buf), "There") diff -Nru golang-github-go-openapi-runtime-0.15.0/client/opentracing.go golang-github-go-openapi-runtime-0.21.0/client/opentracing.go --- golang-github-go-openapi-runtime-0.15.0/client/opentracing.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client/opentracing.go 2021-10-29 03:50:47.000000000 +0000 @@ -0,0 +1,99 @@ +package client + +import ( + "fmt" + "net/http" + + "github.com/go-openapi/strfmt" + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" + "github.com/opentracing/opentracing-go/log" + + "github.com/go-openapi/runtime" +) + +type tracingTransport struct { + transport runtime.ClientTransport + host string + opts []opentracing.StartSpanOption +} + +func newOpenTracingTransport(transport runtime.ClientTransport, host string, opts []opentracing.StartSpanOption, +) runtime.ClientTransport { + return &tracingTransport{ + transport: transport, + host: host, + opts: opts, + } +} + +func (t *tracingTransport) Submit(op *runtime.ClientOperation) (interface{}, error) { + if op.Context == nil { + return t.transport.Submit(op) + } + + params := op.Params + reader := op.Reader + + var span opentracing.Span + defer func() { + if span != nil { + span.Finish() + } + }() + + op.Params = runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error { + span = createClientSpan(op, req.GetHeaderParams(), t.host, t.opts) + return params.WriteToRequest(req, reg) + }) + + op.Reader = runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + if span != nil { + code := response.Code() + ext.HTTPStatusCode.Set(span, uint16(code)) + if code >= 400 { + ext.Error.Set(span, true) + } + } + return reader.ReadResponse(response, consumer) + }) + + submit, err := t.transport.Submit(op) + if err != nil && span != nil { + ext.Error.Set(span, true) + span.LogFields(log.Error(err)) + } + return submit, err +} + +func createClientSpan(op *runtime.ClientOperation, header http.Header, host string, + opts []opentracing.StartSpanOption) opentracing.Span { + ctx := op.Context + span := opentracing.SpanFromContext(ctx) + + if span != nil { + opts = append(opts, ext.SpanKindRPCClient) + span, _ = opentracing.StartSpanFromContextWithTracer( + ctx, span.Tracer(), operationName(op), opts...) + + ext.Component.Set(span, "go-openapi") + ext.PeerHostname.Set(span, host) + span.SetTag("http.path", op.PathPattern) + ext.HTTPMethod.Set(span, op.Method) + + _ = span.Tracer().Inject( + span.Context(), + opentracing.HTTPHeaders, + opentracing.HTTPHeadersCarrier(header)) + + return span + } + return nil +} + +func operationName(op *runtime.ClientOperation) string { + if op.ID != "" { + return op.ID + } + return fmt.Sprintf("%s_%s", op.Method, op.PathPattern) +} diff -Nru golang-github-go-openapi-runtime-0.15.0/client/opentracing_test.go golang-github-go-openapi-runtime-0.21.0/client/opentracing_test.go --- golang-github-go-openapi-runtime-0.15.0/client/opentracing_test.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client/opentracing_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -0,0 +1,133 @@ +package client + +import ( + "bytes" + "context" + "io" + "io/ioutil" + "testing" + + "github.com/go-openapi/strfmt" + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" + "github.com/opentracing/opentracing-go/mocktracer" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/go-openapi/runtime" +) + +type tres struct { +} + +func (r tres) Code() int { + return 490 +} +func (r tres) Message() string { + return "the message" +} +func (r tres) GetHeader(_ string) string { + return "the header" +} +func (r tres) GetHeaders(_ string) []string { + return []string{"the headers", "the headers2"} +} +func (r tres) Body() io.ReadCloser { + return ioutil.NopCloser(bytes.NewBufferString("the content")) +} + +type mockRuntime struct { + req runtime.TestClientRequest +} + +func (m *mockRuntime) Submit(operation *runtime.ClientOperation) (interface{}, error) { + _ = operation.Params.WriteToRequest(&m.req, nil) + _, _ = operation.Reader.ReadResponse(&tres{}, nil) + return nil, nil +} + +func testOperation(ctx context.Context) *runtime.ClientOperation { + return &runtime.ClientOperation{ + ID: "getCluster", + Method: "GET", + PathPattern: "/kubernetes-clusters/{cluster_id}", + ProducesMediaTypes: []string{"application/json"}, + ConsumesMediaTypes: []string{"application/json"}, + Schemes: []string{"https"}, + Reader: runtime.ClientResponseReaderFunc(func(runtime.ClientResponse, runtime.Consumer) (interface{}, error) { + return nil, nil + }), + Params: runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error { + return nil + }), + AuthInfo: PassThroughAuth, + Context: ctx, + } +} + +func Test_TracingRuntime_submit(t *testing.T) { + t.Parallel() + tracer := mocktracer.New() + _, ctx := opentracing.StartSpanFromContextWithTracer(context.Background(), tracer, "op") + testSubmit(t, testOperation(ctx), tracer, 1) +} + +func Test_TracingRuntime_submit_nilAuthInfo(t *testing.T) { + t.Parallel() + tracer := mocktracer.New() + _, ctx := opentracing.StartSpanFromContextWithTracer(context.Background(), tracer, "op") + operation := testOperation(ctx) + operation.AuthInfo = nil + testSubmit(t, operation, tracer, 1) +} + +func Test_TracingRuntime_submit_nilContext(t *testing.T) { + t.Parallel() + tracer := mocktracer.New() + _, ctx := opentracing.StartSpanFromContextWithTracer(context.Background(), tracer, "op") + operation := testOperation(ctx) + operation.Context = nil + testSubmit(t, operation, tracer, 0) // just don't panic +} + +func testSubmit(t *testing.T, operation *runtime.ClientOperation, tracer *mocktracer.MockTracer, expectedSpans int) { + + header := map[string][]string{} + r := newOpenTracingTransport(&mockRuntime{runtime.TestClientRequest{Headers: header}}, + "remote_host", + []opentracing.StartSpanOption{opentracing.Tag{ + Key: string(ext.PeerService), + Value: "service", + }}) + + _, err := r.Submit(operation) + require.NoError(t, err) + + assert.Len(t, tracer.FinishedSpans(), expectedSpans) + + if expectedSpans == 1 { + span := tracer.FinishedSpans()[0] + assert.Equal(t, "getCluster", span.OperationName) + assert.Equal(t, map[string]interface{}{ + "component": "go-openapi", + "http.method": "GET", + "http.path": "/kubernetes-clusters/{cluster_id}", + "http.status_code": uint16(490), + "peer.hostname": "remote_host", + "peer.service": "service", + "span.kind": ext.SpanKindRPCClientEnum, + "error": true, + }, span.Tags()) + } +} + +func Test_injectSpanContext(t *testing.T) { + t.Parallel() + tracer := mocktracer.New() + _, ctx := opentracing.StartSpanFromContextWithTracer(context.Background(), tracer, "op") + header := map[string][]string{} + createClientSpan(testOperation(ctx), header, "", nil) + + // values are random - just check that something was injected + assert.Len(t, header, 3) +} diff -Nru golang-github-go-openapi-runtime-0.15.0/client/request.go golang-github-go-openapi-runtime-0.21.0/client/request.go --- golang-github-go-openapi-runtime-0.15.0/client/request.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client/request.go 2021-10-29 03:50:47.000000000 +0000 @@ -18,10 +18,10 @@ "bytes" "fmt" "io" - "io/ioutil" "log" "mime/multipart" "net/http" + "net/textproto" "net/url" "os" "path" @@ -29,8 +29,9 @@ "strings" "time" - "github.com/go-openapi/runtime" "github.com/go-openapi/strfmt" + + "github.com/go-openapi/runtime" ) // NewRequest creates a new swagger http client request @@ -42,6 +43,7 @@ header: make(http.Header), query: make(url.Values), timeout: DefaultTimeout, + getBody: getRequestBuffer, }, nil } @@ -67,6 +69,8 @@ payload interface{} timeout time.Duration buf *bytes.Buffer + + getBody func(r *request) []byte } var ( @@ -86,67 +90,43 @@ func (r *request) BuildHTTP(mediaType, basePath string, producers map[string]runtime.Producer, registry strfmt.Registry) (*http.Request, error) { return r.buildHTTP(mediaType, basePath, producers, registry, nil) } - +func escapeQuotes(s string) string { + return strings.NewReplacer("\\", "\\\\", `"`, "\\\"").Replace(s) +} func (r *request) buildHTTP(mediaType, basePath string, producers map[string]runtime.Producer, registry strfmt.Registry, auth runtime.ClientAuthInfoWriter) (*http.Request, error) { // build the data if err := r.writer.WriteToRequest(r, registry); err != nil { return nil, err } - if auth != nil { - if err := auth.AuthenticateRequest(r, registry); err != nil { - return nil, err - } - } - - // create http request - var reinstateSlash bool - if r.pathPattern != "" && r.pathPattern != "/" && r.pathPattern[len(r.pathPattern)-1] == '/' { - reinstateSlash = true - } - urlPath := path.Join(basePath, r.pathPattern) - for k, v := range r.pathParams { - urlPath = strings.Replace(urlPath, "{"+k+"}", url.PathEscape(v), -1) - } - if reinstateSlash { - urlPath = urlPath + "/" - } - - var body io.ReadCloser + // Our body must be an io.Reader. + // When we create the http.Request, if we pass it a + // bytes.Buffer then it will wrap it in an io.ReadCloser + // and set the content length automatically. + var body io.Reader var pr *io.PipeReader var pw *io.PipeWriter r.buf = bytes.NewBuffer(nil) if r.payload != nil || len(r.formFields) > 0 || len(r.fileFields) > 0 { - body = ioutil.NopCloser(r.buf) + body = r.buf if r.isMultipart(mediaType) { pr, pw = io.Pipe() body = pr } } - req, err := http.NewRequest(r.method, urlPath, body) - - if err != nil { - return nil, err - } - - req.URL.RawQuery = r.query.Encode() - req.Header = r.header // check if this is a form type request if len(r.formFields) > 0 || len(r.fileFields) > 0 { if !r.isMultipart(mediaType) { - req.Header.Set(runtime.HeaderContentType, mediaType) + r.header.Set(runtime.HeaderContentType, mediaType) formString := r.formFields.Encode() - // set content length before writing to the buffer - req.ContentLength = int64(len(formString)) - // write the form values as the body r.buf.WriteString(formString) - return req, nil + goto DoneChoosingBodySource } mp := multipart.NewWriter(pw) - req.Header.Set(runtime.HeaderContentType, mangleContentType(mediaType, mp.Boundary())) + r.header.Set(runtime.HeaderContentType, mangleContentType(mediaType, mp.Boundary())) go func() { defer func() { @@ -159,6 +139,7 @@ if err := mp.WriteField(fn, vi); err != nil { pw.CloseWithError(err) log.Println(err) + return } } } @@ -172,21 +153,39 @@ }() for fn, f := range r.fileFields { for _, fi := range f { - wrtr, err := mp.CreateFormFile(fn, filepath.Base(fi.Name())) + // Need to read the data so that we can detect the content type + buf := make([]byte, 512) + size, err := fi.Read(buf) + if err != nil { + _ = pw.CloseWithError(err) + log.Println(err) + return + } + fileContentType := http.DetectContentType(buf) + newFi := runtime.NamedReader(fi.Name(), io.MultiReader(bytes.NewReader(buf[:size]), fi)) + + // Create the MIME headers for the new part + h := make(textproto.MIMEHeader) + h.Set("Content-Disposition", + fmt.Sprintf(`form-data; name="%s"; filename="%s"`, + escapeQuotes(fn), escapeQuotes(filepath.Base(fi.Name())))) + h.Set("Content-Type", fileContentType) + + wrtr, err := mp.CreatePart(h) if err != nil { pw.CloseWithError(err) log.Println(err) + return } - if _, err := io.Copy(wrtr, fi); err != nil { + if _, err := io.Copy(wrtr, newFi); err != nil { pw.CloseWithError(err) log.Println(err) } } } - }() - return req, nil + goto DoneChoosingBodySource } // if there is payload, use the producer to write the payload, and then @@ -194,59 +193,145 @@ if r.payload != nil { // TODO: infer most appropriate content type based on the producer used, // and the `consumers` section of the spec/operation - req.Header.Set(runtime.HeaderContentType, mediaType) + r.header.Set(runtime.HeaderContentType, mediaType) if rdr, ok := r.payload.(io.ReadCloser); ok { - req.Body = rdr - - return req, nil + body = rdr + goto DoneChoosingBodySource } if rdr, ok := r.payload.(io.Reader); ok { - req.Body = ioutil.NopCloser(rdr) + body = rdr + goto DoneChoosingBodySource + } - return req, nil + producer := producers[mediaType] + if err := producer.Produce(r.buf, r.payload); err != nil { + return nil, err } + } - req.GetBody = func() (io.ReadCloser, error) { - var b bytes.Buffer - producer := producers[mediaType] - if err := producer.Produce(&b, r.payload); err != nil { - return nil, err - } +DoneChoosingBodySource: - if _, err := r.buf.Write(b.Bytes()); err != nil { - return nil, err - } - return ioutil.NopCloser(&b), nil - } + if runtime.CanHaveBody(r.method) && body == nil && r.header.Get(runtime.HeaderContentType) == "" { + r.header.Set(runtime.HeaderContentType, mediaType) + } - // set the content length of the request or else a chunked transfer is - // declared, and this corrupts outgoing JSON payloads. the content's - // length must be set prior to the body being written per the spec at - // https://golang.org/pkg/net/http + if auth != nil { + // If we're not using r.buf as our http.Request's body, + // either the payload is an io.Reader or io.ReadCloser, + // or we're doing a multipart form/file. // - // If Body is present, Content-Length is <= 0 and TransferEncoding - // hasn't been set to "identity", Write adds - // "Transfer-Encoding: chunked" to the header. Body is closed - // after it is sent. + // In those cases, if the AuthenticateRequest call asks for the body, + // we must read it into a buffer and provide that, then use that buffer + // as the body of our http.Request. // - // to that end a temporary buffer, b, is created to produce the payload - // body, and then its size is used to set the request's content length - var b bytes.Buffer - producer := producers[mediaType] - if err := producer.Produce(&b, r.payload); err != nil { - return nil, err + // This is done in-line with the GetBody() request rather than ahead + // of time, because there's no way to know if the AuthenticateRequest + // will even ask for the body of the request. + // + // If for some reason the copy fails, there's no way to return that + // error to the GetBody() call, so return it afterwards. + // + // An error from the copy action is prioritized over any error + // from the AuthenticateRequest call, because the mis-read + // body may have interfered with the auth. + // + var copyErr error + if buf, ok := body.(*bytes.Buffer); body != nil && (!ok || buf != r.buf) { + var copied bool + r.getBody = func(r *request) []byte { + if copied { + return getRequestBuffer(r) + } + + defer func() { + copied = true + }() + + if _, copyErr = io.Copy(r.buf, body); copyErr != nil { + return nil + } + + if closer, ok := body.(io.ReadCloser); ok { + if copyErr = closer.Close(); copyErr != nil { + return nil + } + } + + body = r.buf + return getRequestBuffer(r) + } } - req.ContentLength = int64(b.Len()) - if _, err := r.buf.Write(b.Bytes()); err != nil { - return nil, err + + authErr := auth.AuthenticateRequest(r, registry) + + if copyErr != nil { + return nil, fmt.Errorf("error retrieving the response body: %v", copyErr) + } + + if authErr != nil { + return nil, authErr + } + } + + // In case the basePath or the request pathPattern include static query parameters, + // parse those out before constructing the final path. The parameters themselves + // will be merged with the ones set by the client, with the priority given first to + // the ones set by the client, then the path pattern, and lastly the base path. + basePathURL, err := url.Parse(basePath) + if err != nil { + return nil, err + } + staticQueryParams := basePathURL.Query() + + pathPatternURL, err := url.Parse(r.pathPattern) + if err != nil { + return nil, err + } + for name, values := range pathPatternURL.Query() { + if _, present := staticQueryParams[name]; present { + staticQueryParams.Del(name) + } + for _, value := range values { + staticQueryParams.Add(name, value) } } - if runtime.CanHaveBody(req.Method) && req.Body == nil && req.Header.Get(runtime.HeaderContentType) == "" { - req.Header.Set(runtime.HeaderContentType, mediaType) + // create http request + var reinstateSlash bool + if pathPatternURL.Path != "" && pathPatternURL.Path != "/" && pathPatternURL.Path[len(pathPatternURL.Path)-1] == '/' { + reinstateSlash = true } + urlPath := path.Join(basePathURL.Path, pathPatternURL.Path) + for k, v := range r.pathParams { + urlPath = strings.Replace(urlPath, "{"+k+"}", url.PathEscape(v), -1) + } + if reinstateSlash { + urlPath = urlPath + "/" + } + + req, err := http.NewRequest(r.method, urlPath, body) + if err != nil { + return nil, err + } + + originalParams := r.GetQueryParams() + + // Merge the query parameters extracted from the basePath with the ones set by + // the client in this struct. In case of conflict, the client wins. + for k, v := range staticQueryParams { + _, present := originalParams[k] + if !present { + if err = r.SetQueryParam(k, v...); err != nil { + return nil, err + } + } + } + + req.URL.RawQuery = r.query.Encode() + req.Header = r.header + return req, nil } @@ -270,6 +355,10 @@ } func (r *request) GetBody() []byte { + return r.getBody(r) +} + +func getRequestBuffer(r *request) []byte { if r.buf == nil { return nil } @@ -287,6 +376,11 @@ return nil } +// GetHeaderParams returns the all headers currently set for the request +func (r *request) GetHeaderParams() http.Header { + return r.header +} + // SetQueryParam adds a query param to the request // when there is only 1 value provided for the varargs, it will set it. // when there are several values provided for the varargs it will add it (no overriding) @@ -353,6 +447,10 @@ return nil } +func (r *request) GetFileParam() map[string][]runtime.NamedReadCloser { + return r.fileFields +} + // SetBodyParam sets a body parameter on the request. // This does not yet serialze the object, this happens as late as possible. func (r *request) SetBodyParam(payload interface{}) error { @@ -360,6 +458,10 @@ return nil } +func (r *request) GetBodyParam() interface{} { + return r.payload +} + // SetTimeout sets the timeout for a request func (r *request) SetTimeout(timeout time.Duration) error { r.timeout = timeout diff -Nru golang-github-go-openapi-runtime-0.15.0/client/request_test.go golang-github-go-openapi-runtime-0.21.0/client/request_test.go --- golang-github-go-openapi-runtime-0.15.0/client/request_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client/request_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -18,17 +18,24 @@ "bytes" "encoding/json" "encoding/xml" + "errors" + "io" "io/ioutil" "mime" "mime/multipart" + "net/http" + "net/http/httptest" + "net/url" "os" "path/filepath" "strings" "testing" - "github.com/go-openapi/runtime" "github.com/go-openapi/strfmt" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/go-openapi/runtime" ) var testProducers = map[string]runtime.Producer{ @@ -509,3 +516,145 @@ assert.Equal(t, runtime.JSONMime, req.Header.Get(runtime.HeaderContentType)) } } + +func TestBuildRequest_BuildHTTP_BasePathWithQueryParameters(t *testing.T) { + reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error { + _ = req.SetBodyParam(nil) + _ = req.SetQueryParam("hello", "world") + _ = req.SetPathParam("id", "1234") + return nil + }) + r, _ := newRequest("POST", "/flats/{id}/", reqWrtr) + + req, err := r.BuildHTTP(runtime.JSONMime, "/basepath?foo=bar", testProducers, nil) + if assert.NoError(t, err) && assert.NotNil(t, req) { + assert.Equal(t, "world", req.URL.Query().Get("hello")) + assert.Equal(t, "bar", req.URL.Query().Get("foo")) + assert.Equal(t, "/basepath/flats/1234/", req.URL.Path) + } +} + +func TestBuildRequest_BuildHTTP_PathPatternWithQueryParameters(t *testing.T) { + reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error { + _ = req.SetBodyParam(nil) + _ = req.SetQueryParam("hello", "world") + _ = req.SetPathParam("id", "1234") + return nil + }) + r, _ := newRequest("POST", "/flats/{id}/?foo=bar", reqWrtr) + + req, err := r.BuildHTTP(runtime.JSONMime, "/basepath", testProducers, nil) + if assert.NoError(t, err) && assert.NotNil(t, req) { + assert.Equal(t, "world", req.URL.Query().Get("hello")) + assert.Equal(t, "bar", req.URL.Query().Get("foo")) + assert.Equal(t, "/basepath/flats/1234/", req.URL.Path) + } +} + +func TestBuildRequest_BuildHTTP_StaticParametersPathPatternPrevails(t *testing.T) { + reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error { + _ = req.SetBodyParam(nil) + _ = req.SetPathParam("id", "1234") + return nil + }) + r, _ := newRequest("POST", "/flats/{id}/?hello=world", reqWrtr) + + req, err := r.BuildHTTP(runtime.JSONMime, "/basepath?hello=kitty", testProducers, nil) + if assert.NoError(t, err) && assert.NotNil(t, req) { + assert.Equal(t, "world", req.URL.Query().Get("hello")) + assert.Equal(t, "/basepath/flats/1234/", req.URL.Path) + } +} + +func TestBuildRequest_BuildHTTP_StaticParametersConflictClientPrevails(t *testing.T) { + reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error { + _ = req.SetBodyParam(nil) + _ = req.SetQueryParam("hello", "there") + _ = req.SetPathParam("id", "1234") + return nil + }) + r, _ := newRequest("POST", "/flats/{id}/?hello=world", reqWrtr) + + req, err := r.BuildHTTP(runtime.JSONMime, "/basepath?hello=kitty", testProducers, nil) + if assert.NoError(t, err) && assert.NotNil(t, req) { + assert.Equal(t, "there", req.URL.Query().Get("hello")) + assert.Equal(t, "/basepath/flats/1234/", req.URL.Path) + } +} + +type testReqFn func(*testing.T, *http.Request) + +type testRoundTripper struct { + tr http.RoundTripper + testFn testReqFn + testHarness *testing.T +} + +func (t *testRoundTripper) RoundTrip(req *http.Request) (resp *http.Response, err error) { + t.testFn(t.testHarness, req) + return t.tr.RoundTrip(req) +} + +func TestGetBodyCallsBeforeRoundTrip(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.WriteHeader(http.StatusCreated) + _, err := rw.Write([]byte("test result")) + require.NoError(t, err) + })) + defer server.Close() + hu, _ := url.Parse(server.URL) + + client := http.DefaultClient + transport := http.DefaultTransport + + client.Transport = &testRoundTripper{ + tr: transport, + testHarness: t, + testFn: func(t *testing.T, req *http.Request) { + // Read the body once before sending the request + body, err := req.GetBody() + require.NoError(t, err) + bodyContent, err := ioutil.ReadAll(io.Reader(body)) + require.EqualValues(t, req.ContentLength, len(bodyContent)) + require.NoError(t, err) + require.EqualValues(t, "\"test body\"\n", string(bodyContent)) + + // Read the body a second time before sending the request + body, err = req.GetBody() + require.NoError(t, err) + bodyContent, err = ioutil.ReadAll(io.Reader(body)) + require.NoError(t, err) + require.EqualValues(t, req.ContentLength, len(bodyContent)) + require.EqualValues(t, "\"test body\"\n", string(bodyContent)) + }, + } + + rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error { + return req.SetBodyParam("test body") + }) + + operation := &runtime.ClientOperation{ + ID: "getSites", + Method: "POST", + PathPattern: "/", + Params: rwrtr, + Client: client, + Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + if response.Code() == http.StatusCreated { + var result string + if err := consumer.Consume(response.Body(), &result); err != nil { + return nil, err + } + return result, nil + } + return nil, errors.New("Unexpected error code") + }), + } + + openAPIClient := New(hu.Host, "/", []string{"http"}) + res, err := openAPIClient.Submit(operation) + + require.NoError(t, err) + actual := res.(string) + require.EqualValues(t, "test result", actual) +} diff -Nru golang-github-go-openapi-runtime-0.15.0/client/response.go golang-github-go-openapi-runtime-0.21.0/client/response.go --- golang-github-go-openapi-runtime-0.15.0/client/response.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client/response.go 2021-10-29 03:50:47.000000000 +0000 @@ -39,6 +39,10 @@ return r.resp.Header.Get(name) } +func (r response) GetHeaders(name string) []string { + return r.resp.Header.Values(name) +} + func (r response) Body() io.ReadCloser { return r.resp.Body } diff -Nru golang-github-go-openapi-runtime-0.15.0/client/response_test.go golang-github-go-openapi-runtime-0.21.0/client/response_test.go --- golang-github-go-openapi-runtime-0.15.0/client/response_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client/response_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -20,8 +20,9 @@ "net/http" "testing" - "github.com/go-openapi/runtime" "github.com/stretchr/testify/assert" + + "github.com/go-openapi/runtime" ) func TestResponse(t *testing.T) { @@ -36,5 +37,6 @@ 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, []string{"blah blah"}, resp.GetHeaders("blah")) assert.Equal(t, under.Body, resp.Body()) } diff -Nru golang-github-go-openapi-runtime-0.15.0/client/runtime.go golang-github-go-openapi-runtime-0.21.0/client/runtime.go --- golang-github-go-openapi-runtime-0.15.0/client/runtime.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client/runtime.go 2021-10-29 03:50:47.000000000 +0000 @@ -15,6 +15,7 @@ package client import ( + "context" "crypto" "crypto/ecdsa" "crypto/rsa" @@ -30,13 +31,13 @@ "sync" "time" - "golang.org/x/net/context" - "golang.org/x/net/context/ctxhttp" + "github.com/go-openapi/strfmt" + "github.com/opentracing/opentracing-go" "github.com/go-openapi/runtime" "github.com/go-openapi/runtime/logger" "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/strfmt" + "github.com/go-openapi/runtime/yamlpc" ) // TLSClientOptions to configure client authentication with mutual TLS @@ -68,15 +69,42 @@ // If this field (and CA) is not set, the system certificate pool is used. LoadedCA *x509.Certificate + // LoadedCAPool specifies a pool of RootCAs to use when validating the server's TLS certificate. + // If set, it will be combined with the the other loaded certificates (see LoadedCA and CA). + // If neither LoadedCA or CA is set, the provided pool with override the system + // certificate pool. + // The caller must not use the supplied pool after calling TLSClientAuth. + LoadedCAPool *x509.CertPool + // ServerName specifies the hostname to use when verifying the server certificate. // If this field is set then InsecureSkipVerify will be ignored and treated as // false. ServerName string // InsecureSkipVerify controls whether the certificate chain and hostname presented - // by the server are validated. If false, any certificate is accepted. + // by the server are validated. If true, any certificate is accepted. InsecureSkipVerify bool + // VerifyPeerCertificate, if not nil, is called after normal + // certificate verification. It receives the raw ASN.1 certificates + // provided by the peer and also any verified chains that normal processing found. + // If it returns a non-nil error, the handshake is aborted and that error results. + // + // If normal verification fails then the handshake will abort before + // considering this callback. If normal verification is disabled by + // setting InsecureSkipVerify then this callback will be considered but + // the verifiedChains argument will always be nil. + VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error + + // SessionTicketsDisabled may be set to true to disable session ticket and + // PSK (resumption) support. Note that on clients, session ticket support is + // also disabled if ClientSessionCache is nil. + SessionTicketsDisabled bool + + // ClientSessionCache is a cache of ClientSessionState entries for TLS + // session resumption. It is only used by clients. + ClientSessionCache tls.ClientSessionCache + // Prevents callers using unkeyed fields. _ struct{} } @@ -123,11 +151,15 @@ cfg.InsecureSkipVerify = opts.InsecureSkipVerify + cfg.VerifyPeerCertificate = opts.VerifyPeerCertificate + cfg.SessionTicketsDisabled = opts.SessionTicketsDisabled + cfg.ClientSessionCache = opts.ClientSessionCache + // When no CA certificate is provided, default to the system cert pool // that way when a request is made to a server known by the system trust store, // the name is still verified if opts.LoadedCA != nil { - caCertPool := x509.NewCertPool() + caCertPool := basePool(opts.LoadedCAPool) caCertPool.AddCert(opts.LoadedCA) cfg.RootCAs = caCertPool } else if opts.CA != "" { @@ -136,9 +168,11 @@ if err != nil { return nil, fmt.Errorf("tls client ca: %v", err) } - caCertPool := x509.NewCertPool() + caCertPool := basePool(opts.LoadedCAPool) caCertPool.AppendCertsFromPEM(caCert) cfg.RootCAs = caCertPool + } else if opts.LoadedCAPool != nil { + cfg.RootCAs = opts.LoadedCAPool } // apply servername overrride @@ -152,6 +186,13 @@ return cfg, nil } +func basePool(pool *x509.CertPool) *x509.CertPool { + if pool == nil { + return x509.NewCertPool() + } + return pool +} + // TLSTransport creates a http client transport suitable for mutual tls auth func TLSTransport(opts TLSClientOptions) (http.RoundTripper, error) { cfg, err := TLSClientAuth(opts) @@ -196,7 +237,6 @@ clientOnce *sync.Once client *http.Client schemes []string - do func(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) } // New creates a new default runtime for a swagger api runtime.Client @@ -206,17 +246,21 @@ // TODO: actually infer this stuff from the spec rt.Consumers = map[string]runtime.Consumer{ + runtime.YAMLMime: yamlpc.YAMLConsumer(), runtime.JSONMime: runtime.JSONConsumer(), runtime.XMLMime: runtime.XMLConsumer(), runtime.TextMime: runtime.TextConsumer(), runtime.HTMLMime: runtime.TextConsumer(), + runtime.CSVMime: runtime.CSVConsumer(), runtime.DefaultMime: runtime.ByteStreamConsumer(), } rt.Producers = map[string]runtime.Producer{ + runtime.YAMLMime: yamlpc.YAMLProducer(), runtime.JSONMime: runtime.JSONProducer(), runtime.XMLMime: runtime.XMLProducer(), runtime.TextMime: runtime.TextProducer(), runtime.HTMLMime: runtime.TextProducer(), + runtime.CSVMime: runtime.CSVProducer(), runtime.DefaultMime: runtime.ByteStreamProducer(), } rt.Transport = http.DefaultTransport @@ -235,7 +279,6 @@ if len(schemes) > 0 { rt.schemes = schemes } - rt.do = ctxhttp.Do return &rt } @@ -250,6 +293,14 @@ return rt } +// WithOpenTracing adds opentracing support to the provided runtime. +// A new client span is created for each request. +// If the context of the client operation does not contain an active span, no span is created. +// The provided opts are applied to each spans - for example to add global tags. +func (r *Runtime) WithOpenTracing(opts ...opentracing.StartSpanOption) runtime.ClientTransport { + return newOpenTracingTransport(r, r.Host, opts) +} + func (r *Runtime) pickScheme(schemes []string) string { if v := r.selectScheme(r.schemes); v != "" { return v @@ -342,7 +393,7 @@ } } - if _, ok := r.Producers[cmt]; !ok && cmt != runtime.MultipartFormMime { + if _, ok := r.Producers[cmt]; !ok && cmt != runtime.MultipartFormMime && cmt != runtime.URLencodedFormMime { return nil, fmt.Errorf("none of producers: %v registered. try %s", r.Producers, cmt) } @@ -352,6 +403,7 @@ } req.URL.Scheme = r.pickScheme(operation.Schemes) req.URL.Host = r.Host + req.Host = r.Host r.clientOnce.Do(func() { r.client = &http.Client{ @@ -391,28 +443,30 @@ if client == nil { client = r.client } - if r.do == nil { - r.do = ctxhttp.Do - } - res, err := r.do(ctx, client, req) // make requests, by default follows 10 redirects before failing + req = req.WithContext(ctx) + res, err := client.Do(req) // make requests, by default follows 10 redirects before failing if err != nil { return nil, err } defer res.Body.Close() + ct := res.Header.Get(runtime.HeaderContentType) + if ct == "" { // this should really really never occur + ct = r.DefaultMediaType + } + if r.Debug { - b, err2 := httputil.DumpResponse(res, true) + printBody := true + if ct == runtime.DefaultMime { + printBody = false // Spare the terminal from a binary blob. + } + b, err2 := httputil.DumpResponse(res, printBody) if err2 != nil { return nil, err2 } r.logger.Debugf("%s\n", string(b)) } - ct := res.Header.Get(runtime.HeaderContentType) - if ct == "" { // this should really really never occur - ct = r.DefaultMediaType - } - mt, _, err := mime.ParseMediaType(ct) if err != nil { return nil, fmt.Errorf("parse content type: %s", err) diff -Nru golang-github-go-openapi-runtime-0.15.0/client/runtime_test.go golang-github-go-openapi-runtime-0.21.0/client/runtime_test.go --- golang-github-go-openapi-runtime-0.15.0/client/runtime_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client/runtime_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -28,8 +28,7 @@ "testing" "time" - "golang.org/x/net/context" - + "crypto/tls" "crypto/x509" "encoding/pem" @@ -37,11 +36,12 @@ "github.com/go-openapi/strfmt" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + goruntime "runtime" ) // task This describes a task. Tasks require a content property to be set. type task struct { - // Completed Completed bool `json:"completed" xml:"completed"` @@ -70,7 +70,6 @@ } func TestRuntime_TLSAuthConfigWithRSAKey(t *testing.T) { - keyPem, err := ioutil.ReadFile("../fixtures/certs/myclient.key") require.NoError(t, err) @@ -87,6 +86,7 @@ require.NotNil(t, certDer) cert, err := x509.ParseCertificate(certDer.Bytes) + require.NoError(t, err) var opts TLSClientOptions opts.LoadedKey = key @@ -101,7 +101,6 @@ } func TestRuntime_TLSAuthConfigWithECKey(t *testing.T) { - keyPem, err := ioutil.ReadFile("../fixtures/certs/myclient-ecc.key") require.NoError(t, err) @@ -119,6 +118,7 @@ require.NotNil(t, certDer) cert, err := x509.ParseCertificate(certDer.Bytes) + require.NoError(t, err) var opts TLSClientOptions opts.LoadedKey = key @@ -133,7 +133,6 @@ } func TestRuntime_TLSAuthConfigWithLoadedCA(t *testing.T) { - certPem, err := ioutil.ReadFile("../fixtures/certs/myCA.crt") require.NoError(t, err) @@ -154,6 +153,189 @@ } } +func TestRuntime_TLSAuthConfigWithLoadedCAPool(t *testing.T) { + certPem, err := ioutil.ReadFile("../fixtures/certs/myCA.crt") + require.NoError(t, err) + + block, _ := pem.Decode(certPem) + require.NotNil(t, block) + + cert, err := x509.ParseCertificate(block.Bytes) + require.NoError(t, err) + + pool := x509.NewCertPool() + pool.AddCert(cert) + + var opts TLSClientOptions + opts.LoadedCAPool = pool + + cfg, err := TLSClientAuth(opts) + if assert.NoError(t, err) { + if assert.NotNil(t, cfg) { + require.NotNil(t, cfg.RootCAs) + + // Using require.Len prints the (very large and incomprehensible) + // Subjects list on failure, so instead use require.Equal. + require.Equal(t, 1, len(cfg.RootCAs.Subjects())) + } + } +} + +func TestRuntime_TLSAuthConfigWithLoadedCAPoolAndLoadedCA(t *testing.T) { + certPem, err := ioutil.ReadFile("../fixtures/certs/myCA.crt") + require.NoError(t, err) + + block, _ := pem.Decode(certPem) + require.NotNil(t, block) + + cert, err := x509.ParseCertificate(block.Bytes) + require.NoError(t, err) + + var pool *x509.CertPool + if goruntime.GOOS == "windows" { + // Windows doesn't have the system cert pool. + pool = x509.NewCertPool() + } else { + pool, err = x509.SystemCertPool() + require.NoError(t, err) + } + startingCertCount := len(pool.Subjects()) + + var opts TLSClientOptions + opts.LoadedCAPool = pool + opts.LoadedCA = cert + + cfg, err := TLSClientAuth(opts) + if assert.NoError(t, err) { + if assert.NotNil(t, cfg) { + require.NotNil(t, cfg.RootCAs) + + // Using require.Len prints the (very large and incomprehensible) + // Subjects list on failure, so instead use require.Equal. + require.Equal(t, startingCertCount+1, len(cfg.RootCAs.Subjects())) + } + } +} + +func TestRuntime_TLSAuthConfigWithVerifyPeerCertificate(t *testing.T) { + var opts TLSClientOptions + opts.InsecureSkipVerify = true + var verify = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { + return nil + } + opts.VerifyPeerCertificate = verify + + cfg, err := TLSClientAuth(opts) + if assert.NoError(t, err) { + if assert.NotNil(t, cfg) { + assert.True(t, cfg.InsecureSkipVerify) + assert.NotNil(t, cfg.VerifyPeerCertificate) + } + } +} + +func TestRuntime_ManualCertificateValidation(t *testing.T) { + // test manual verification of server certificates + // against root certificate on client side. + result := []task{ + {false, "task 1 content", 1}, + {false, "task 2 content", 2}, + } + var verifyCalled bool + server := httptest.NewUnstartedServer(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) + })) + + // root cert + rootCertFile := "../fixtures/certs/myCA.crt" + rootCertPem, err := ioutil.ReadFile(rootCertFile) + require.NoError(t, err) + rootCertRaw, _ := pem.Decode(rootCertPem) + require.NotNil(t, rootCertRaw) + rootCert, err := x509.ParseCertificate(rootCertRaw.Bytes) + require.NoError(t, err) + + // create server tls config + serverCACertPool := x509.NewCertPool() + serverCACertPool.AddCert(rootCert) + server.TLS = &tls.Config{ + RootCAs: serverCACertPool, + } + + // load server certs + serverCertFile := "../fixtures/certs/mycert1.crt" + serverKeyFile := "../fixtures/certs/mycert1.key" + server.TLS.Certificates = make([]tls.Certificate, 1) + server.TLS.Certificates[0], err = tls.LoadX509KeyPair( + serverCertFile, + serverKeyFile, + ) + require.NoError(t, err) + + server.StartTLS() + defer server.Close() + + // test if server is a valid endpoint + // by comparing received certs against root cert, + // explicitly omitting DNSName check. + client, err := TLSClient(TLSClientOptions{ + InsecureSkipVerify: true, + VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { + verifyCalled = true + + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(rootCertPem) + + opts := x509.VerifyOptions{ + Roots: caCertPool, + CurrentTime: time.Date(2017, time.July, 1, 1, 1, 1, 1, time.UTC), + } + + cert, err := x509.ParseCertificate(rawCerts[0]) + if err != nil { + return err + } + + _, err = cert.Verify(opts) + return err + }, + }) + + require.NoError(t, err) + hu, _ := url.Parse(server.URL) + rt := NewWithClient(hu.Host, "/", []string{"https"}, client) + + rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error { + return nil + }) + + var received []task + _, 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 { + if err := consumer.Consume(response.Body(), &received); err != nil { + return nil, err + } + return result, nil + } + return nil, errors.New("Generic error") + }), + }) + + if assert.NoError(t, err) { + assert.True(t, verifyCalled) + assert.IsType(t, []task{}, received) + assert.EqualValues(t, result, received) + } +} + func TestRuntime_Concurrent(t *testing.T) { // test that it can make a simple request // and get the response for it. @@ -368,6 +550,50 @@ } } +func TestRuntime_CSVCanary(t *testing.T) { + // test that it can make a simple csv request + // and get the response for it. + result := `task,content,result +1,task1,ok +2,task2,fail +` + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.Header().Add(runtime.HeaderContentType, runtime.CSVMime) + 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 bytes.Buffer + 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, bytes.Buffer{}, res) + actual := res.(bytes.Buffer) + assert.EqualValues(t, result, actual.String()) + } +} + type roundTripperFunc func(*http.Request) (*http.Response, error) func (fn roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) { @@ -388,6 +614,8 @@ if req.URL.Scheme != "https" { return nil, errors.New("this was not a https request") } + assert.Equal(t, "localhost:3245", req.Host) + assert.Equal(t, "localhost:3245", req.URL.Host) var resp http.Response resp.StatusCode = 200 resp.Header = make(http.Header) @@ -607,7 +835,6 @@ hu, _ := url.Parse(server.URL) rt := New(hu.Host, "/", []string{"http"}) - rt.do = nil res, err := rt.Submit(&runtime.ClientOperation{ ID: "getTasks", Method: "GET", @@ -707,6 +934,10 @@ runtime = New("", "/", []string{"https"}) assert.True(t, runtime.Debug) + _ = os.Setenv("DEBUG", "false") + runtime = New("", "/", []string{"https"}) + assert.False(t, runtime.Debug) + _ = os.Setenv("DEBUG", "foo") runtime = New("", "/", []string{"https"}) assert.True(t, runtime.Debug) @@ -730,6 +961,18 @@ assert.Equal(t, 0, i) } +type overrideRoundTripper struct { + overriden bool +} + +func (o *overrideRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + o.overriden = true + res := new(http.Response) + res.StatusCode = 200 + res.Body = ioutil.NopCloser(bytes.NewBufferString("OK")) + return res, nil +} + func TestRuntime_OverrideClientOperation(t *testing.T) { client := &http.Client{} rt := NewWithClient("", "/", []string{"https"}, client) @@ -738,17 +981,9 @@ 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 + var transport = &overrideRoundTripper{} + client2.Transport = transport if assert.NotEqual(t, client, client2) { _, err := rt.Submit(&runtime.ClientOperation{ Client: client2, @@ -760,8 +995,7 @@ }), }) if assert.NoError(t, err) { - - assert.Equal(t, client2, seen) + assert.True(t, transport.overriden) } } } diff -Nru golang-github-go-openapi-runtime-0.15.0/client_operation.go golang-github-go-openapi-runtime-0.21.0/client_operation.go --- golang-github-go-openapi-runtime-0.15.0/client_operation.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client_operation.go 2021-10-29 03:50:47.000000000 +0000 @@ -15,9 +15,8 @@ package runtime import ( + "context" "net/http" - - "golang.org/x/net/context" ) // ClientOperation represents the context for a swagger operation to be submitted to the transport diff -Nru golang-github-go-openapi-runtime-0.15.0/client_request.go golang-github-go-openapi-runtime-0.21.0/client_request.go --- golang-github-go-openapi-runtime-0.15.0/client_request.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client_request.go 2021-10-29 03:50:47.000000000 +0000 @@ -17,6 +17,7 @@ import ( "io" "io/ioutil" + "net/http" "net/url" "time" @@ -41,6 +42,8 @@ type ClientRequest interface { SetHeaderParam(string, ...string) error + GetHeaderParams() http.Header + SetQueryParam(string, ...string) error SetFormParam(string, ...string) error @@ -60,6 +63,10 @@ GetPath() string GetBody() []byte + + GetBodyParam() interface{} + + GetFileParam() map[string][]NamedReadCloser } // NamedReadCloser represents a named ReadCloser interface @@ -94,3 +101,53 @@ func (n *namedReadCloser) Name() string { return n.name } + +type TestClientRequest struct { + Headers http.Header + Body interface{} +} + +func (t *TestClientRequest) 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 *TestClientRequest) SetQueryParam(_ string, _ ...string) error { return nil } + +func (t *TestClientRequest) SetFormParam(_ string, _ ...string) error { return nil } + +func (t *TestClientRequest) SetPathParam(_ string, _ string) error { return nil } + +func (t *TestClientRequest) SetFileParam(_ string, _ ...NamedReadCloser) error { return nil } + +func (t *TestClientRequest) SetBodyParam(body interface{}) error { + t.Body = body + return nil +} + +func (t *TestClientRequest) SetTimeout(time.Duration) error { + return nil +} + +func (t *TestClientRequest) GetQueryParams() url.Values { return nil } + +func (t *TestClientRequest) GetMethod() string { return "" } + +func (t *TestClientRequest) GetPath() string { return "" } + +func (t *TestClientRequest) GetBody() []byte { return nil } + +func (t *TestClientRequest) GetBodyParam() interface{} { + return t.Body +} + +func (t *TestClientRequest) GetFileParam() map[string][]NamedReadCloser { + return nil +} + +func (t *TestClientRequest) GetHeaderParams() http.Header { + return t.Headers +} diff -Nru golang-github-go-openapi-runtime-0.15.0/client_request_test.go golang-github-go-openapi-runtime-0.21.0/client_request_test.go --- golang-github-go-openapi-runtime-0.15.0/client_request_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client_request_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -15,62 +15,20 @@ package runtime import ( - "net/http" - "net/url" "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 (t *trw) GetQueryParams() url.Values { return nil } - -func (t *trw) GetMethod() string { return "" } - -func (t *trw) GetPath() string { return "" } - -func (t *trw) GetBody() []byte { 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) + tr := new(TestClientRequest) _ = hand.WriteToRequest(tr, nil) assert.Equal(t, "blah blah", tr.Headers.Get("blah")) assert.Equal(t, "Adriana", tr.Body.(struct{ Name string }).Name) diff -Nru golang-github-go-openapi-runtime-0.15.0/client_response.go golang-github-go-openapi-runtime-0.21.0/client_response.go --- golang-github-go-openapi-runtime-0.15.0/client_response.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client_response.go 2021-10-29 03:50:47.000000000 +0000 @@ -17,6 +17,8 @@ import ( "fmt" "io" + + "encoding/json" ) // A ClientResponse represents a client response @@ -25,6 +27,7 @@ Code() int Message() string GetHeader(string) string + GetHeaders(string) []string Body() io.ReadCloser } @@ -59,5 +62,10 @@ } func (a *APIError) Error() string { - return fmt.Sprintf("%s (status %d): %+v ", a.OperationName, a.Code, a.Response) + resp, _ := json.Marshal(a.Response) + return fmt.Sprintf("%s (status %d): %s", a.OperationName, a.Code, resp) +} + +func (a *APIError) String() string { + return a.Error() } diff -Nru golang-github-go-openapi-runtime-0.15.0/client_response_test.go golang-github-go-openapi-runtime-0.21.0/client_response_test.go --- golang-github-go-openapi-runtime-0.15.0/client_response_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/client_response_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -35,6 +35,9 @@ func (r response) GetHeader(_ string) string { return "the header" } +func (r response) GetHeaders(_ string) []string { + return []string{"the headers", "the headers2"} +} func (r response) Body() io.ReadCloser { return ioutil.NopCloser(bytes.NewBufferString("the content")) } diff -Nru golang-github-go-openapi-runtime-0.15.0/constants.go golang-github-go-openapi-runtime-0.21.0/constants.go --- golang-github-go-openapi-runtime-0.15.0/constants.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/constants.go 2021-10-29 03:50:47.000000000 +0000 @@ -38,6 +38,8 @@ TextMime = "text/plain" // HTMLMime the html mime type HTMLMime = "text/html" + // CSVMime the csv mime type + CSVMime = "text/csv" // MultipartFormMime the multipart form mime type MultipartFormMime = "multipart/form-data" // URLencodedFormMime the url encoded form mime type diff -Nru golang-github-go-openapi-runtime-0.15.0/csv.go golang-github-go-openapi-runtime-0.21.0/csv.go --- golang-github-go-openapi-runtime-0.15.0/csv.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/csv.go 2021-10-29 03:50:47.000000000 +0000 @@ -0,0 +1,77 @@ +// 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/csv" + "errors" + "io" +) + +// CSVConsumer creates a new CSV consumer +func CSVConsumer() Consumer { + return ConsumerFunc(func(reader io.Reader, data interface{}) error { + if reader == nil { + return errors.New("CSVConsumer requires a reader") + } + + csvReader := csv.NewReader(reader) + writer, ok := data.(io.Writer) + if !ok { + return errors.New("data type must be io.Writer") + } + csvWriter := csv.NewWriter(writer) + records, err := csvReader.ReadAll() + if err != nil { + return err + } + for _, r := range records { + if err := csvWriter.Write(r); err != nil { + return err + } + } + csvWriter.Flush() + return nil + }) +} + +// CSVProducer creates a new CSV producer +func CSVProducer() Producer { + return ProducerFunc(func(writer io.Writer, data interface{}) error { + if writer == nil { + return errors.New("CSVProducer requires a writer") + } + + dataBytes, ok := data.([]byte) + if !ok { + return errors.New("data type must be byte array") + } + + csvReader := csv.NewReader(bytes.NewBuffer(dataBytes)) + records, err := csvReader.ReadAll() + if err != nil { + return err + } + csvWriter := csv.NewWriter(writer) + for _, r := range records { + if err := csvWriter.Write(r); err != nil { + return err + } + } + csvWriter.Flush() + return nil + }) +} diff -Nru golang-github-go-openapi-runtime-0.15.0/csv_test.go golang-github-go-openapi-runtime-0.21.0/csv_test.go --- golang-github-go-openapi-runtime-0.15.0/csv_test.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/csv_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -0,0 +1,74 @@ +// 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" +) + +const consProdCSV = `name,country,age +John,US,19 +Mike,US,20 +` + +type csvEmptyReader struct{} + +func (r *csvEmptyReader) Read(d []byte) (int, error) { + return 0, io.EOF +} + +func TestCSVConsumer(t *testing.T) { + cons := CSVConsumer() + reader := bytes.NewBuffer([]byte(consProdCSV)) + + outBuf := new(bytes.Buffer) + err := cons.Consume(reader, outBuf) + assert.NoError(t, err) + assert.Equal(t, consProdCSV, outBuf.String()) + + outBuf2 := new(bytes.Buffer) + err = cons.Consume(nil, outBuf2) + assert.Error(t, err) + + err = cons.Consume(reader, struct{}{}) + assert.Error(t, err) + + emptyOutBuf := new(bytes.Buffer) + err = cons.Consume(&csvEmptyReader{}, emptyOutBuf) + assert.NoError(t, err) + assert.Equal(t, "", emptyOutBuf.String()) +} + +func TestCSVProducer(t *testing.T) { + prod := CSVProducer() + data := []byte(consProdCSV) + + rw := httptest.NewRecorder() + err := prod.Produce(rw, data) + assert.NoError(t, err) + assert.Equal(t, consProdCSV, rw.Body.String()) + + rw2 := httptest.NewRecorder() + err = prod.Produce(rw2, struct{}{}) + assert.Error(t, err) + + err = prod.Produce(nil, data) + assert.Error(t, err) +} diff -Nru golang-github-go-openapi-runtime-0.15.0/debian/changelog golang-github-go-openapi-runtime-0.21.0/debian/changelog --- golang-github-go-openapi-runtime-0.15.0/debian/changelog 2019-10-29 08:50:11.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/debian/changelog 2021-11-25 22:41:42.000000000 +0000 @@ -1,3 +1,40 @@ +golang-github-go-openapi-runtime (0.21.0-1) unstable; urgency=medium + + * Team upload. + + [ Guillem Jover ] + * New upstream release. + * Update Go Team Maintainer address. + * Switch to debhelper-compat level 13. + * Switch to Standards-Version 4.6.0 (no changes needed). + * Use dh-sequence-golang instead of dh-golang and --with=golang. + * Set Rules-Requires-Root to no. + * Mark -dev package as Multi-Arch: foreign. + * Switch Section to golang. + * Remove ${shlibs:Depends} from Depends field. + * Remove copyright statements from License fields. + * Move license location on Debian systems into a Comment field. + * Fix debian/watch syntax. + * Switch to debian/watch format 4. + * Update gitlab-ci.yml from its canonical source. + * Update gbp configuration following Go Team new workflow. + * Update copyright claims. + * Replace patch with DH_GOLANG_INSTALL_EXTRA to include fixtures. + * Update dependencies for new upstream release. + * Add a debian/.gitignore file. + * Set build directory to _build. + * Do not ignore the test suite results. + + -- Guillem Jover Thu, 25 Nov 2021 23:41:42 +0100 + +golang-github-go-openapi-runtime (0.15.0-2) unstable; urgency=medium + + [ Debian Janitor ] + * Update standards version to 4.5.0, no changes needed. + * Set upstream metadata fields: Bug-Database, Bug-Submit, Repository, Repository-Browse. + + -- Jelmer Vernooij Fri, 05 Feb 2021 03:14:21 +0000 + golang-github-go-openapi-runtime (0.15.0-1) unstable; urgency=medium * Team upload. diff -Nru golang-github-go-openapi-runtime-0.15.0/debian/control golang-github-go-openapi-runtime-0.21.0/debian/control --- golang-github-go-openapi-runtime-0.15.0/debian/control 2019-10-29 08:50:11.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/debian/control 2021-11-25 22:40:01.000000000 +0000 @@ -1,25 +1,25 @@ Source: golang-github-go-openapi-runtime -Maintainer: Debian Go Packaging Team +Maintainer: Debian Go Packaging Team Uploaders: Tim Potter , -Section: devel +Section: golang Testsuite: autopkgtest-pkg-go Priority: optional -Build-Depends: debhelper-compat (= 12), - dh-golang, +Rules-Requires-Root: no +Build-Depends: debhelper-compat (= 13), + dh-sequence-golang, golang-any, golang-github-docker-go-units-dev, golang-github-go-openapi-analysis-dev (>= 0.15.0~), golang-github-go-openapi-errors-dev, golang-github-go-openapi-loads-dev (>= 0.15.0~), golang-github-go-openapi-spec-dev (>= 0.15.0~), - golang-github-go-openapi-strfmt-dev, + golang-github-go-openapi-strfmt-dev (>= 0.19.0~), golang-github-go-openapi-swag-dev (>= 0.15.0~), - golang-github-go-openapi-validate-dev, - golang-github-gorilla-context-dev, - golang-github-stretchr-testify-dev, - golang-golang-x-net-dev, + golang-github-go-openapi-validate-dev (>= 0.20.3~), + golang-github-opentracing-opentracing-go-dev, + golang-github-stretchr-testify-dev , golang-gopkg-yaml.v2-dev, -Standards-Version: 4.4.1 +Standards-Version: 4.6.0 Vcs-Browser: https://salsa.debian.org/go-team/packages/golang-github-go-openapi-runtime Vcs-Git: https://salsa.debian.org/go-team/packages/golang-github-go-openapi-runtime.git Homepage: https://github.com/go-openapi/runtime @@ -27,20 +27,19 @@ Package: golang-github-go-openapi-runtime-dev Architecture: all +Multi-Arch: foreign Depends: golang-github-docker-go-units-dev, golang-github-go-openapi-analysis-dev (>= 0.15.0~), golang-github-go-openapi-errors-dev, golang-github-go-openapi-loads-dev (>= 0.15.0~), golang-github-go-openapi-spec-dev (>= 0.15.0~), - golang-github-go-openapi-strfmt-dev, + golang-github-go-openapi-strfmt-dev (>= 0.19.0~), golang-github-go-openapi-swag-dev (>= 0.15.0~), - golang-github-go-openapi-validate-dev, - golang-github-gorilla-context-dev, - golang-github-stretchr-testify-dev, - golang-golang-x-net-dev, + golang-github-go-openapi-validate-dev (>= 0.20.3~), + golang-github-opentracing-opentracing-go-dev, + golang-github-stretchr-testify-dev , golang-gopkg-yaml.v2-dev, ${misc:Depends}, - ${shlibs:Depends}, Description: OpenAPI runtime interfaces The runtime library is part of the OpenAPI Initiative and OpenAPI Specification, and consists of classes and functions to be used in diff -Nru golang-github-go-openapi-runtime-0.15.0/debian/copyright golang-github-go-openapi-runtime-0.21.0/debian/copyright --- golang-github-go-openapi-runtime-0.15.0/debian/copyright 2019-10-29 08:50:11.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/debian/copyright 2021-11-25 17:25:49.000000000 +0000 @@ -16,6 +16,7 @@ Files: debian/* Copyright: 2017 Tim Potter + 2021 Sipwise GmbH, Austria License: Apache-2.0 Comment: Debian packaging is licensed under the same terms as upstream @@ -31,14 +32,11 @@ 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. - . +Comment: On Debian systems, the complete text of the Apache version 2.0 license can be found in "/usr/share/common-licenses/Apache-2.0". License: BSD-3-Clause - Copyright (c) 2013, Google Inc. - All rights reserved. - . Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -67,8 +65,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. License: Expat - Copyright (c) 2014 Naoya Inada - . Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights diff -Nru golang-github-go-openapi-runtime-0.15.0/debian/gbp.conf golang-github-go-openapi-runtime-0.21.0/debian/gbp.conf --- golang-github-go-openapi-runtime-0.15.0/debian/gbp.conf 2019-10-29 08:50:11.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/debian/gbp.conf 2021-11-25 17:25:49.000000000 +0000 @@ -1,6 +1,3 @@ [DEFAULT] debian-branch = debian/sid - -[buildpackage] dist = DEP14 -upstream-tag = upstream/%(version)s diff -Nru golang-github-go-openapi-runtime-0.15.0/debian/gitlab-ci.yml golang-github-go-openapi-runtime-0.21.0/debian/gitlab-ci.yml --- golang-github-go-openapi-runtime-0.15.0/debian/gitlab-ci.yml 2019-10-29 08:50:11.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/debian/gitlab-ci.yml 2021-11-25 17:25:49.000000000 +0000 @@ -1,9 +1,7 @@ - # auto-generated, DO NOT MODIFY. # The authoritative copy of this file lives at: -# https://salsa.debian.org/go-team/ci/blob/master/cmd/ci/gitlabciyml.go +# https://salsa.debian.org/go-team/ci/blob/master/config/gitlabciyml.go -# TODO: publish under debian-go-team/ci image: stapelberg/ci2 test_the_archive: diff -Nru golang-github-go-openapi-runtime-0.15.0/debian/patches/series golang-github-go-openapi-runtime-0.21.0/debian/patches/series --- golang-github-go-openapi-runtime-0.15.0/debian/patches/series 2019-10-29 08:50:11.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test-fixture-locations.patch diff -Nru golang-github-go-openapi-runtime-0.15.0/debian/patches/test-fixture-locations.patch golang-github-go-openapi-runtime-0.21.0/debian/patches/test-fixture-locations.patch --- golang-github-go-openapi-runtime-0.15.0/debian/patches/test-fixture-locations.patch 2019-10-29 08:50:11.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/debian/patches/test-fixture-locations.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -Description: Test fixture locations -Index: golang-github-go-openapi-runtime/middleware/context_test.go -=================================================================== ---- golang-github-go-openapi-runtime.orig/middleware/context_test.go -+++ golang-github-go-openapi-runtime/middleware/context_test.go -@@ -52,7 +52,7 @@ func init() { - } - - func TestContentType_Issue264(t *testing.T) { -- swspec, err := loads.Spec("../fixtures/bugs/264/swagger.yml") -+ swspec, err := loads.Spec("../../../../../../fixtures/bugs/264/swagger.yml") - if assert.NoError(t, err) { - api := untyped.NewAPI(swspec) - api.RegisterConsumer("application/json", runtime.JSONConsumer()) diff -Nru golang-github-go-openapi-runtime-0.15.0/debian/rules golang-github-go-openapi-runtime-0.21.0/debian/rules --- golang-github-go-openapi-runtime-0.15.0/debian/rules 2019-10-29 08:50:11.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/debian/rules 2021-11-25 22:40:59.000000000 +0000 @@ -1,8 +1,8 @@ #!/usr/bin/make -f -%: - dh $@ --buildsystem=golang --with=golang +export DH_GOLANG_INSTALL_EXTRA := \ + fixtures \ + # EOL -# Test suite appears to be in bad shape for 0.0~git20160704.0.11e322e snapshot -override_dh_auto_test: - -dh_auto_test +%: + dh $@ --buildsystem=golang --builddirectory=_build diff -Nru golang-github-go-openapi-runtime-0.15.0/debian/upstream/metadata golang-github-go-openapi-runtime-0.21.0/debian/upstream/metadata --- golang-github-go-openapi-runtime-0.15.0/debian/upstream/metadata 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/debian/upstream/metadata 2021-11-25 17:25:49.000000000 +0000 @@ -0,0 +1,4 @@ +Bug-Database: https://github.com/go-openapi/runtime/issues +Bug-Submit: https://github.com/go-openapi/runtime/issues/new +Repository: https://github.com/go-openapi/runtime.git +Repository-Browse: https://github.com/go-openapi/runtime diff -Nru golang-github-go-openapi-runtime-0.15.0/debian/watch golang-github-go-openapi-runtime-0.21.0/debian/watch --- golang-github-go-openapi-runtime-0.15.0/debian/watch 2019-10-29 08:50:11.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/debian/watch 2021-11-25 17:25:49.000000000 +0000 @@ -1,4 +1,4 @@ -version=3 -opts=filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/golang-github-go-openapi-runtime-\$1\.tar\.gz/,\\ -uversionmangle=s/(\d)[_\.\-\+]?(RC|rc|pre|dev|beta|alpha)[.]?(\d*)$/\$1~\$2\$3/ \\ +version=4 +opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%@PACKAGE@-$1.tar.gz%,\ + uversionmangle=s/(\d)[_\.\-\+]?(RC|rc|pre|dev|beta|alpha)[.]?(\d*)$/$1~$2$3/" \ https://github.com/go-openapi/runtime/tags .*/v?(\d\S*)\.tar\.gz diff -Nru golang-github-go-openapi-runtime-0.15.0/fixtures/bugs/172/swagger.yml golang-github-go-openapi-runtime-0.21.0/fixtures/bugs/172/swagger.yml --- golang-github-go-openapi-runtime-0.15.0/fixtures/bugs/172/swagger.yml 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/fixtures/bugs/172/swagger.yml 2021-10-29 03:50:47.000000000 +0000 @@ -0,0 +1,99 @@ +swagger: '2.0' +info: + version: 1.0.0 + title: 'Test' +schemes: + - http +produces: + - application/vnd.cia.v1+json + +paths: + /pets: + get: + description: Returns all pets from the system that the user has access to + operationId: findPets + 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 + consumes: + - application/vnd.cia.v1+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' + +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 diff -Nru golang-github-go-openapi-runtime-0.15.0/fixtures/bugs/174/swagger.yml golang-github-go-openapi-runtime-0.21.0/fixtures/bugs/174/swagger.yml --- golang-github-go-openapi-runtime-0.15.0/fixtures/bugs/174/swagger.yml 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/fixtures/bugs/174/swagger.yml 2021-10-29 03:50:47.000000000 +0000 @@ -0,0 +1,99 @@ +swagger: '2.0' +info: + version: 1.0.0 + title: 'Test' +schemes: + - http + +paths: + /pets: + get: + description: Returns all pets from the system that the user has access to + operationId: findPets + 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 + consumes: + - application/json + 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' + +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 diff -Nru golang-github-go-openapi-runtime-0.15.0/flagext/byte_size_test.go golang-github-go-openapi-runtime-0.21.0/flagext/byte_size_test.go --- golang-github-go-openapi-runtime-0.15.0/flagext/byte_size_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/flagext/byte_size_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -1,7 +1,10 @@ package flagext -import "testing" -import "github.com/stretchr/testify/assert" +import ( + "testing" + + "github.com/stretchr/testify/assert" +) func TestMarshalBytesize(t *testing.T) { v, err := ByteSize(1024).MarshalFlag() diff -Nru golang-github-go-openapi-runtime-0.15.0/.gitattributes golang-github-go-openapi-runtime-0.21.0/.gitattributes --- golang-github-go-openapi-runtime-0.15.0/.gitattributes 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/.gitattributes 2021-10-29 03:50:47.000000000 +0000 @@ -0,0 +1 @@ +*.go text eol=lf diff -Nru golang-github-go-openapi-runtime-0.15.0/.github/workflows/ci.yaml golang-github-go-openapi-runtime-0.21.0/.github/workflows/ci.yaml --- golang-github-go-openapi-runtime-0.15.0/.github/workflows/ci.yaml 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/.github/workflows/ci.yaml 2021-10-29 03:50:47.000000000 +0000 @@ -0,0 +1,32 @@ +name: Go + +on: [push, pull_request] + +jobs: + build: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ ubuntu-latest, macos-latest, windows-latest ] + fail-fast: false + + steps: + - uses: actions/checkout@v2 + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.17.1 + + - name: Setup gotestsum + uses: autero1/action-gotestsum@v1.0.0 + with: + gotestsum_version: 1.7.0 + + - name: Test + run: gotestsum --format short-verbose -- -race -timeout=20m -coverprofile=coverage_txt -covermode=atomic ./... + + - uses: codecov/codecov-action@v2 + with: + files: coverage_txt diff -Nru golang-github-go-openapi-runtime-0.15.0/.github/workflows/lint.yaml golang-github-go-openapi-runtime-0.21.0/.github/workflows/lint.yaml --- golang-github-go-openapi-runtime-0.15.0/.github/workflows/lint.yaml 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/.github/workflows/lint.yaml 2021-10-29 03:50:47.000000000 +0000 @@ -0,0 +1,12 @@ +name: golangci-lint +on: [push, pull_request] +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: golangci-lint + uses: golangci/golangci-lint-action@v2 + with: + only-new-issues: true diff -Nru golang-github-go-openapi-runtime-0.15.0/.golangci.yml golang-github-go-openapi-runtime-0.21.0/.golangci.yml --- golang-github-go-openapi-runtime-0.15.0/.golangci.yml 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/.golangci.yml 2021-10-29 03:50:47.000000000 +0000 @@ -0,0 +1,43 @@ +linters-settings: + govet: + check-shadowing: true + golint: + min-confidence: 0 + gocyclo: + min-complexity: 30 + maligned: + suggest-new: true + dupl: + threshold: 100 + goconst: + min-len: 2 + min-occurrences: 4 +linters: + disable: + - maligned + - lll + - gochecknoglobals + - godox + - gocognit + - whitespace + - wsl + - funlen + - gochecknoglobals + - gochecknoinits + - scopelint + - wrapcheck + - exhaustivestruct + - exhaustive + - nlreturn + - testpackage + - gci + - gofumpt + - goerr113 + - gomnd + - tparallel + - nestif + - godot + - errorlint + - noctx + - interfacer + - nilerr diff -Nru golang-github-go-openapi-runtime-0.15.0/go.mod golang-github-go-openapi-runtime-0.21.0/go.mod --- golang-github-go-openapi-runtime-0.15.0/go.mod 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/go.mod 2021-10-29 03:50:47.000000000 +0000 @@ -0,0 +1,17 @@ +module github.com/go-openapi/runtime + +require ( + github.com/docker/go-units v0.4.0 + github.com/go-openapi/analysis v0.20.1 + github.com/go-openapi/errors v0.20.1 + github.com/go-openapi/loads v0.21.0 + github.com/go-openapi/spec v0.20.4 + github.com/go-openapi/strfmt v0.21.0 + github.com/go-openapi/swag v0.19.15 + github.com/go-openapi/validate v0.20.3 + github.com/opentracing/opentracing-go v1.2.0 + github.com/stretchr/testify v1.7.0 + gopkg.in/yaml.v2 v2.4.0 +) + +go 1.15 diff -Nru golang-github-go-openapi-runtime-0.15.0/go.sum golang-github-go-openapi-runtime-0.21.0/go.sum --- golang-github-go-openapi-runtime-0.15.0/go.sum 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/go.sum 2021-10-29 03:50:47.000000000 +0000 @@ -0,0 +1,319 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= +github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= +github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg= +github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= +github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= +github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= +github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= +github.com/go-openapi/analysis v0.19.10/go.mod h1:qmhS3VNFxBlquFJ0RGoDtylO9y4pgTAUNE9AEEMdlJQ= +github.com/go-openapi/analysis v0.19.16/go.mod h1:GLInF007N83Ad3m8a/CbQ5TPzdnGT7workfHwuVjNVk= +github.com/go-openapi/analysis v0.20.0/go.mod h1:BMchjvaHDykmRMsK40iPtvyOfFdMMxlOmQr9FBZk+Og= +github.com/go-openapi/analysis v0.20.1 h1:zdVbw8yoD4SWZeq+cWdGgquaB0W4VrsJvDJHJND/Ktc= +github.com/go-openapi/analysis v0.20.1/go.mod h1:BMchjvaHDykmRMsK40iPtvyOfFdMMxlOmQr9FBZk+Og= +github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/errors v0.19.3/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/errors v0.19.6/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.19.7/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.20.1 h1:j23mMDtRxMwIobkpId7sWh7Ddcx4ivaoqUbfXx5P+a8= +github.com/go-openapi/errors v0.20.1/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= +github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= +github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= +github.com/go-openapi/loads v0.19.3/go.mod h1:YVfqhUCdahYwR3f3iiwQLhicVRvLlU/WO5WPaZvcvSI= +github.com/go-openapi/loads v0.19.5/go.mod h1:dswLCAdonkRufe/gSUC3gN8nTSaB9uaS2es0x5/IbjY= +github.com/go-openapi/loads v0.19.6/go.mod h1:brCsvE6j8mnbmGBh103PT/QLHfbyDxA4hsKvYBNEGVc= +github.com/go-openapi/loads v0.19.7/go.mod h1:brCsvE6j8mnbmGBh103PT/QLHfbyDxA4hsKvYBNEGVc= +github.com/go-openapi/loads v0.20.0/go.mod h1:2LhKquiE513rN5xC6Aan6lYOSddlL8Mp20AW9kpviM4= +github.com/go-openapi/loads v0.20.2/go.mod h1:hTVUotJ+UonAMMZsvakEgmWKgtulweO9vYP2bQYKA/o= +github.com/go-openapi/loads v0.21.0 h1:jYtUO4wwP7psAweisP/MDoOpdzsYEESdoPcsWjHDR68= +github.com/go-openapi/loads v0.21.0/go.mod h1:rHYve9nZrQ4CJhyeIIFJINGCg1tQpx2yJrrNo8sf1ws= +github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= +github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= +github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= +github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo= +github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98= +github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk= +github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/spec v0.19.8/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/spec v0.19.15/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU= +github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU= +github.com/go-openapi/spec v0.20.1/go.mod h1:93x7oh+d+FQsmsieroS4cmR3u0p/ywH649a3qwC9OsQ= +github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg= +github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= +github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= +github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= +github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= +github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= +github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= +github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= +github.com/go-openapi/strfmt v0.19.11/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc= +github.com/go-openapi/strfmt v0.20.0/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc= +github.com/go-openapi/strfmt v0.20.2/go.mod h1:43urheQI9dNtE5lTZQfuFJvjYJKPrxicATpEfZwHUNk= +github.com/go-openapi/strfmt v0.21.0 h1:hX2qEZKmYks+t0hKeb4VTJpUm2UYsdL3+DCid5swxIs= +github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= +github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= +github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= +github.com/go-openapi/swag v0.19.12/go.mod h1:eFdyEBkTdoAf/9RXBvj4cr1nH7GD8Kzo5HTt47gr72M= +github.com/go-openapi/swag v0.19.13/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= +github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= +github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo= +github.com/go-openapi/validate v0.19.10/go.mod h1:RKEZTUWDkxKQxN2jDT7ZnZi2bhZlbNMAuKvKB+IaGx8= +github.com/go-openapi/validate v0.19.12/go.mod h1:Rzou8hA/CBw8donlS6WNEUQupNvUZ0waH08tGe6kAQ4= +github.com/go-openapi/validate v0.19.15/go.mod h1:tbn/fdOwYHgrhPBzidZfJC2MIVvs9GA7monOmWBbeCI= +github.com/go-openapi/validate v0.20.1/go.mod h1:b60iJT+xNNLfaQJUqLI7946tYiFEOuE9E4k54HpKcJ0= +github.com/go-openapi/validate v0.20.3 h1:GZPPhhKSZrE8HjB4eEkoYAZmoWA4+tCemSgINH1/vKw= +github.com/go-openapi/validate v0.20.3/go.mod h1:goDdqVGiigM3jChcrYJxD2joalke3ZXeftD16byIjA4= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= +github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= +github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= +github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= +github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= +github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= +github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= +github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= +github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= +github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= +github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= +github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= +github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= +github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= +github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= +github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= +github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= +go.mongodb.org/mongo-driver v1.3.4/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= +go.mongodb.org/mongo-driver v1.4.3/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= +go.mongodb.org/mongo-driver v1.4.4/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= +go.mongodb.org/mongo-driver v1.4.6/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= +go.mongodb.org/mongo-driver v1.5.1/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw= +go.mongodb.org/mongo-driver v1.7.3 h1:G4l/eYY9VrQAK/AUgkV0koQKzQnyddnWxrd/Etf0jIs= +go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758 h1:aEpZnXcAmXkd6AvLb2OPt+EN1Zu/8Ne3pCqPjja5PXY= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff -Nru golang-github-go-openapi-runtime-0.15.0/hack/coverage golang-github-go-openapi-runtime-0.21.0/hack/coverage --- golang-github-go-openapi-runtime-0.15.0/hack/coverage 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/hack/coverage 1970-01-01 00:00:00.000000000 +0000 @@ -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 diff -Nru golang-github-go-openapi-runtime-0.15.0/headers_test.go golang-github-go-openapi-runtime-0.21.0/headers_test.go --- golang-github-go-openapi-runtime-0.15.0/headers_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/headers_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -57,5 +57,4 @@ assert.Equal(t, v.mt, ct, "input: %q", v.hdr) assert.Equal(t, v.cs, cs, "input: %q", v.hdr) } - } diff -Nru golang-github-go-openapi-runtime-0.15.0/interfaces.go golang-github-go-openapi-runtime-0.21.0/interfaces.go --- golang-github-go-openapi-runtime-0.15.0/interfaces.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/interfaces.go 2021-10-29 03:50:47.000000000 +0000 @@ -15,6 +15,7 @@ package runtime import ( + "context" "io" "net/http" @@ -101,3 +102,11 @@ type Validatable interface { Validate(strfmt.Registry) error } + +// ContextValidatable types implementing this interface allow customizing their validation +// this will be used instead of the reflective validation based on the spec document. +// the implementations are assumed to have been generated by the swagger tool so they should +// contain all the context validations obtained from the spec +type ContextValidatable interface { + ContextValidate(context.Context, strfmt.Registry) error +} diff -Nru golang-github-go-openapi-runtime-0.15.0/internal/testing/petstore/api.go golang-github-go-openapi-runtime-0.21.0/internal/testing/petstore/api.go --- golang-github-go-openapi-runtime-0.15.0/internal/testing/petstore/api.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/internal/testing/petstore/api.go 2021-10-29 03:50:47.000000000 +0000 @@ -23,12 +23,13 @@ "github.com/go-openapi/errors" "github.com/go-openapi/loads" + "github.com/stretchr/testify/assert" + "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 @@ -51,6 +52,8 @@ return "admin", nil } else if username == "topuser" && password == "topuser" { return "topuser", nil + } else if username == "anyother" && password == "anyother" { + return "anyother", nil } return nil, errors.Unauthenticated("basic") })) @@ -62,7 +65,11 @@ })) api.RegisterAuthorizer(runtime.AuthorizerFunc(func(r *http.Request, user interface{}) error { if r.Method == http.MethodPost && strings.HasPrefix(r.URL.Path, "/api/pets") && user.(string) != "admin" { - return goerrors.New("unauthorized") + if user.(string) == "topuser" { + return errors.CompositeValidationError(errors.New(errors.InvalidTypeCode, "unauthorized")) + } else { + return goerrors.New("unauthorized") + } } return nil })) diff -Nru golang-github-go-openapi-runtime-0.15.0/internal/testing/simplepetstore/api.go golang-github-go-openapi-runtime-0.21.0/internal/testing/simplepetstore/api.go --- golang-github-go-openapi-runtime-0.15.0/internal/testing/simplepetstore/api.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/internal/testing/simplepetstore/api.go 2021-10-29 03:50:47.000000000 +0000 @@ -22,6 +22,7 @@ "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" diff -Nru golang-github-go-openapi-runtime-0.15.0/internal/testing/simplepetstore/api_test.go golang-github-go-openapi-runtime-0.21.0/internal/testing/simplepetstore/api_test.go --- golang-github-go-openapi-runtime-0.15.0/internal/testing/simplepetstore/api_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/internal/testing/simplepetstore/api_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -19,8 +19,9 @@ "net/http/httptest" "testing" - "github.com/go-openapi/runtime" "github.com/stretchr/testify/assert" + + "github.com/go-openapi/runtime" ) func TestSimplePetstoreSpec(t *testing.T) { diff -Nru golang-github-go-openapi-runtime-0.15.0/json.go golang-github-go-openapi-runtime-0.21.0/json.go --- golang-github-go-openapi-runtime-0.15.0/json.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/json.go 2021-10-29 03:50:47.000000000 +0000 @@ -32,6 +32,7 @@ func JSONProducer() Producer { return ProducerFunc(func(writer io.Writer, data interface{}) error { enc := json.NewEncoder(writer) + enc.SetEscapeHTML(false) return enc.Encode(data) }) } diff -Nru golang-github-go-openapi-runtime-0.15.0/logger/logger.go golang-github-go-openapi-runtime-0.21.0/logger/logger.go --- golang-github-go-openapi-runtime-0.15.0/logger/logger.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/logger/logger.go 2021-10-29 03:50:47.000000000 +0000 @@ -8,5 +8,13 @@ } func DebugEnabled() bool { - return os.Getenv("SWAGGER_DEBUG") != "" || os.Getenv("DEBUG") != "" + d := os.Getenv("SWAGGER_DEBUG") + if d != "" && d != "false" && d != "0" { + return true + } + d = os.Getenv("DEBUG") + if d != "" && d != "false" && d != "0" { + return true + } + return false } diff -Nru golang-github-go-openapi-runtime-0.15.0/middleware/body_test.go golang-github-go-openapi-runtime-0.21.0/middleware/body_test.go --- golang-github-go-openapi-runtime-0.15.0/middleware/body_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/middleware/body_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -6,9 +6,10 @@ "path" "testing" + "github.com/stretchr/testify/assert" + "github.com/go-openapi/runtime" "github.com/go-openapi/runtime/internal/testing/petstore" - "github.com/stretchr/testify/assert" ) type eofReader struct { diff -Nru golang-github-go-openapi-runtime-0.15.0/middleware/context.go golang-github-go-openapi-runtime-0.21.0/middleware/context.go --- golang-github-go-openapi-runtime-0.15.0/middleware/context.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/middleware/context.go 2021-10-29 03:50:47.000000000 +0000 @@ -16,6 +16,7 @@ import ( stdContext "context" + "fmt" "net/http" "strings" "sync" @@ -23,11 +24,13 @@ "github.com/go-openapi/analysis" "github.com/go-openapi/errors" "github.com/go-openapi/loads" + "github.com/go-openapi/spec" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/runtime" "github.com/go-openapi/runtime/logger" "github.com/go-openapi/runtime/middleware/untyped" - "github.com/go-openapi/spec" - "github.com/go-openapi/strfmt" + "github.com/go-openapi/runtime/security" ) // Debug when true turns on verbose logging @@ -277,8 +280,8 @@ // 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 + var requestContentType string - requestContentType := "*/*" // check and validate content type, select consumer if runtime.HasBody(request) { ct, _, err := runtime.ContentType(request.Header) @@ -301,7 +304,13 @@ } // check and validate the response format - if len(res) == 0 && runtime.HasBody(request) { + if len(res) == 0 { + // if the route does not provide Produces and a default contentType could not be identified + // based on a body, typical for GET and DELETE requests, then default contentType to. + if len(route.Produces) == 0 && requestContentType == "" { + requestContentType = "*/*" + } + if str := NegotiateContentType(request, route.Produces, requestContentType); str == "" { res = append(res, errors.InvalidResponseFormat(request.Header.Get(runtime.HeaderAccept), route.Produces)) } @@ -426,10 +435,16 @@ } if route.Authorizer != nil { if err := route.Authorizer.Authorize(request, usr); err != nil { + if _, ok := err.(errors.Error); ok { + return nil, nil, err + } + return nil, nil, errors.New(http.StatusForbidden, err.Error()) } } + rCtx = request.Context() + rCtx = stdContext.WithValue(rCtx, ctxSecurityPrincipal, usr) rCtx = stdContext.WithValue(rCtx, ctxSecurityScopes, route.Authenticator.AllScopes()) return usr, request.WithContext(rCtx), nil @@ -500,6 +515,11 @@ if format == "" { rw.Header().Set(runtime.HeaderContentType, runtime.JSONMime) } + + if realm := security.FailedBasicAuth(r); realm != "" { + rw.Header().Set("WWW-Authenticate", fmt.Sprintf("Basic realm=%q", realm)) + } + if route == nil || route.Operation == nil { c.api.ServeErrorFor("")(rw, r, err) return @@ -551,6 +571,26 @@ c.api.ServeErrorFor(route.Operation.ID)(rw, r, errors.New(http.StatusInternalServerError, "can't produce response")) } +func (c *Context) APIHandlerSwaggerUI(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 + } + + swaggerUIOpts := SwaggerUIOpts{ + BasePath: c.BasePath(), + Title: title, + } + + return Spec("", c.spec.Raw(), SwaggerUI(swaggerUIOpts, c.RoutesHandler(b))) +} + // 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 diff -Nru golang-github-go-openapi-runtime-0.15.0/middleware/context_test.go golang-github-go-openapi-runtime-0.21.0/middleware/context_test.go --- golang-github-go-openapi-runtime-0.15.0/middleware/context_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/middleware/context_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -18,16 +18,26 @@ "errors" "net/http" "net/http/httptest" + "strings" "testing" + apierrors "github.com/go-openapi/errors" "github.com/go-openapi/loads" "github.com/go-openapi/loads/fmts" + "github.com/stretchr/testify/assert" + "github.com/go-openapi/runtime" "github.com/go-openapi/runtime/internal/testing/petstore" "github.com/go-openapi/runtime/middleware/untyped" - "github.com/stretchr/testify/assert" ) +type stubBindRequester struct { +} + +func (s *stubBindRequester) BindRequest(*http.Request, *MatchedRoute) error { + return nil +} + type stubOperationHandler struct { } @@ -43,6 +53,20 @@ loads.AddLoader(fmts.YAMLMatcher, fmts.YAMLDoc) } +func assertAPIError(t *testing.T, wantCode int, err error) { + t.Helper() + + assert.NotNil(t, err) + + ce, ok := err.(*apierrors.CompositeError) + assert.True(t, ok) + assert.NotEmpty(t, ce.Errors) + + ae, ok := ce.Errors[0].(apierrors.Error) + assert.True(t, ok) + assert.Equal(t, wantCode, int(ae.Code())) +} + func TestContentType_Issue264(t *testing.T) { swspec, err := loads.Spec("../fixtures/bugs/264/swagger.yml") if assert.NoError(t, err) { @@ -59,6 +83,45 @@ } } +func TestContentType_Issue172(t *testing.T) { + swspec, err := loads.Spec("../fixtures/bugs/172/swagger.yml") + if assert.NoError(t, err) { + api := untyped.NewAPI(swspec) + api.RegisterConsumer("application/vnd.cia.v1+json", runtime.JSONConsumer()) + api.RegisterProducer("application/vnd.cia.v1+json", runtime.JSONProducer()) + api.RegisterOperation("get", "/pets", new(stubOperationHandler)) + + handler := Serve(swspec, api) + request, _ := http.NewRequest("GET", "/pets", nil) + request.Header.Add("Accept", "application/json+special") + recorder := httptest.NewRecorder() + handler.ServeHTTP(recorder, request) + assert.Equal(t, http.StatusNotAcceptable, recorder.Code) + + // acceptable as defined as default by the API (not explicit in the spec) + request.Header.Add("Accept", "application/json") + recorder = httptest.NewRecorder() + handler.ServeHTTP(recorder, request) + assert.Equal(t, http.StatusOK, recorder.Code) + } +} + +func TestContentType_Issue174(t *testing.T) { + swspec, err := loads.Spec("../fixtures/bugs/174/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("get", "/pets", new(stubOperationHandler)) + + handler := Serve(swspec, api) + request, _ := http.NewRequest("GET", "/pets", nil) + recorder := httptest.NewRecorder() + handler.ServeHTTP(recorder, request) + assert.Equal(t, http.StatusOK, recorder.Code) + } +} + func TestServe(t *testing.T) { spec, api := petstore.NewAPI(t) handler := Serve(spec, api) @@ -146,7 +209,7 @@ request.SetBasicAuth("topuser", "topuser") p, reqWithCtx, err := ctx.Authorize(request, ri) - assert.Error(t, err) + assertAPIError(t, apierrors.InvalidTypeCode, err) assert.Nil(t, p) assert.Nil(t, reqWithCtx) @@ -155,6 +218,15 @@ assert.NoError(t, err) assert.Equal(t, "admin", p) assert.NotNil(t, reqWithCtx) + + request.SetBasicAuth("anyother", "anyother") + p, reqWithCtx, err = ctx.Authorize(request, ri) + assert.Error(t, err) + ae, ok := err.(apierrors.Error) + assert.True(t, ok) + assert.Equal(t, http.StatusForbidden, int(ae.Code())) + assert.Nil(t, p) + assert.Nil(t, reqWithCtx) } func TestContextNegotiateContentType(t *testing.T) { @@ -175,6 +247,51 @@ assert.Equal(t, ri.Produces[0], res) } +func TestContextBindValidRequest(t *testing.T) { + spec, api := petstore.NewAPI(t) + ctx := NewContext(spec, api, nil) + ctx.router = DefaultRouter(spec, ctx.api) + + // invalid content-type value + request, _ := http.NewRequest("POST", "/api/pets", strings.NewReader(`{"name":"dog"}`)) + request.Header.Add("content-type", "/json") + + ri, request, _ := ctx.RouteInfo(request) + assertAPIError(t, 400, ctx.BindValidRequest(request, ri, new(stubBindRequester))) + + // unsupported content-type value + request, _ = http.NewRequest("POST", "/api/pets", strings.NewReader(`{"name":"dog"}`)) + request.Header.Add("content-type", "text/html") + + ri, request, _ = ctx.RouteInfo(request) + assertAPIError(t, http.StatusUnsupportedMediaType, ctx.BindValidRequest(request, ri, new(stubBindRequester))) + + // unacceptable accept value + request, _ = http.NewRequest("POST", "/api/pets", nil) + request.Header.Add("Accept", "application/vnd.cia.v1+json") + request.Header.Add("content-type", "application/json") + + ri, request, _ = ctx.RouteInfo(request) + assertAPIError(t, http.StatusNotAcceptable, ctx.BindValidRequest(request, ri, new(stubBindRequester))) +} + +func TestContextBindValidRequest_Issue174(t *testing.T) { + spec, err := loads.Spec("../fixtures/bugs/174/swagger.yml") + assert.NoError(t, err) + + api := untyped.NewAPI(spec) + api.RegisterConsumer("application/json", runtime.JSONConsumer()) + api.RegisterProducer("application/json", runtime.JSONProducer()) + api.RegisterOperation("get", "/pets", new(stubOperationHandler)) + + ctx := NewContext(spec, api, nil) + ctx.router = DefaultRouter(spec, ctx.api) + + request, _ := http.NewRequest("GET", "/pets", nil) + ri, request, _ := ctx.RouteInfo(request) + assert.NoError(t, ctx.BindValidRequest(request, ri, new(stubBindRequester))) +} + func TestContextBindAndValidate(t *testing.T) { spec, api := petstore.NewAPI(t) ctx := NewContext(spec, api, nil) @@ -259,7 +376,6 @@ ri, request, _ = ctx.RouteInfo(request) ctx.Respond(recorder, request, ri.Produces, ri, nil) assert.Equal(t, 204, recorder.Code) - } func TestContextValidResponseFormat(t *testing.T) { diff -Nru golang-github-go-openapi-runtime-0.15.0/middleware/denco/router.go golang-github-go-openapi-runtime-0.21.0/middleware/denco/router.go --- golang-github-go-openapi-runtime-0.15.0/middleware/denco/router.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/middleware/denco/router.go 2021-10-29 03:50:47.000000000 +0000 @@ -17,6 +17,12 @@ // TerminationCharacter is a special character for end of path. TerminationCharacter = '#' + // SeparatorCharacter separates path segments. + SeparatorCharacter = '/' + + // PathParamCharacter indicates a RESTCONF path param + PathParamCharacter = '=' + // MaxSize is max size of records and internal slice. MaxSize = (1 << 22) - 1 ) @@ -420,10 +426,12 @@ // 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) + paramPrefix := string(SeparatorCharacter) + string(ParamCharacter) + wildcardPrefix := string(SeparatorCharacter) + string(WildcardCharacter) + restconfPrefix := string(PathParamCharacter) + string(ParamCharacter) for _, r := range srcs { - if strings.ContainsAny(r.Key, spChars) { + if strings.Contains(r.Key, paramPrefix) || strings.Contains(r.Key, wildcardPrefix) ||strings.Contains(r.Key, restconfPrefix){ r.Key += termChar params = append(params, &record{Record: r}) } else { diff -Nru golang-github-go-openapi-runtime-0.15.0/middleware/denco/router_test.go golang-github-go-openapi-runtime-0.21.0/middleware/denco/router_test.go --- golang-github-go-openapi-runtime-0.15.0/middleware/denco/router_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/middleware/denco/router_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -26,6 +26,7 @@ {"/:year/:month/:day", "testroute8"}, {"/user/:id", "testroute9"}, {"/a/to/b/:param/*routepath", "testroute10"}, + {"/path/with/key=:value", "testroute14"}, } } @@ -211,6 +212,7 @@ {"/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}, + {"/path/with/key=value", "testroute14", []denco.Param{{"value", "value"}}, true}, } runLookupTest(t, routes(), testcases) @@ -448,6 +450,7 @@ {[]string{"/user"}, 0}, {[]string{"/user/:id"}, 1}, {[]string{"/user/:id/post"}, 1}, + {[]string{"/user/:id/post:validate"}, 2}, {[]string{"/user/:id/:group"}, 2}, {[]string{"/user/:id/post/:cid"}, 2}, {[]string{"/user/:id/post/:cid", "/admin/:id/post/:cid"}, 2}, @@ -487,6 +490,7 @@ {"/user/:id", 3, 3}, {"/user/:id/:group", 0, 0}, {"/user/:id/:group", 1, 1}, + {"/user/:id/:group:validate", 1, 1}, } { r := denco.New() r.SizeHint = v.sizeHint diff -Nru golang-github-go-openapi-runtime-0.15.0/middleware/header/header.go golang-github-go-openapi-runtime-0.21.0/middleware/header/header.go --- golang-github-go-openapi-runtime-0.15.0/middleware/header/header.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/middleware/header/header.go 2021-10-29 03:50:47.000000000 +0000 @@ -265,13 +265,16 @@ case len(s) == 0: return -1, "" case s[0] == '0': - q = 0 + // q is already 0 + s = s[1:] case s[0] == '1': + s = s[1:] q = 1 + case s[0] == '.': + // q is already 0 default: return -1, "" } - s = s[1:] if !strings.HasPrefix(s, ".") { return q, s } diff -Nru golang-github-go-openapi-runtime-0.15.0/middleware/negotiate_test.go golang-github-go-openapi-runtime-0.21.0/middleware/negotiate_test.go --- golang-github-go-openapi-runtime-0.15.0/middleware/negotiate_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/middleware/negotiate_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -61,6 +61,9 @@ {"application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited;q=0.7,text/plain;version=0.0.4;q=0.3", []string{"text/plain"}, "", "text/plain"}, {"application/json", []string{"application/json; charset=utf-8", "image/png"}, "", "application/json; charset=utf-8"}, {"application/json; charset=utf-8", []string{"application/json; charset=utf-8", "image/png"}, "", "application/json; charset=utf-8"}, + {"application/json", []string{"application/vnd.cia.v1+json"}, "", ""}, + // Default header of java clients + {"text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2", []string{"application/json"}, "", "application/json"}, } func TestNegotiateContentType(t *testing.T) { diff -Nru golang-github-go-openapi-runtime-0.15.0/middleware/not_implemented.go golang-github-go-openapi-runtime-0.21.0/middleware/not_implemented.go --- golang-github-go-openapi-runtime-0.15.0/middleware/not_implemented.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/middleware/not_implemented.go 2021-10-29 03:50:47.000000000 +0000 @@ -38,11 +38,30 @@ rw.WriteHeader(http.StatusInternalServerError) } if err := producer.Produce(rw, e.response); err != nil { - panic(err) + Logger.Printf("failed to write error response: %v", err) } } // NotImplemented the error response when the response is not implemented func NotImplemented(message string) Responder { - return &errorResp{http.StatusNotImplemented, message, make(http.Header)} + return Error(http.StatusNotImplemented, message) +} + +// Error creates a generic responder for returning errors, the data will be serialized +// with the matching producer for the request +func Error(code int, data interface{}, headers ...http.Header) Responder { + var hdr http.Header + for _, h := range headers { + for k, v := range h { + if hdr == nil { + hdr = make(http.Header) + } + hdr[k] = v + } + } + return &errorResp{ + code: code, + response: data, + headers: hdr, + } } diff -Nru golang-github-go-openapi-runtime-0.15.0/middleware/not_implemented_test.go golang-github-go-openapi-runtime-0.21.0/middleware/not_implemented_test.go --- golang-github-go-openapi-runtime-0.15.0/middleware/not_implemented_test.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/middleware/not_implemented_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -0,0 +1,20 @@ +package middleware + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/go-openapi/runtime" + "github.com/stretchr/testify/require" +) + +func TestErrorResponder(t *testing.T) { + resp := Error(http.StatusBadRequest, map[string]string{"message": "this is the error body"}) + + rec := httptest.NewRecorder() + resp.WriteResponse(rec, runtime.JSONProducer()) + + require.Equal(t, http.StatusBadRequest, rec.Code) + require.Equal(t, "{\"message\":\"this is the error body\"}\n", rec.Body.String()) +} diff -Nru golang-github-go-openapi-runtime-0.15.0/middleware/operation_test.go golang-github-go-openapi-runtime-0.21.0/middleware/operation_test.go --- golang-github-go-openapi-runtime-0.15.0/middleware/operation_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/middleware/operation_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -20,9 +20,10 @@ "testing" "github.com/go-openapi/errors" + "github.com/stretchr/testify/assert" + "github.com/go-openapi/runtime" "github.com/go-openapi/runtime/internal/testing/petstore" - "github.com/stretchr/testify/assert" ) func TestOperationExecutor(t *testing.T) { diff -Nru golang-github-go-openapi-runtime-0.15.0/middleware/parameter.go golang-github-go-openapi-runtime-0.21.0/middleware/parameter.go --- golang-github-go-openapi-runtime-0.15.0/middleware/parameter.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/middleware/parameter.go 2021-10-29 03:50:47.000000000 +0000 @@ -24,11 +24,12 @@ "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" + + "github.com/go-openapi/runtime" ) const defaultMaxMemory = 32 << 20 @@ -275,7 +276,7 @@ } if (!hasKey || (!p.parameter.AllowEmptyValue && data == "")) && p.parameter.Required && p.parameter.Default == nil { - return errors.Required(p.Name, p.parameter.In) + return errors.Required(p.Name, p.parameter.In, data) } ok, err := p.tryUnmarshaler(target, defaultValue, data) @@ -450,7 +451,7 @@ 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) + return errors.Required(p.Name, p.parameter.In, data) } defVal := reflect.Zero(target.Type()) diff -Nru golang-github-go-openapi-runtime-0.15.0/middleware/parameter_test.go golang-github-go-openapi-runtime-0.21.0/middleware/parameter_test.go --- golang-github-go-openapi-runtime-0.15.0/middleware/parameter_test.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/middleware/parameter_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -22,10 +22,11 @@ "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" + + "github.com/go-openapi/runtime" ) // type email struct { @@ -64,29 +65,28 @@ } } -func requiredError(param *spec.Parameter) *errors.Validation { - return errors.Required(param.Name, param.In) +func requiredError(param *spec.Parameter, data interface{}) *errors.Validation { + return errors.Required(param.Name, param.In, data) } 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()) + assert.EqualError(t, requiredError(param, value.Interface()), err.Error()) err = binder.bindValue([]string{""}, true, value) if assert.Error(t, err) { - assert.EqualError(t, requiredError(param), err.Error()) + assert.EqualError(t, requiredError(param, value.Interface()), 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()) + assert.EqualError(t, requiredError(param, value.Interface()), err.Error()) err = binder.bindValue([]string{""}, false, value) assert.Error(t, err) - assert.EqualError(t, requiredError(param), err.Error()) + assert.EqualError(t, requiredError(param, value.Interface()), err.Error()) } func validateRequiredAllowEmptyTest(t *testing.T, param *spec.Parameter, value reflect.Value) { @@ -99,10 +99,10 @@ assert.NoError(t, err) err = binder.bindValue([]string{"1"}, false, value) assert.Error(t, err) - assert.EqualError(t, requiredError(param), err.Error()) + assert.EqualError(t, requiredError(param, value.Interface()), err.Error()) err = binder.bindValue([]string{""}, false, value) assert.Error(t, err) - assert.EqualError(t, requiredError(param), err.Error()) + assert.EqualError(t, requiredError(param, value.Interface()), err.Error()) } } diff -Nru golang-github-go-openapi-runtime-0.15.0/middleware/rapidoc.go golang-github-go-openapi-runtime-0.21.0/middleware/rapidoc.go --- golang-github-go-openapi-runtime-0.15.0/middleware/rapidoc.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/middleware/rapidoc.go 2021-10-29 03:50:47.000000000 +0000 @@ -0,0 +1,90 @@ +package middleware + +import ( + "bytes" + "fmt" + "html/template" + "net/http" + "path" +) + +// RapiDocOpts configures the RapiDoc middlewares +type RapiDocOpts 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 + // RapiDocURL for the js that generates the rapidoc site, defaults to: https://cdn.jsdelivr.net/npm/rapidoc/bundles/rapidoc.standalone.js + RapiDocURL string + // Title for the documentation site, default to: API documentation + Title string +} + +// EnsureDefaults in case some options are missing +func (r *RapiDocOpts) EnsureDefaults() { + if r.BasePath == "" { + r.BasePath = "/" + } + if r.Path == "" { + r.Path = "docs" + } + if r.SpecURL == "" { + r.SpecURL = "/swagger.json" + } + if r.RapiDocURL == "" { + r.RapiDocURL = rapidocLatest + } + if r.Title == "" { + r.Title = "API documentation" + } +} + +// RapiDoc creates a middleware to serve a documentation site for a swagger spec. +// This allows for altering the spec before starting the http listener. +// +func RapiDoc(opts RapiDocOpts, next http.Handler) http.Handler { + opts.EnsureDefaults() + + pth := path.Join(opts.BasePath, opts.Path) + tmpl := template.Must(template.New("rapidoc").Parse(rapidocTemplate)) + + 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 ( + rapidocLatest = "https://unpkg.com/rapidoc/dist/rapidoc-min.js" + rapidocTemplate = ` + + + {{ .Title }} + + + + + + + +` +) diff -Nru golang-github-go-openapi-runtime-0.15.0/middleware/rapidoc_test.go golang-github-go-openapi-runtime-0.21.0/middleware/rapidoc_test.go --- golang-github-go-openapi-runtime-0.15.0/middleware/rapidoc_test.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/middleware/rapidoc_test.go 2021-10-29 03:50:47.000000000 +0000 @@ -0,0 +1,22 @@ +package middleware + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRapiDocMiddleware(t *testing.T) { + rapidoc := RapiDoc(RapiDocOpts{}, nil) + + req, _ := http.NewRequest("GET", "/docs", nil) + recorder := httptest.NewRecorder() + rapidoc.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(), "API documentation") + assert.Contains(t, recorder.Body.String(), "") + assert.Contains(t, recorder.Body.String(), rapidocLatest) +} diff -Nru golang-github-go-openapi-runtime-0.15.0/middleware/redoc.go golang-github-go-openapi-runtime-0.21.0/middleware/redoc.go --- golang-github-go-openapi-runtime-0.15.0/middleware/redoc.go 2018-06-28 22:01:56.000000000 +0000 +++ golang-github-go-openapi-runtime-0.21.0/middleware/redoc.go 2021-10-29 03:50:47.000000000 +0000 @@ -16,7 +16,7 @@ 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 for the js that generates the redoc site, defaults to: https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js RedocURL string // Title for the documentation site, default to: API documentation Title string @@ -74,13 +74,15 @@ } const ( - redocLatest = "https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js" + redocLatest = "https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js" redocTemplate = ` {{ .Title }} - - + + + +