providers/lib/client/debug.go (78 lines of code) (raw):

// Copyright (c) Facebook, Inc. and its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package client import ( "fmt" "net/http" "net/http/httputil" "os" "strconv" "sync/atomic" "github.com/facebookincubator/flog" ) var debug struct { // Print HTTP requests and responses to stderr. traceRequests bool // Print the bodies of HTTP requests and responses to stderr. traceRequestBodies bool // When tools issue concurrent GET requests, the normal behaviour is to // cancel pending requests as soon as one request fails. This option // restores the old behaviour or executing the remaning requests anyway. continueDownloading bool // When set to a number n, the n th HTTP request will fail. failRequestNum uint64 requestNum uint64 } func getBool(varName string) bool { v, _ := strconv.ParseBool(os.Getenv(varName)) return v } func getUint(varName string, defaultValue uint64) uint64 { v, err := strconv.ParseUint(os.Getenv(varName), 10, 64) if err != nil { return defaultValue } return v } func init() { debug.traceRequests = getBool("NVD_TRACE_REQUESTS") debug.traceRequestBodies = getBool("NVD_TRACE_REQUEST_BODIES") debug.continueDownloading = getBool("NVD_CONTINUE_DOWNLOADING") debug.failRequestNum = getUint("NVD_FAIL_REQUEST", 0) } func obfuscateHeaders(req *http.Request) *http.Request { authHeaders := []string{ "Authorization", // fireeye "X-Auth", "X-Auth-Hash", // idefense "Auth-Token", } headers := req.Header.Clone() for _, header := range authHeaders { if headers.Get(header) == "" { continue } headers.Set(header, "<obfuscated>") } // A shallow copy is enough for this usage. newReq := *req newReq.Header = headers return &newReq } func traceRequestStart(req *http.Request) uint64 { id := atomic.AddUint64(&debug.requestNum, 1) if !debug.traceRequests { return id } data, _ := httputil.DumpRequest(obfuscateHeaders(req), debug.traceRequestBodies) fmt.Fprintf(os.Stderr, "Req %d: %s", id, string(data)) return id } func traceRequestEnd(id uint64, resp *http.Response) { if !debug.traceRequests { return } if resp == nil { return } data, _ := httputil.DumpResponse(resp, debug.traceRequestBodies) fmt.Fprintf(os.Stderr, "Req %d: %s", id, string(data)) } // StopOrContinue can help controlling the behaviour of concurrent GET requests // when using an errgroup and encountering an error. Depending on the // NVD_CONTINUE_DOWNLOADING env variable, this function will return the passed // error (when we want to stop pending requests) or just log the error (when we // want the pending requests to continue being processed). func StopOrContinue(err error) error { if debug.continueDownloading { flog.Errorln(err) return nil } return err }