github.com/rigado/snapd@v2.42.5-go-mod+incompatible/httputil/logger.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016-2017 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package httputil 21 22 import ( 23 "errors" 24 "net/http" 25 "net/http/httputil" 26 "os" 27 "strconv" 28 29 "github.com/snapcore/snapd/logger" 30 ) 31 32 type debugflag uint 33 34 // set these via the Key environ 35 const ( 36 DebugRequest = debugflag(1 << iota) 37 DebugResponse 38 DebugBody 39 ) 40 41 func (f debugflag) debugRequest() bool { 42 return f&DebugRequest != 0 43 } 44 45 func (f debugflag) debugResponse() bool { 46 return f&DebugResponse != 0 47 } 48 49 func (f debugflag) debugBody() bool { 50 return f&DebugBody != 0 51 } 52 53 // LoggedTransport is an http.RoundTripper that can be used by 54 // http.Client to log request/response roundtrips. 55 type LoggedTransport struct { 56 Transport http.RoundTripper 57 Key string 58 body bool 59 } 60 61 // RoundTrip is from the http.RoundTripper interface. 62 func (tr *LoggedTransport) RoundTrip(req *http.Request) (*http.Response, error) { 63 flags := tr.getFlags() 64 65 if flags.debugRequest() { 66 buf, _ := httputil.DumpRequestOut(req, tr.body && flags.debugBody()) 67 logger.Debugf("> %q", buf) 68 } 69 70 rsp, err := tr.Transport.RoundTrip(req) 71 72 if err == nil && flags.debugResponse() { 73 buf, _ := httputil.DumpResponse(rsp, tr.body && flags.debugBody()) 74 logger.Debugf("< %q", buf) 75 } 76 77 return rsp, err 78 } 79 80 func (tr *LoggedTransport) getFlags() debugflag { 81 flags, err := strconv.Atoi(os.Getenv(tr.Key)) 82 if err != nil { 83 flags = 0 84 } 85 86 return debugflag(flags) 87 } 88 89 func checkRedirect(req *http.Request, via []*http.Request) error { 90 if len(via) > 10 { 91 return errors.New("stopped after 10 redirects") 92 } 93 // fixed in go 1.8 94 fixupHeadersForRedirect(req, via) 95 96 return nil 97 } 98 99 // BaseTransport returns the underlying http.Transport of a client created with NewHTTPClient. It panics if that's not the case. For tests. 100 func BaseTransport(cli *http.Client) *http.Transport { 101 tr, ok := cli.Transport.(*LoggedTransport) 102 if !ok { 103 panic("client must have been created with httputil.NewHTTPClient") 104 } 105 return tr.Transport.(*http.Transport) 106 }