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 {