The code already existed for setting the UserAgent header, but a value was never passed to the client. This change will now set a string matching the following format ``` faas-cli/<build version> ``` For example: ``` faas-cli/0.14.6-5-ga9c2b10f ``` Signed-off-by: Lucas Roesler <roesler.lucas@gmail.com>
133 lines
3.0 KiB
Go
133 lines
3.0 KiB
Go
package proxy
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httputil"
|
|
"net/url"
|
|
"os"
|
|
gopath "path"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/openfaas/faas-cli/version"
|
|
)
|
|
|
|
// Client an API client to perform all operations
|
|
type Client struct {
|
|
httpClient *http.Client
|
|
//ClientAuth a type implementing ClientAuth interface for client authentication
|
|
ClientAuth ClientAuth
|
|
//GatewayURL base URL of OpenFaaS gateway
|
|
GatewayURL *url.URL
|
|
//UserAgent user agent for the client
|
|
UserAgent string
|
|
}
|
|
|
|
// ClientAuth an interface for client authentication.
|
|
// to add authentication to the client implement this interface
|
|
type ClientAuth interface {
|
|
Set(req *http.Request) error
|
|
}
|
|
|
|
// NewClient initializes a new API client
|
|
func NewClient(auth ClientAuth, gatewayURL string, transport http.RoundTripper, timeout *time.Duration) (*Client, error) {
|
|
gatewayURL = strings.TrimRight(gatewayURL, "/")
|
|
baseURL, err := url.Parse(gatewayURL)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid gateway URL: %s", gatewayURL)
|
|
}
|
|
|
|
client := &http.Client{}
|
|
if timeout != nil {
|
|
client.Timeout = *timeout
|
|
}
|
|
|
|
if transport != nil {
|
|
client.Transport = transport
|
|
}
|
|
|
|
return &Client{
|
|
ClientAuth: auth,
|
|
httpClient: client,
|
|
GatewayURL: baseURL,
|
|
UserAgent: fmt.Sprintf("faas-cli/%s", version.BuildVersion()),
|
|
}, nil
|
|
}
|
|
|
|
// newRequest create a new HTTP request with authentication
|
|
func (c *Client) newRequest(method, path string, query url.Values, body io.Reader) (*http.Request, error) {
|
|
|
|
// deep copy gateway url and then add the supplied path and args to the copy so that
|
|
// we preserve the original gateway URL as much as possible
|
|
endpoint, err := url.Parse(c.GatewayURL.String())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
endpoint.Path = gopath.Join(endpoint.Path, path)
|
|
endpoint.RawQuery = query.Encode()
|
|
|
|
req, err := http.NewRequest(method, endpoint.String(), body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if body != nil {
|
|
req.Header.Set("Content-Type", "application/json")
|
|
}
|
|
|
|
if c.UserAgent != "" {
|
|
req.Header.Set("User-Agent", c.UserAgent)
|
|
}
|
|
|
|
c.ClientAuth.Set(req)
|
|
|
|
return req, err
|
|
}
|
|
|
|
// doRequest perform an HTTP request with context
|
|
func (c *Client) doRequest(ctx context.Context, req *http.Request) (*http.Response, error) {
|
|
req = req.WithContext(ctx)
|
|
|
|
if val, ok := os.LookupEnv("OPENFAAS_DUMP_HTTP"); ok && val == "true" {
|
|
dump, err := httputil.DumpRequest(req, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
fmt.Println(string(dump))
|
|
}
|
|
|
|
res, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
select {
|
|
case <-ctx.Done():
|
|
return nil, ctx.Err()
|
|
default:
|
|
}
|
|
}
|
|
|
|
return res, err
|
|
}
|
|
|
|
func addQueryParams(u string, params map[string]string) (string, error) {
|
|
parsedURL, err := url.Parse(u)
|
|
if err != nil {
|
|
return u, err
|
|
}
|
|
|
|
qs := parsedURL.Query()
|
|
for key, value := range params {
|
|
qs.Add(key, value)
|
|
}
|
|
parsedURL.RawQuery = qs.Encode()
|
|
return parsedURL.String(), nil
|
|
}
|
|
|
|
// AddCheckRedirect add CheckRedirect to the client
|
|
func (c *Client) AddCheckRedirect(checkRedirect func(*http.Request, []*http.Request) error) {
|
|
c.httpClient.CheckRedirect = checkRedirect
|
|
}
|