Skip to content

Commit

Permalink
Merge 95b44c7 into 1439b7d
Browse files Browse the repository at this point in the history
  • Loading branch information
k1LoW committed Jun 14, 2024
2 parents 1439b7d + 95b44c7 commit 783ecd1
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 29 deletions.
7 changes: 0 additions & 7 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
run:
go: 1.21
modules-download-mode: mod
linters:
fast: false
linters-settings:
staticcheck:
go: 1.16
issues:
exclude:
- SA3000
18 changes: 18 additions & 0 deletions copybuf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package rc

import "sync"

// Copy from net/http/server.go
const copyBufPoolSize = 32 * 1024

var copyBufPool = sync.Pool{New: func() any { return new([copyBufPoolSize]byte) }}

func getCopyBuf() []byte { //nostyle:getters
return copyBufPool.Get().(*[copyBufPoolSize]byte)[:]
}
func putCopyBuf(b []byte) {
if len(b) != copyBufPoolSize {
panic("trying to put back buffer of the wrong size in the copyBufPool") //nostyle:dontpanic
}
copyBufPool.Put((*[copyBufPoolSize]byte)(b))
}
48 changes: 26 additions & 22 deletions rc.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,27 +131,31 @@ func (m *cacheMw) Handler(next http.Handler) http.Handler {
}
}
w.WriteHeader(res.StatusCode)
body, err := io.ReadAll(res.Body)
if err != nil {
m.logger.Error("failed to read response body", slog.String("error", err.Error()), slog.String("host", preq.Host), slog.String("method", preq.Method), slog.String("url", preq.URL.String()), slog.Any("headers", m.maskHeader(preq.Header)), slog.Int("status", res.StatusCode), slog.Any("response_headers", m.maskHeader(res.Header)))
} else {
if _, err := w.Write(body); err != nil {
// Error as debug
// - os.ErrDeadlineExceeded: The request context has been canceled or has expired.
// - "client disconnected": The client disconnected. (net/http.http2errClientDisconnected)
// - "http2: stream closed": The client disconnected. (net/http.http2errStreamClosed)
// - syscall.ECONNRESET: The client disconnected. ("connection reset by peer")
// - syscall.EPIPE: The client disconnected. ("broken pipe")
// - http.ErrBodyNotAllowed: The request method does not allow a body.
switch {
case errors.Is(err, os.ErrDeadlineExceeded) || errors.Is(err, syscall.ECONNRESET) || errors.Is(err, syscall.EPIPE) || contains([]string{"client disconnected", "http2: stream closed"}, err.Error()):
m.logger.Debug("failed to write response body", slog.String("error", err.Error()), slog.String("host", preq.Host), slog.String("method", preq.Method), slog.String("url", preq.URL.String()), slog.Any("headers", m.maskHeader(preq.Header)), slog.Int("status", res.StatusCode), slog.Any("response_headers", m.maskHeader(res.Header)))
case errors.Is(err, http.ErrBodyNotAllowed):
// It is desirable that there should be no content body in the response, but the proxy server cannot handle it, so it is used as a debug log.
m.logger.Debug("failed to write response body", slog.String("error", err.Error()), slog.String("host", preq.Host), slog.String("method", preq.Method), slog.String("url", preq.URL.String()), slog.Any("headers", m.maskHeader(preq.Header)), slog.Int("status", res.StatusCode), slog.Any("response_headers", m.maskHeader(res.Header)))
default:
m.logger.Error("failed to write response body", slog.String("error", err.Error()), slog.String("host", preq.Host), slog.String("method", preq.Method), slog.String("url", preq.URL.String()), slog.Any("headers", m.maskHeader(preq.Header)), slog.Int("status", res.StatusCode), slog.Any("response_headers", m.maskHeader(res.Header)))
}

ww := w.(io.Writer)
b := new(bytes.Buffer)
if !cacheUsed {
// If the cache is not used, duplicate the response body for caching.
ww = io.MultiWriter(ww, b)
}
buf := getCopyBuf()
defer putCopyBuf(buf)
if _, err := io.CopyBuffer(ww, res.Body, buf); err != nil {
// Error as debug
// - os.ErrDeadlineExceeded: The request context has been canceled or has expired.
// - "client disconnected": The client disconnected. (net/http.http2errClientDisconnected)
// - "http2: stream closed": The client disconnected. (net/http.http2errStreamClosed)
// - syscall.ECONNRESET: The client disconnected. ("connection reset by peer")
// - syscall.EPIPE: The client disconnected. ("broken pipe")
// - http.ErrBodyNotAllowed: The request method does not allow a body.
switch {
case errors.Is(err, os.ErrDeadlineExceeded) || errors.Is(err, syscall.ECONNRESET) || errors.Is(err, syscall.EPIPE) || contains([]string{"client disconnected", "http2: stream closed"}, err.Error()):
m.logger.Debug("failed to write response body", slog.String("error", err.Error()), slog.String("host", preq.Host), slog.String("method", preq.Method), slog.String("url", preq.URL.String()), slog.Any("headers", m.maskHeader(preq.Header)), slog.Int("status", res.StatusCode), slog.Any("response_headers", m.maskHeader(res.Header)))
case errors.Is(err, http.ErrBodyNotAllowed):
// It is desirable that there should be no content body in the response, but the proxy server cannot handle it, so it is used as a debug log.
m.logger.Debug("failed to write response body", slog.String("error", err.Error()), slog.String("host", preq.Host), slog.String("method", preq.Method), slog.String("url", preq.URL.String()), slog.Any("headers", m.maskHeader(preq.Header)), slog.Int("status", res.StatusCode), slog.Any("response_headers", m.maskHeader(res.Header)))
default:
m.logger.Error("failed to write response body", slog.String("error", err.Error()), slog.String("host", preq.Host), slog.String("method", preq.Method), slog.String("url", preq.URL.String()), slog.Any("headers", m.maskHeader(preq.Header)), slog.Int("status", res.StatusCode), slog.Any("response_headers", m.maskHeader(res.Header)))
}
}
if err := res.Body.Close(); err != nil {
Expand All @@ -168,7 +172,7 @@ func (m *cacheMw) Handler(next http.Handler) http.Handler {
return
}
// Restore response body
res.Body = io.NopCloser(bytes.NewReader(body))
res.Body = io.NopCloser(b)

// Store response as cache
if err := m.cacher.Store(preq, res, expires); err != nil {
Expand Down

0 comments on commit 783ecd1

Please sign in to comment.