@marcel91200 / caddy Mirror · read-only / commits / 5ba1e06f
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 12, 04:30 UTC

encode: try to use sendfile when compression is not used (#6749)

* try to use sendfile when encode is enabled * change variable name * add comments * remove connect check since it's done in Write method

WeidiDeng committed Dec 21, 2024 at 05:37 UTC 5ba1e06fd661aac2cbaab6d4a2ef63a9eb877a46
1 file changed +43
modules/caddyhttp/encode/encode.go
+43
@@ -347,6 +347,49 @@ func (rw *responseWriter) Write(p []byte) (int, error) {
347 }
348 }
349
350 +// used to mask ReadFrom method
351 +type writerOnly struct {
352 + io.Writer
353 +}
354 +
355 +// copied from stdlib
356 +const sniffLen = 512
357 +
358 +// ReadFrom will try to use sendfile to copy from the reader to the response writer.
359 +// It's only used if the response writer implements io.ReaderFrom and the data can't be compressed.
360 +// It's based on stdlin http1.1 response writer implementation.
361 +// https://github.com/golang/go/blob/f4e3ec3dbe3b8e04a058d266adf8e048bab563f2/src/net/http/server.go#L586
362 +func (rw *responseWriter) ReadFrom(r io.Reader) (int64, error) {
363 + rf, ok := rw.ResponseWriter.(io.ReaderFrom)
364 + // sendfile can't be used anyway
365 + if !ok {
366 + // mask ReadFrom to avoid infinite recursion
367 + return io.Copy(writerOnly{rw}, r)
368 + }
369 +
370 + var ns int64
371 + // try to sniff the content type and determine if the response should be compressed
372 + if !rw.wroteHeader && rw.config.MinLength > 0 {
373 + var (
374 + err error
375 + buf [sniffLen]byte
376 + )
377 + // mask ReadFrom to let Write determine if the response should be compressed
378 + ns, err = io.CopyBuffer(writerOnly{rw}, io.LimitReader(r, sniffLen), buf[:])
379 + if err != nil || ns < sniffLen {
380 + return ns, err
381 + }
382 + }
383 +
384 + // the response will be compressed, no sendfile support
385 + if rw.w != nil {
386 + nr, err := io.Copy(rw.w, r)
387 + return nr + ns, err
388 + }
389 + nr, err := rf.ReadFrom(r)
390 + return nr + ns, err
391 +}
392 +
393 // Close writes any remaining buffered response and
394 // deallocates any active resources.
395 func (rw *responseWriter) Close() error {