Просмотр исходного кода

Refactor log into self-managing objects

Lu Stadler лет назад: 7
Родитель
Сommit
1bd93213d3
1 измененных файлов с 50 добавлено и 19 удалено
  1. 50 19
      go/fake-http/fake-http.go

+ 50 - 19
go/fake-http/fake-http.go

10
	"io/ioutil"
10
	"io/ioutil"
11
	"log"
11
	"log"
12
	"net/http"
12
	"net/http"
13
	"net/http/httputil"
14
	"net/url"
13
	"net/url"
15
	"os"
14
	"os"
16
	"os/exec"
15
	"os/exec"
58
		responsesPath = flag.Arg(0)
57
		responsesPath = flag.Arg(0)
59
	}
58
	}
60
59
61
	requestLog := make([]LogEntry, 0)
60
	requestLog := Log(make([]LogEntry, 0))
62
61
63
	http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
62
	http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
64
		responses.Load(responsesPath)
63
		responses.Load(responsesPath)
73
		userAgent := req.Header.Get("User-Agent")
72
		userAgent := req.Header.Get("User-Agent")
74
		log.Printf("%s %s - %d (%s, %q)", req.Method, req.URL, resp.StatusCode, req.RemoteAddr, userAgent)
73
		log.Printf("%s %s - %d (%s, %q)", req.Method, req.URL, resp.StatusCode, req.RemoteAddr, userAgent)
75
74
76
		out, err := httputil.DumpRequest(req, true)
77
		if err != nil {
78
			log.Printf("Error: Dumping request: %s", err)
79
			return
80
		}
81
82
		if resp.Header.Get("Content-Type") == "application/json" {
75
		if resp.Header.Get("Content-Type") == "application/json" {
83
			pretty, err := prettyfyJSON(resp.Body)
76
			pretty, err := prettyfyJSON(resp.Body)
84
			if err != nil {
77
			if err != nil {
89
			}
82
			}
90
		}
83
		}
91
84
92
		requestLog = append(requestLog, LogEntry{
93
			Request:  out,
94
			Response: asResponse(req, resp),
95
		})
85
		requestLog.Log(req, resp)
96
	})
86
	})
97
87
98
	http.HandleFunc("/_log", func(w http.ResponseWriter, req *http.Request) {
88
	http.HandleFunc("/_log", func(w http.ResponseWriter, req *http.Request) {
99
		if strings.Contains(req.Header.Get("Accept"), "application/yaml") {
89
		if strings.Contains(req.Header.Get("Accept"), "application/yaml") {
100
			rs := make([]Response, len(requestLog))
90
			rs := make([]Response, len(requestLog))
101
			for i, log := range requestLog {
91
			for i, log := range requestLog {
102
				rs[i] = log.Response
92
				rs[i] = log.AsResponse()
103
			}
93
			}
104
			err := renderYAML(w, rs)
94
			err := renderYAML(w, rs)
105
			if err != nil {
95
			if err != nil {
110
100
111
		for i := len(requestLog) - 1; i >= 0; i-- {
101
		for i := len(requestLog) - 1; i >= 0; i-- {
112
			w.Write([]byte("------------------------------------------------------\n"))
102
			w.Write([]byte("------------------------------------------------------\n"))
113
			w.Write(requestLog[i].Request)
114
			w.Write([]byte("\n\n"))
115
			requestLog[i].Response.AsHTTP().Write(w)
103
			requestLog[i].Request().Write(w)
104
			w.Write([]byte("\n"))
105
			requestLog[i].Response().Write(w)
116
			w.Write([]byte("\n"))
106
			w.Write([]byte("\n"))
117
		}
107
		}
118
	})
108
	})
253
	return nil
243
	return nil
254
}
244
}
255
245
256
// LogEntry is a request/respond pair for logging.
246
// Log collects HTTP requests/responses for later display and
247
// processing.
248
type Log []LogEntry
249
250
// Log logs the request/response pair.
251
func (l *Log) Log(req *http.Request, resp *http.Response) {
252
	e := LogEntry{
253
		request:      req,
254
		requestBody:  new(bytes.Buffer),
255
		response:     resp,
256
		responseBody: new(bytes.Buffer),
257
	}
258
	io.Copy(e.requestBody, req.Body)
259
	io.Copy(e.responseBody, resp.Body)
260
	*l = append(*l, e)
261
}
262
263
// LogEntry is a request/response pair for logging.
257
type LogEntry struct {
264
type LogEntry struct {
258
	Request  Request
259
	Response Response
265
	request      *http.Request
266
	requestBody  *bytes.Buffer
267
	response     *http.Response
268
	responseBody *bytes.Buffer
269
}
270
271
// AsResponse returns a Response representation of the entry.
272
func (e LogEntry) AsResponse() Response {
273
	return Response{
274
		Method: e.request.Method,
275
		Path:   e.request.URL.Path,
276
		Status: e.response.StatusCode,
277
		Body:   e.responseBody.String(),
278
	}
279
}
280
281
// Request returns the stored http.Request.
282
func (e LogEntry) Request() *http.Request {
283
	e.request.Body = ioutil.NopCloser(bytes.NewReader(e.requestBody.Bytes()))
284
	return e.request
285
}
286
287
// Response returns the stored http.Response.
288
func (e LogEntry) Response() *http.Response {
289
	e.response.Body = ioutil.NopCloser(bytes.NewReader(e.responseBody.Bytes()))
290
	return e.response
260
}
291
}
261
292
262
// Request is a stored serialized HTTP request.
293
// Request is a stored serialized HTTP request.