loghandler_test.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package handler
  2. import (
  3. "bytes"
  4. "io"
  5. "log"
  6. "net/http"
  7. "net/http/httptest"
  8. "testing"
  9. "time"
  10. "github.com/stretchr/testify/assert"
  11. "github.com/zeromicro/go-zero/rest/internal"
  12. "github.com/zeromicro/go-zero/rest/internal/response"
  13. )
  14. func init() {
  15. log.SetOutput(io.Discard)
  16. }
  17. func TestLogHandler(t *testing.T) {
  18. handlers := []func(handler http.Handler) http.Handler{
  19. LogHandler,
  20. DetailedLogHandler,
  21. }
  22. for _, logHandler := range handlers {
  23. req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
  24. handler := logHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  25. r.Context().Value(internal.LogContext).(*internal.LogCollector).Append("anything")
  26. w.Header().Set("X-Test", "test")
  27. w.WriteHeader(http.StatusServiceUnavailable)
  28. _, err := w.Write([]byte("content"))
  29. assert.Nil(t, err)
  30. flusher, ok := w.(http.Flusher)
  31. assert.True(t, ok)
  32. flusher.Flush()
  33. }))
  34. resp := httptest.NewRecorder()
  35. handler.ServeHTTP(resp, req)
  36. assert.Equal(t, http.StatusServiceUnavailable, resp.Code)
  37. assert.Equal(t, "test", resp.Header().Get("X-Test"))
  38. assert.Equal(t, "content", resp.Body.String())
  39. }
  40. }
  41. func TestLogHandlerVeryLong(t *testing.T) {
  42. var buf bytes.Buffer
  43. for i := 0; i < limitBodyBytes<<1; i++ {
  44. buf.WriteByte('a')
  45. }
  46. req := httptest.NewRequest(http.MethodPost, "http://localhost", &buf)
  47. handler := LogHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  48. r.Context().Value(internal.LogContext).(*internal.LogCollector).Append("anything")
  49. _, _ = io.Copy(io.Discard, r.Body)
  50. w.Header().Set("X-Test", "test")
  51. w.WriteHeader(http.StatusServiceUnavailable)
  52. _, err := w.Write([]byte("content"))
  53. assert.Nil(t, err)
  54. flusher, ok := w.(http.Flusher)
  55. assert.True(t, ok)
  56. flusher.Flush()
  57. }))
  58. resp := httptest.NewRecorder()
  59. handler.ServeHTTP(resp, req)
  60. assert.Equal(t, http.StatusServiceUnavailable, resp.Code)
  61. assert.Equal(t, "test", resp.Header().Get("X-Test"))
  62. assert.Equal(t, "content", resp.Body.String())
  63. }
  64. func TestLogHandlerSlow(t *testing.T) {
  65. handlers := []func(handler http.Handler) http.Handler{
  66. LogHandler,
  67. DetailedLogHandler,
  68. }
  69. for _, logHandler := range handlers {
  70. req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
  71. handler := logHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  72. time.Sleep(defaultSlowThreshold + time.Millisecond*50)
  73. }))
  74. resp := httptest.NewRecorder()
  75. handler.ServeHTTP(resp, req)
  76. assert.Equal(t, http.StatusOK, resp.Code)
  77. }
  78. }
  79. func TestDetailedLogHandler_Hijack(t *testing.T) {
  80. resp := httptest.NewRecorder()
  81. writer := &detailLoggedResponseWriter{
  82. writer: &response.WithCodeResponseWriter{
  83. Writer: resp,
  84. },
  85. }
  86. assert.NotPanics(t, func() {
  87. _, _, _ = writer.Hijack()
  88. })
  89. writer = &detailLoggedResponseWriter{
  90. writer: &response.WithCodeResponseWriter{
  91. Writer: mockedHijackable{resp},
  92. },
  93. }
  94. assert.NotPanics(t, func() {
  95. _, _, _ = writer.Hijack()
  96. })
  97. }
  98. func TestSetSlowThreshold(t *testing.T) {
  99. assert.Equal(t, defaultSlowThreshold, slowThreshold.Load())
  100. SetSlowThreshold(time.Second)
  101. assert.Equal(t, time.Second, slowThreshold.Load())
  102. }
  103. func TestWrapMethodWithColor(t *testing.T) {
  104. // no tty
  105. assert.Equal(t, http.MethodGet, wrapMethod(http.MethodGet))
  106. assert.Equal(t, http.MethodPost, wrapMethod(http.MethodPost))
  107. assert.Equal(t, http.MethodPut, wrapMethod(http.MethodPut))
  108. assert.Equal(t, http.MethodDelete, wrapMethod(http.MethodDelete))
  109. assert.Equal(t, http.MethodPatch, wrapMethod(http.MethodPatch))
  110. assert.Equal(t, http.MethodHead, wrapMethod(http.MethodHead))
  111. assert.Equal(t, http.MethodOptions, wrapMethod(http.MethodOptions))
  112. assert.Equal(t, http.MethodConnect, wrapMethod(http.MethodConnect))
  113. assert.Equal(t, http.MethodTrace, wrapMethod(http.MethodTrace))
  114. }
  115. func TestWrapStatusCodeWithColor(t *testing.T) {
  116. // no tty
  117. assert.Equal(t, "200", wrapStatusCode(http.StatusOK))
  118. assert.Equal(t, "302", wrapStatusCode(http.StatusFound))
  119. assert.Equal(t, "404", wrapStatusCode(http.StatusNotFound))
  120. assert.Equal(t, "500", wrapStatusCode(http.StatusInternalServerError))
  121. assert.Equal(t, "503", wrapStatusCode(http.StatusServiceUnavailable))
  122. }
  123. func BenchmarkLogHandler(b *testing.B) {
  124. b.ReportAllocs()
  125. req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
  126. handler := LogHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  127. w.WriteHeader(http.StatusOK)
  128. }))
  129. for i := 0; i < b.N; i++ {
  130. resp := httptest.NewRecorder()
  131. handler.ServeHTTP(resp, req)
  132. }
  133. }