2019-02-15 01:10:36 +00:00
|
|
|
package cache
|
|
|
|
|
|
|
|
import (
|
2019-03-12 20:21:02 +00:00
|
|
|
"bytes"
|
2019-02-15 01:10:36 +00:00
|
|
|
"context"
|
2019-03-12 20:21:02 +00:00
|
|
|
"io/ioutil"
|
2019-02-15 01:10:36 +00:00
|
|
|
"net/http"
|
2019-03-12 20:21:02 +00:00
|
|
|
"time"
|
2019-02-15 01:10:36 +00:00
|
|
|
|
|
|
|
"github.com/hashicorp/vault/api"
|
|
|
|
)
|
|
|
|
|
|
|
|
// SendRequest is the input for Proxier.Send.
|
|
|
|
type SendRequest struct {
|
2019-03-12 20:21:02 +00:00
|
|
|
Token string
|
|
|
|
Request *http.Request
|
|
|
|
|
|
|
|
// RequestBody is the stored body bytes from Request.Body. It is set here to
|
|
|
|
// avoid reading and re-setting the stream multiple times.
|
2019-02-15 01:10:36 +00:00
|
|
|
RequestBody []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
// SendResponse is the output from Proxier.Send.
|
|
|
|
type SendResponse struct {
|
2019-03-12 20:21:02 +00:00
|
|
|
Response *api.Response
|
|
|
|
|
|
|
|
// ResponseBody is the stored body bytes from Response.Body. It is set here to
|
|
|
|
// avoid reading and re-setting the stream multiple times.
|
2019-02-15 01:10:36 +00:00
|
|
|
ResponseBody []byte
|
2019-03-12 20:21:02 +00:00
|
|
|
CacheMeta *CacheMeta
|
|
|
|
}
|
|
|
|
|
|
|
|
// CacheMeta contains metadata information about the response,
|
|
|
|
// such as whether it was a cache hit or miss, and the age of the
|
|
|
|
// cached entry.
|
|
|
|
type CacheMeta struct {
|
|
|
|
Hit bool
|
|
|
|
Age time.Duration
|
2019-02-15 01:10:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Proxier is the interface implemented by different components that are
|
|
|
|
// responsible for performing specific tasks, such as caching and proxying. All
|
|
|
|
// these tasks combined together would serve the request received by the agent.
|
|
|
|
type Proxier interface {
|
|
|
|
Send(ctx context.Context, req *SendRequest) (*SendResponse, error)
|
|
|
|
}
|
2019-03-12 20:21:02 +00:00
|
|
|
|
|
|
|
// NewSendResponse creates a new SendResponse and takes care of initializing its
|
|
|
|
// fields properly.
|
|
|
|
func NewSendResponse(apiResponse *api.Response, responseBody []byte) (*SendResponse, error) {
|
|
|
|
resp := &SendResponse{
|
|
|
|
Response: apiResponse,
|
|
|
|
CacheMeta: &CacheMeta{},
|
|
|
|
}
|
|
|
|
|
|
|
|
// If a response body is separately provided we set that as the SendResponse.ResponseBody,
|
|
|
|
// otherwise we will do an ioutil.ReadAll to extract the response body from apiResponse.
|
|
|
|
switch {
|
|
|
|
case len(responseBody) > 0:
|
|
|
|
resp.ResponseBody = responseBody
|
|
|
|
case apiResponse.Body != nil:
|
|
|
|
respBody, err := ioutil.ReadAll(apiResponse.Body)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
// Close the old body
|
|
|
|
apiResponse.Body.Close()
|
|
|
|
|
|
|
|
// Re-set the response body after reading from the Reader
|
|
|
|
apiResponse.Body = ioutil.NopCloser(bytes.NewReader(respBody))
|
|
|
|
|
|
|
|
resp.ResponseBody = respBody
|
|
|
|
}
|
|
|
|
|
|
|
|
return resp, nil
|
|
|
|
}
|