loghandler_test.go 4.4 KB

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