giffer

Create .gif images from sites like youtube.com
Log | Files | Refs | LICENSE

commit dc415b1904e4746c9be67ac4c37dc00741c69dab
parent 3a8276ba6d181769b736e6c8081151c6b616d5ae
Author: Jack Mordaunt <jackmordaunt@gmail.com>
Date:   Wed,  7 Nov 2018 12:51:43 +1300

[+] Implemented logging middleware.

Diffstat:
Mcmd/desktop/main.go | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 56 insertions(+), 6 deletions(-)

diff --git a/cmd/desktop/main.go b/cmd/desktop/main.go @@ -1,6 +1,7 @@ package main import ( + "os" "net/http/httputil" "net/url" "bytes" @@ -65,6 +66,8 @@ func main() { svr := &http.Server{ Addr: fmt.Sprintf(":%s", port), Handler: ui, + // Can't use these time-outs yet since the gifify route doesn't + // return immediately (downloads 400MB, etc...). // WriteTimeout: 15 * time.Second, // ReadTimeout: 15 * time.Second, } @@ -102,17 +105,18 @@ func (ui *UI) ServeHTTP(w http.ResponseWriter, r *http.Request) { } func (ui *UI) routes() { + log := Log{ + Logger: log.New(os.Stdout, "", 0), + ShowBody: true, + } + ui.Router.Handle("/gifify", Wrap(ui.gifify(), log)) // The router typically treats "/" as a unique router We have to tell // it otherwise in order to handle file paths correctly. - ui.Router.HandleFunc("/gifify", ui.gifify()) - ui.Router.Handle("/{path:.*}", ui.Static) + ui.Router.Handle("/{path:.*}", Wrap(ui.Static, log)) } func (ui *UI) gifify() http.HandlerFunc { - log.Printf("gifify route registered") return func(w http.ResponseWriter, r *http.Request) { - log.Printf("%s /gifify", r.Method) - defer log.Printf("done") defer r.Body.Close() type request struct { URL string `json:"url,omitempty"` @@ -128,7 +132,6 @@ func (ui *UI) gifify() http.HandlerFunc { ui.error(w, errors.Wrap(err, "decoding json request")) return } - log.Printf("%#v", req) img, err := ui.App.GififyURL( req.URL, req.Start, @@ -254,4 +257,51 @@ func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { r.Header.Set("X-Forwarded-Host", r.Header.Get("Host")) r.Host = p.Target.Host proxy.ServeHTTP(w, r) +} + +// Log creates middleware that logs requests. +// If out is nil it is assumed that no logs are desired. +type Log struct { + Logger *log.Logger + ShowBody bool +} + +// Wrap the handler with logging middleware. +func (l Log) Wrap(next http.Handler) http.Handler { + if l.Logger == nil { + return next + } + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var msg = &strings.Builder{} + fmt.Fprintf(msg, "%s %s", r.Method, r.URL) + if l.ShowBody { + by, _ := readUntil(r.Body, 1000*64) // 64Kb + if len(by) > 0 { + fmt.Fprintf(msg, " body:\n%s\n", string(by)) + } + } + l.Logger.Printf(msg.String()) + next.ServeHTTP(w, r) + }) +} + +func readUntil(r io.Reader, until int64) ([]byte, error) { + buf := bytes.NewBuffer(nil) + if _, err := io.CopyN(buf, r, until); err != nil && err != io.EOF { + return buf.Bytes(), err + } + return buf.Bytes(), nil +} + +// Wrapper wraps an http.Handler to provide things like middleware. +type Wrapper interface { + Wrap(http.Handler) http.Handler +} + +// Wrap the handler with the provided wrappers. +func Wrap(h http.Handler, wrappers ...Wrapper) http.Handler { + for _, w := range wrappers { + h = w.Wrap(h) + } + return h } \ No newline at end of file