您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

218 行
5.3 KiB

  1. package handlers
  2. import (
  3. "bytes"
  4. "fmt"
  5. "log"
  6. "net/http"
  7. "net/http/httptest"
  8. "regexp"
  9. "testing"
  10. "time"
  11. )
  12. type testCase struct {
  13. tok string
  14. fmt string
  15. rx *regexp.Regexp
  16. }
  17. func TestLog(t *testing.T) {
  18. log.SetFlags(0)
  19. now := time.Now()
  20. formats := []testCase{
  21. testCase{"remote-addr",
  22. "%s",
  23. regexp.MustCompile(`^127\.0\.0\.1:\d+\n$`),
  24. },
  25. testCase{"date",
  26. "%s",
  27. regexp.MustCompile(`^` + fmt.Sprintf("%04d-%02d-%02d", now.Year(), now.Month(), now.Day()) + `\n$`),
  28. },
  29. testCase{"method",
  30. "%s",
  31. regexp.MustCompile(`^GET\n$`),
  32. },
  33. testCase{"url",
  34. "%s",
  35. regexp.MustCompile(`^/\n$`),
  36. },
  37. testCase{"http-version",
  38. "%s",
  39. regexp.MustCompile(`^1\.1\n$`),
  40. },
  41. testCase{"status",
  42. "%d",
  43. regexp.MustCompile(`^200\n$`),
  44. },
  45. testCase{"referer",
  46. "%s",
  47. regexp.MustCompile(`^http://www\.test\.com\n$`),
  48. },
  49. testCase{"referrer",
  50. "%s",
  51. regexp.MustCompile(`^http://www\.test\.com\n$`),
  52. },
  53. testCase{"user-agent",
  54. "%s",
  55. regexp.MustCompile(`^Go \d+\.\d+ package http\n$`),
  56. },
  57. testCase{"bidon",
  58. "%s",
  59. regexp.MustCompile(`^\?\n$`),
  60. },
  61. testCase{"response-time",
  62. "%.3f",
  63. regexp.MustCompile(`^0\.1\d\d\n$`),
  64. },
  65. testCase{"req[Accept-Encoding]",
  66. "%s",
  67. regexp.MustCompile(`^gzip\n$`),
  68. },
  69. testCase{"res[blah]",
  70. "%s",
  71. regexp.MustCompile(`^$`),
  72. },
  73. testCase{"tiny",
  74. Ltiny,
  75. regexp.MustCompile(`^GET / 200 - 0\.1\d\d s\n$`),
  76. },
  77. testCase{"short",
  78. Lshort,
  79. regexp.MustCompile(`^127\.0\.0\.1:\d+ - GET / HTTP/1\.1 200 - 0\.1\d\d s\n$`),
  80. },
  81. testCase{"default",
  82. Ldefault,
  83. regexp.MustCompile(`^127\.0\.0\.1:\d+ - - \[\d{4}-\d{2}-\d{2}\] "GET / HTTP/1\.1" 200 "http://www\.test\.com" "Go \d+\.\d+ package http"\n$`),
  84. },
  85. testCase{"res[Content-Type]",
  86. "%s",
  87. regexp.MustCompile(`^text/plain\n$`),
  88. },
  89. }
  90. for _, tc := range formats {
  91. testLogCase(tc, t)
  92. }
  93. }
  94. func testLogCase(tc testCase, t *testing.T) {
  95. buf := bytes.NewBuffer(nil)
  96. log.SetOutput(buf)
  97. opts := NewLogOptions(log.Printf, tc.fmt, tc.tok)
  98. opts.DateFormat = "2006-01-02"
  99. h := LogHandler(http.HandlerFunc(
  100. func(w http.ResponseWriter, r *http.Request) {
  101. time.Sleep(100 * time.Millisecond)
  102. w.Header().Set("Content-Type", "text/plain")
  103. w.WriteHeader(200)
  104. w.Write([]byte("body"))
  105. }), opts)
  106. s := httptest.NewServer(h)
  107. defer s.Close()
  108. t.Logf("running %s...", tc.tok)
  109. req, err := http.NewRequest("GET", s.URL, nil)
  110. if err != nil {
  111. panic(err)
  112. }
  113. req.Header.Set("Referer", "http://www.test.com")
  114. req.Header.Set("Accept-Encoding", "gzip")
  115. res, err := http.DefaultClient.Do(req)
  116. if err != nil {
  117. panic(err)
  118. }
  119. assertStatus(http.StatusOK, res.StatusCode, t)
  120. ac := buf.String()
  121. assertTrue(tc.rx.MatchString(ac), fmt.Sprintf("expected log to match '%s', got '%s'", tc.rx.String(), ac), t)
  122. }
  123. func TestForwardedFor(t *testing.T) {
  124. rx := regexp.MustCompile(`^1\.1\.1\.1:0 - - \[\d{4}-\d{2}-\d{2}\] "GET / HTTP/1\.1" 200 "http://www\.test\.com" "Go \d+\.\d+ package http"\n$`)
  125. buf := bytes.NewBuffer(nil)
  126. log.SetOutput(buf)
  127. opts := NewLogOptions(log.Printf, Ldefault)
  128. opts.DateFormat = "2006-01-02"
  129. h := LogHandler(http.HandlerFunc(
  130. func(w http.ResponseWriter, r *http.Request) {
  131. time.Sleep(100 * time.Millisecond)
  132. w.Header().Set("Content-Type", "text/plain")
  133. w.WriteHeader(200)
  134. w.Write([]byte("body"))
  135. }), opts)
  136. s := httptest.NewServer(h)
  137. defer s.Close()
  138. t.Logf("running ForwardedFor...")
  139. req, err := http.NewRequest("GET", s.URL, nil)
  140. if err != nil {
  141. panic(err)
  142. }
  143. req.Header.Set("Referer", "http://www.test.com")
  144. req.Header.Set("X-Forwarded-For", "1.1.1.1")
  145. req.Header.Set("Accept-Encoding", "gzip")
  146. res, err := http.DefaultClient.Do(req)
  147. if err != nil {
  148. panic(err)
  149. }
  150. assertStatus(http.StatusOK, res.StatusCode, t)
  151. ac := buf.String()
  152. assertTrue(rx.MatchString(ac), fmt.Sprintf("expected log to match '%s', got '%s'", rx.String(), ac), t)
  153. }
  154. func TestImmediate(t *testing.T) {
  155. buf := bytes.NewBuffer(nil)
  156. log.SetFlags(0)
  157. log.SetOutput(buf)
  158. opts := NewLogOptions(nil, Ltiny)
  159. opts.Immediate = true
  160. h := LogHandler(http.HandlerFunc(
  161. func(w http.ResponseWriter, r *http.Request) {
  162. time.Sleep(100 * time.Millisecond)
  163. w.WriteHeader(200)
  164. w.Write([]byte("body"))
  165. }), opts)
  166. s := httptest.NewServer(h)
  167. defer s.Close()
  168. res, err := http.Get(s.URL)
  169. if err != nil {
  170. panic(err)
  171. }
  172. assertStatus(http.StatusOK, res.StatusCode, t)
  173. ac := buf.String()
  174. // Since it is Immediate logging, status is still 0 and response time is less than 100ms
  175. rx := regexp.MustCompile(`GET / 0 - 0\.0\d\d s\n`)
  176. assertTrue(rx.MatchString(ac), fmt.Sprintf("expected log to match '%s', got '%s'", rx.String(), ac), t)
  177. }
  178. func TestCustom(t *testing.T) {
  179. buf := bytes.NewBuffer(nil)
  180. log.SetFlags(0)
  181. log.SetOutput(buf)
  182. opts := NewLogOptions(nil, "%s %s", "method", "custom")
  183. opts.CustomTokens["custom"] = func(w http.ResponseWriter, r *http.Request) string {
  184. return "toto"
  185. }
  186. h := LogHandler(http.HandlerFunc(
  187. func(w http.ResponseWriter, r *http.Request) {
  188. time.Sleep(100 * time.Millisecond)
  189. w.WriteHeader(200)
  190. w.Write([]byte("body"))
  191. }), opts)
  192. s := httptest.NewServer(h)
  193. defer s.Close()
  194. res, err := http.Get(s.URL)
  195. if err != nil {
  196. panic(err)
  197. }
  198. assertStatus(http.StatusOK, res.StatusCode, t)
  199. ac := buf.String()
  200. rx := regexp.MustCompile(`GET toto`)
  201. assertTrue(rx.MatchString(ac), fmt.Sprintf("expected log to match '%s', got '%s'", rx.String(), ac), t)
  202. }