1
0
vault-redux/api/request.go

150 lines
3.0 KiB
Go
Raw Normal View History

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
2015-03-09 21:38:50 +03:00
package api
import (
"bytes"
"encoding/json"
"io"
2018-05-10 00:44:53 +03:00
"io/ioutil"
"net/http"
2015-03-09 21:38:50 +03:00
"net/url"
2018-05-10 00:44:53 +03:00
retryablehttp "github.com/hashicorp/go-retryablehttp"
2015-03-09 21:38:50 +03:00
)
// Request is a raw request configuration structure used to initiate
// API requests to the Vault server.
type Request struct {
2017-10-23 23:52:56 +03:00
Method string
URL *url.URL
Host string
2017-10-23 23:52:56 +03:00
Params url.Values
Headers http.Header
ClientToken string
MFAHeaderVals []string
WrapTTL string
Obj interface{}
// When possible, use BodyBytes as it is more efficient due to how the
// retry logic works
BodyBytes []byte
// Fallback
Body io.Reader
BodySize int64
2017-10-23 23:52:56 +03:00
// Whether to request overriding soft-mandatory Sentinel policies (RGPs and
// EGPs). If set, the override flag will take effect for all policies
// evaluated during the request.
PolicyOverride bool
2015-03-09 21:38:50 +03:00
}
// SetJSONBody is used to set a request body that is a JSON-encoded value.
func (r *Request) SetJSONBody(val interface{}) error {
buf, err := json.Marshal(val)
if err != nil {
2015-03-09 21:38:50 +03:00
return err
}
2015-04-20 20:44:51 +03:00
r.Obj = val
r.BodyBytes = buf
2015-03-09 21:38:50 +03:00
return nil
}
2015-04-20 20:44:51 +03:00
// ResetJSONBody is used to reset the body for a redirect
func (r *Request) ResetJSONBody() error {
if r.BodyBytes == nil {
2015-04-20 20:44:51 +03:00
return nil
}
return r.SetJSONBody(r.Obj)
}
// DEPRECATED: ToHTTP turns this request into a valid *http.Request for use
// with the net/http package.
func (r *Request) ToHTTP() (*http.Request, error) {
req, err := r.toRetryableHTTP()
2018-05-10 00:44:53 +03:00
if err != nil {
return nil, err
}
switch {
case r.BodyBytes == nil && r.Body == nil:
// No body
case r.BodyBytes != nil:
req.Request.Body = ioutil.NopCloser(bytes.NewReader(r.BodyBytes))
default:
if c, ok := r.Body.(io.ReadCloser); ok {
req.Request.Body = c
} else {
req.Request.Body = ioutil.NopCloser(r.Body)
}
}
2018-05-10 00:44:53 +03:00
return req.Request, nil
}
func (r *Request) toRetryableHTTP() (*retryablehttp.Request, error) {
2015-03-09 21:38:50 +03:00
// Encode the query parameters
r.URL.RawQuery = r.Params.Encode()
2018-05-10 00:44:53 +03:00
// Create the HTTP request, defaulting to retryable
var req *retryablehttp.Request
var err error
var body interface{}
switch {
case r.BodyBytes == nil && r.Body == nil:
// No body
case r.BodyBytes != nil:
// Use bytes, it's more efficient
body = r.BodyBytes
default:
body = r.Body
}
req, err = retryablehttp.NewRequest(r.Method, r.URL.RequestURI(), body)
if err != nil {
return nil, err
2015-03-09 21:38:50 +03:00
}
req.URL.User = r.URL.User
2015-03-09 21:38:50 +03:00
req.URL.Scheme = r.URL.Scheme
req.URL.Host = r.URL.Host
req.Host = r.Host
2015-03-09 21:38:50 +03:00
if r.Headers != nil {
for header, vals := range r.Headers {
for _, val := range vals {
req.Header.Add(header, val)
}
}
}
2015-08-22 03:36:19 +03:00
if len(r.ClientToken) != 0 {
2023-02-06 17:41:56 +03:00
req.Header.Set(AuthHeaderName, r.ClientToken)
2015-08-22 03:36:19 +03:00
}
2016-05-02 08:58:58 +03:00
if len(r.WrapTTL) != 0 {
req.Header.Set("X-Vault-Wrap-TTL", r.WrapTTL)
}
2017-10-23 23:52:56 +03:00
if len(r.MFAHeaderVals) != 0 {
for _, mfaHeaderVal := range r.MFAHeaderVals {
req.Header.Add("X-Vault-MFA", mfaHeaderVal)
}
}
if r.PolicyOverride {
req.Header.Set("X-Vault-Policy-Override", "true")
}
2015-03-09 21:38:50 +03:00
return req, nil
}