Skip to content

Commit 7258cb7

Browse files
weltekialexellis
authored andcommitted
Support request debug logging in the builder package
The request body is only logged if the Content-Type is printable (e.g. application/json or text/plain) to prevent payloads that are not human readable, like the build context tar, from getting logged out. Signed-off-by: Han Verstraete (OpenFaaS Ltd) <[email protected]>
1 parent 6fcb167 commit 7258cb7

File tree

7 files changed

+273
-190
lines changed

7 files changed

+273
-190
lines changed

builder/builder.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"strings"
1919

2020
"github.com/alexellis/hmac/v2"
21+
"github.com/openfaas/go-sdk/internal/httpclient"
2122
)
2223

2324
const BuilderConfigFileName = "com.openfaas.docker.config"
@@ -80,6 +81,8 @@ func WithHmacAuth(secret string) BuilderOption {
8081

8182
// NewFunctionBuilder create a new builder for building OpenFaaS functions using the Function Builder API.
8283
func NewFunctionBuilder(url *url.URL, client *http.Client, options ...BuilderOption) *FunctionBuilder {
84+
client = httpclient.WithFaasTransport(client)
85+
8386
b := &FunctionBuilder{
8487
URL: url,
8588

client.go

Lines changed: 29 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,13 @@ import (
99
"log"
1010
"net/http"
1111
"net/url"
12-
"os"
1312
"path/filepath"
14-
"sort"
1513
"strconv"
16-
"strings"
1714
"time"
1815

1916
"github.com/openfaas/faas-provider/logs"
2017
"github.com/openfaas/faas-provider/types"
18+
"github.com/openfaas/go-sdk/internal/httpclient"
2119
)
2220

2321
// Client is used to manage OpenFaaS and invoke functions
@@ -39,25 +37,6 @@ type Client struct {
3937
fnTokenCache TokenCache
4038
}
4139

42-
// Wrap http request Do function to add default headers and support debug capabilities
43-
func (s *Client) do(req *http.Request) (*http.Response, error) {
44-
// Add default user-agent header
45-
if len(req.Header.Get("User-Agent")) == 0 {
46-
req.Header.Set("User-Agent", "openfaas-go-sdk")
47-
}
48-
49-
if os.Getenv("FAAS_DEBUG") == "1" {
50-
dump, err := dumpRequest(req)
51-
if err != nil {
52-
return nil, err
53-
}
54-
55-
fmt.Println(dump)
56-
}
57-
58-
return s.client.Do(req)
59-
}
60-
6140
// ClientAuth an interface for client authentication.
6241
// to add authentication to the client implement this interface
6342
type ClientAuth interface {
@@ -96,6 +75,9 @@ func NewClient(gatewayURL *url.URL, auth ClientAuth, client *http.Client) *Clien
9675
// NewClientWithOpts creates a Client for managing OpenFaaS and invoking functions
9776
// It takes a list of ClientOptions to configure the client.
9877
func NewClientWithOpts(gatewayURL *url.URL, client *http.Client, options ...ClientOption) *Client {
78+
// Wrap http client to add default headers and support debug capabilities
79+
client = httpclient.WithFaasTransport(client)
80+
9981
c := &Client{
10082
GatewayURL: gatewayURL,
10183

@@ -136,7 +118,7 @@ func (s *Client) GetNamespaces(ctx context.Context) ([]string, error) {
136118
}
137119
}
138120

139-
res, err := s.do(req)
121+
res, err := s.client.Do(req)
140122
if err != nil {
141123
return namespaces, fmt.Errorf("unable to make request: %w", err)
142124
}
@@ -181,7 +163,7 @@ func (s *Client) GetNamespace(ctx context.Context, namespace string) (types.Func
181163
}
182164
}
183165

184-
res, err := s.do(req)
166+
res, err := s.client.Do(req)
185167
if err != nil {
186168
return types.FunctionNamespace{}, fmt.Errorf("unable to make HTTP request: %w", err)
187169
}
@@ -240,14 +222,15 @@ func (s *Client) CreateNamespace(ctx context.Context, spec types.FunctionNamespa
240222
if err != nil {
241223
return http.StatusBadGateway, err
242224
}
225+
req.Header.Set("Content-Type", "application/json")
243226

244227
if s.ClientAuth != nil {
245228
if err := s.ClientAuth.Set(req); err != nil {
246229
return http.StatusInternalServerError, fmt.Errorf("unable to set Authorization header: %w", err)
247230
}
248231
}
249232

250-
res, err := s.do(req)
233+
res, err := s.client.Do(req)
251234
if err != nil {
252235
return http.StatusBadGateway, err
253236
}
@@ -299,14 +282,15 @@ func (s *Client) UpdateNamespace(ctx context.Context, spec types.FunctionNamespa
299282
if err != nil {
300283
return http.StatusBadGateway, err
301284
}
285+
req.Header.Set("Content-Type", "application/json")
302286

303287
if s.ClientAuth != nil {
304288
if err := s.ClientAuth.Set(req); err != nil {
305289
return http.StatusInternalServerError, fmt.Errorf("unable to set Authorization header: %w", err)
306290
}
307291
}
308292

309-
res, err := s.do(req)
293+
res, err := s.client.Do(req)
310294
if err != nil {
311295
return http.StatusBadGateway, err
312296
}
@@ -354,13 +338,14 @@ func (s *Client) DeleteNamespace(ctx context.Context, namespace string) error {
354338
if err != nil {
355339
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", u.String(), err)
356340
}
341+
req.Header.Set("Content-Type", "application/json")
357342

358343
if s.ClientAuth != nil {
359344
if err := s.ClientAuth.Set(req); err != nil {
360345
return fmt.Errorf("unable to set Authorization header: %w", err)
361346
}
362347
}
363-
res, err := s.do(req)
348+
res, err := s.client.Do(req)
364349
if err != nil {
365350
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
366351

@@ -414,7 +399,7 @@ func (s *Client) GetFunctions(ctx context.Context, namespace string) ([]types.Fu
414399
}
415400
}
416401

417-
res, err := s.do(req)
402+
res, err := s.client.Do(req)
418403
if err != nil {
419404
return []types.FunctionStatus{}, fmt.Errorf("unable to make HTTP request: %w", err)
420405
}
@@ -449,7 +434,7 @@ func (s *Client) GetInfo(ctx context.Context) (SystemInfo, error) {
449434
}
450435
}
451436

452-
res, err := s.do(req)
437+
res, err := s.client.Do(req)
453438
if err != nil {
454439
return SystemInfo{}, fmt.Errorf("unable to make HTTP request: %w", err)
455440
}
@@ -491,7 +476,7 @@ func (s *Client) GetFunction(ctx context.Context, name, namespace string) (types
491476
}
492477
}
493478

494-
res, err := s.do(req)
479+
res, err := s.client.Do(req)
495480
if err != nil {
496481
return types.FunctionStatus{}, fmt.Errorf("unable to make HTTP request: %w", err)
497482
}
@@ -536,14 +521,15 @@ func (s *Client) deploy(ctx context.Context, method string, spec types.FunctionD
536521
if err != nil {
537522
return http.StatusBadGateway, err
538523
}
524+
req.Header.Set("Content-Type", "application/json")
539525

540526
if s.ClientAuth != nil {
541527
if err := s.ClientAuth.Set(req); err != nil {
542528
return http.StatusInternalServerError, fmt.Errorf("unable to set Authorization header: %w", err)
543529
}
544530
}
545531

546-
res, err := s.do(req)
532+
res, err := s.client.Do(req)
547533
if err != nil {
548534
return http.StatusBadGateway, err
549535
}
@@ -587,13 +573,14 @@ func (s *Client) ScaleFunction(ctx context.Context, functionName, namespace stri
587573
if err != nil {
588574
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", u.String(), err)
589575
}
576+
req.Header.Set("Content-Type", "application/json")
590577

591578
if s.ClientAuth != nil {
592579
if err := s.ClientAuth.Set(req); err != nil {
593580
return fmt.Errorf("unable to set Authorization header: %w", err)
594581
}
595582
}
596-
res, err := s.do(req)
583+
res, err := s.client.Do(req)
597584
if err != nil {
598585
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
599586

@@ -645,13 +632,14 @@ func (s *Client) DeleteFunction(ctx context.Context, functionName, namespace str
645632
if err != nil {
646633
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", u.String(), err)
647634
}
635+
req.Header.Set("Content-Type", "application/json")
648636

649637
if s.ClientAuth != nil {
650638
if err := s.ClientAuth.Set(req); err != nil {
651639
return fmt.Errorf("unable to set Authorization header: %w", err)
652640
}
653641
}
654-
res, err := s.do(req)
642+
res, err := s.client.Do(req)
655643
if err != nil {
656644
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
657645

@@ -705,7 +693,7 @@ func (s *Client) GetSecrets(ctx context.Context, namespace string) ([]types.Secr
705693
}
706694
}
707695

708-
res, err := s.do(req)
696+
res, err := s.client.Do(req)
709697
if err != nil {
710698
return []types.Secret{}, fmt.Errorf("unable to make HTTP request: %w", err)
711699
}
@@ -742,14 +730,15 @@ func (s *Client) CreateSecret(ctx context.Context, spec types.Secret) (int, erro
742730
if err != nil {
743731
return http.StatusBadGateway, err
744732
}
733+
req.Header.Set("Content-Type", "application/json")
745734

746735
if s.ClientAuth != nil {
747736
if err := s.ClientAuth.Set(req); err != nil {
748737
return http.StatusInternalServerError, fmt.Errorf("unable to set Authorization header: %w", err)
749738
}
750739
}
751740

752-
res, err := s.do(req)
741+
res, err := s.client.Do(req)
753742
if err != nil {
754743
return http.StatusBadGateway, err
755744
}
@@ -789,14 +778,15 @@ func (s *Client) UpdateSecret(ctx context.Context, spec types.Secret) (int, erro
789778
if err != nil {
790779
return http.StatusBadGateway, err
791780
}
781+
req.Header.Set("Content-Type", "application/json")
792782

793783
if s.ClientAuth != nil {
794784
if err := s.ClientAuth.Set(req); err != nil {
795785
return http.StatusInternalServerError, fmt.Errorf("unable to set Authorization header: %w", err)
796786
}
797787
}
798788

799-
res, err := s.do(req)
789+
res, err := s.client.Do(req)
800790
if err != nil {
801791
return http.StatusBadGateway, err
802792
}
@@ -842,13 +832,14 @@ func (s *Client) DeleteSecret(ctx context.Context, secretName, namespace string)
842832
if err != nil {
843833
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", u.String(), err)
844834
}
835+
req.Header.Set("Content-Type", "application/json")
845836

846837
if s.ClientAuth != nil {
847838
if err := s.ClientAuth.Set(req); err != nil {
848839
return fmt.Errorf("unable to set Authorization header: %w", err)
849840
}
850841
}
851-
res, err := s.do(req)
842+
res, err := s.client.Do(req)
852843
if err != nil {
853844
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
854845

@@ -925,7 +916,7 @@ func (s *Client) GetLogs(ctx context.Context, functionName, namespace string, fo
925916
}
926917
}
927918

928-
res, err := s.do(req)
919+
res, err := s.client.Do(req)
929920
if err != nil {
930921
return nil, fmt.Errorf("cannot connect to OpenFaaS on URL: %s, error: %s", s.GatewayURL, err)
931922

@@ -971,51 +962,3 @@ func (s *Client) GetLogs(ctx context.Context, functionName, namespace string, fo
971962
}
972963
return logStream, nil
973964
}
974-
975-
func dumpRequest(req *http.Request) (string, error) {
976-
var sb strings.Builder
977-
978-
// Get all header keys and sort them
979-
keys := make([]string, 0, len(req.Header))
980-
for k := range req.Header {
981-
keys = append(keys, k)
982-
}
983-
sort.Strings(keys)
984-
985-
sb.WriteString(fmt.Sprintf("%s %s\n", req.Method, req.URL.String()))
986-
for _, k := range keys {
987-
v := req.Header[k]
988-
if k == "Authorization" {
989-
auth := "[REDACTED]"
990-
if len(v) == 0 {
991-
auth = "[NOT_SET]"
992-
} else {
993-
l, _, ok := strings.Cut(v[0], " ")
994-
if ok && (l == "Basic" || l == "Bearer") {
995-
auth = l + " [REDACTED]"
996-
}
997-
}
998-
sb.WriteString(fmt.Sprintf("%s: %s\n", k, auth))
999-
1000-
} else {
1001-
sb.WriteString(fmt.Sprintf("%s: %s\n", k, v))
1002-
}
1003-
}
1004-
1005-
if req.Body != nil {
1006-
r := io.NopCloser(req.Body)
1007-
buf := new(strings.Builder)
1008-
_, err := io.Copy(buf, r)
1009-
if err != nil {
1010-
return "", err
1011-
}
1012-
bodyDebug := buf.String()
1013-
if len(bodyDebug) > 0 {
1014-
sb.WriteString(fmt.Sprintf("%s\n", bodyDebug))
1015-
1016-
}
1017-
req.Body = io.NopCloser(strings.NewReader(buf.String()))
1018-
}
1019-
1020-
return sb.String(), nil
1021-
}

0 commit comments

Comments
 (0)