3
vendor/github.com/go-openapi/runtime/client/auth_info.go
generated
vendored
3
vendor/github.com/go-openapi/runtime/client/auth_info.go
generated
vendored
@@ -17,8 +17,9 @@ package client
|
||||
import (
|
||||
"encoding/base64"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
)
|
||||
|
||||
// PassThroughAuth never manipulates the request
|
||||
|
||||
213
vendor/github.com/go-openapi/runtime/client/request.go
generated
vendored
213
vendor/github.com/go-openapi/runtime/client/request.go
generated
vendored
@@ -18,10 +18,10 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
@@ -29,8 +29,9 @@ import (
|
||||
"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 @@ func newRequest(method, pathPattern string, writer runtime.ClientRequestWriter)
|
||||
header: make(http.Header),
|
||||
query: make(url.Values),
|
||||
timeout: DefaultTimeout,
|
||||
getBody: getRequestBuffer,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -67,6 +69,8 @@ type request struct {
|
||||
payload interface{}
|
||||
timeout time.Duration
|
||||
buf *bytes.Buffer
|
||||
|
||||
getBody func(r *request) []byte
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -86,67 +90,43 @@ func (r *request) isMultipart(mediaType string) bool {
|
||||
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() {
|
||||
@@ -172,20 +152,39 @@ func (r *request) buildHTTP(mediaType, basePath string, producers map[string]run
|
||||
}()
|
||||
for fn, f := range r.fileFields {
|
||||
for _, fi := range f {
|
||||
wrtr, err := mp.CreateFormFile(fn, filepath.Base(fi.Name()))
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
// Need to read the data so that we can detect the content type
|
||||
_, err := io.Copy(buf, fi)
|
||||
if err != nil {
|
||||
_ = pw.CloseWithError(err)
|
||||
log.Println(err)
|
||||
}
|
||||
fileBytes := buf.Bytes()
|
||||
fileContentType := http.DetectContentType(fileBytes)
|
||||
|
||||
newFi := runtime.NamedReader(fi.Name(), buf)
|
||||
|
||||
// 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)
|
||||
} else if _, err := io.Copy(wrtr, fi); err != nil {
|
||||
} else 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
|
||||
@@ -193,56 +192,108 @@ func (r *request) buildHTTP(mediaType, basePath string, producers map[string]run
|
||||
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)
|
||||
|
||||
return req, nil
|
||||
body = rdr
|
||||
goto DoneChoosingBodySource
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
return ioutil.NopCloser(&b), nil
|
||||
}
|
||||
|
||||
// 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 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.
|
||||
//
|
||||
// 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
|
||||
}
|
||||
req.ContentLength = int64(b.Len())
|
||||
if _, err := r.buf.Write(b.Bytes()); err != nil {
|
||||
if err := producer.Produce(r.buf, r.payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if runtime.CanHaveBody(req.Method) && req.Body == nil && req.Header.Get(runtime.HeaderContentType) == "" {
|
||||
req.Header.Set(runtime.HeaderContentType, mediaType)
|
||||
DoneChoosingBodySource:
|
||||
|
||||
if runtime.CanHaveBody(r.method) && body == nil && r.header.Get(runtime.HeaderContentType) == "" {
|
||||
r.header.Set(runtime.HeaderContentType, mediaType)
|
||||
}
|
||||
|
||||
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.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// 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 + "/"
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(r.method, urlPath, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.URL.RawQuery = r.query.Encode()
|
||||
req.Header = r.header
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
@@ -266,6 +317,10 @@ func (r *request) GetPath() string {
|
||||
}
|
||||
|
||||
func (r *request) GetBody() []byte {
|
||||
return r.getBody(r)
|
||||
}
|
||||
|
||||
func getRequestBuffer(r *request) []byte {
|
||||
if r.buf == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
48
vendor/github.com/go-openapi/runtime/client/runtime.go
generated
vendored
48
vendor/github.com/go-openapi/runtime/client/runtime.go
generated
vendored
@@ -31,10 +31,11 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/logger"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
// TLSClientOptions to configure client authentication with mutual TLS
|
||||
@@ -66,6 +67,13 @@ type TLSClientOptions struct {
|
||||
// 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.
|
||||
@@ -75,6 +83,26 @@ type TLSClientOptions struct {
|
||||
// by the server are validated. If false, 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{}
|
||||
}
|
||||
@@ -121,11 +149,15 @@ func TLSClientAuth(opts TLSClientOptions) (*tls.Config, error) {
|
||||
|
||||
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 != "" {
|
||||
@@ -134,9 +166,11 @@ func TLSClientAuth(opts TLSClientOptions) (*tls.Config, error) {
|
||||
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
|
||||
@@ -150,6 +184,13 @@ func TLSClientAuth(opts TLSClientOptions) (*tls.Config, error) {
|
||||
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)
|
||||
@@ -350,6 +391,7 @@ func (r *Runtime) Submit(operation *runtime.ClientOperation) (interface{}, error
|
||||
}
|
||||
req.URL.Scheme = r.pickScheme(operation.Schemes)
|
||||
req.URL.Host = r.Host
|
||||
req.Host = r.Host
|
||||
|
||||
r.clientOnce.Do(func() {
|
||||
r.client = &http.Client{
|
||||
|
||||
Reference in New Issue
Block a user