handler.go 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. package logger
  2. import (
  3. "fmt"
  4. "io"
  5. "net/http"
  6. "strconv"
  7. "strings"
  8. "time"
  9. )
  10. type handler struct {
  11. h http.Handler
  12. w io.Writer
  13. c chan logMsg
  14. }
  15. func (this handler) log(w *writer, r *http.Request) {
  16. rip := r.RemoteAddr
  17. if r.Header.Get("X-Real-IP") != "" && len(r.Header.Get("X-Real-IP")) <= 25 {
  18. rip = rip + ", " + strings.TrimSpace(r.Header.Get("X-Real-IP"))
  19. } else if r.Header.Get("X-Forwarded-For") != "" && len(r.Header.Get("X-Forwarded-For")) <= 25 {
  20. rip = rip + ", " + strings.TrimSpace(r.Header.Get("X-Forwarded-For"))
  21. }
  22. uagent := "-"
  23. if r.Header.Get("User-Agent") != "" && len(r.Header.Get("User-Agent")) <= 256 {
  24. uagent = strings.TrimSpace(r.Header.Get("User-Agent"))
  25. }
  26. msg := fmt.Sprint(strings.Join([]string{
  27. r.Host,
  28. "(" + rip + ")",
  29. "[" + w.s.Format(time.RFC3339) + "]",
  30. `"` + r.Method,
  31. r.RequestURI,
  32. r.Proto + `"`,
  33. strconv.Itoa(w.status),
  34. strconv.Itoa(w.size),
  35. fmt.Sprintf("%.3f ms", time.Now().Sub(w.s).Seconds()),
  36. `"` + uagent + `"`,
  37. }, " "))
  38. select {
  39. case <-r.Context().Done():
  40. return
  41. case this.c <- logMsg{r.Host, msg, w.status >= 400}:
  42. return
  43. case <-time.After(1 * time.Second):
  44. fmt.Printf("Logger, can't write msg (overflow): %s\n", msg)
  45. return
  46. }
  47. }
  48. func (this handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  49. wrt := &writer{w: w, s: time.Now()}
  50. this.h.ServeHTTP(wrt, r)
  51. this.log(wrt, r)
  52. }