1// Copyright 2017 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package main
16
17import (
18	"bytes"
19	"fmt"
20	"io"
21	"io/ioutil"
22	"net/http"
23	"os"
24)
25
26type logTransport struct {
27	rt http.RoundTripper
28}
29
30func (t *logTransport) RoundTrip(req *http.Request) (*http.Response, error) {
31	var buf bytes.Buffer
32
33	os.Stdout.Write([]byte("\n[request]\n"))
34	if req.Body != nil {
35		req.Body = ioutil.NopCloser(&readButCopy{req.Body, &buf})
36	}
37	req.Write(os.Stdout)
38	if req.Body != nil {
39		req.Body = ioutil.NopCloser(&buf)
40	}
41	os.Stdout.Write([]byte("\n[/request]\n"))
42
43	res, err := t.rt.RoundTrip(req)
44
45	fmt.Printf("[response]\n")
46	if err != nil {
47		fmt.Printf("ERROR: %v", err)
48	} else {
49		body := res.Body
50		res.Body = nil
51		res.Write(os.Stdout)
52		if body != nil {
53			res.Body = ioutil.NopCloser(&echoAsRead{body})
54		}
55	}
56
57	return res, err
58}
59
60type echoAsRead struct {
61	src io.Reader
62}
63
64func (r *echoAsRead) Read(p []byte) (int, error) {
65	n, err := r.src.Read(p)
66	if n > 0 {
67		os.Stdout.Write(p[:n])
68	}
69	if err == io.EOF {
70		fmt.Printf("\n[/response]\n")
71	}
72	return n, err
73}
74
75type readButCopy struct {
76	src io.Reader
77	dst io.Writer
78}
79
80func (r *readButCopy) Read(p []byte) (int, error) {
81	n, err := r.src.Read(p)
82	if n > 0 {
83		r.dst.Write(p[:n])
84	}
85	return n, err
86}
87