...
1 package handlers
2
3 import (
4 "context"
5 "errors"
6 "io"
7 "net/http"
8
9 dcontext "github.com/docker/distribution/context"
10 )
11
12
13
14 func closeResources(handler http.Handler, closers ...io.Closer) http.Handler {
15 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
16 for _, closer := range closers {
17 defer closer.Close()
18 }
19 handler.ServeHTTP(w, r)
20 })
21 }
22
23
24
25
26
27
28 func copyFullPayload(ctx context.Context, responseWriter http.ResponseWriter, r *http.Request, destWriter io.Writer, limit int64, action string) error {
29
30 clientClosed := r.Context().Done()
31 var body = r.Body
32 if limit > 0 {
33 body = http.MaxBytesReader(responseWriter, body, limit)
34 }
35
36
37 copied, err := io.Copy(destWriter, body)
38 if clientClosed != nil && (err != nil || (r.ContentLength > 0 && copied < r.ContentLength)) {
39
40
41
42 select {
43 case <-clientClosed:
44
45
46
47
48 responseWriter.WriteHeader(499)
49
50 dcontext.GetLoggerWithFields(ctx, map[interface{}]interface{}{
51 "error": err,
52 "copied": copied,
53 "contentLength": r.ContentLength,
54 }, "error", "copied", "contentLength").Error("client disconnected during " + action)
55 return errors.New("client disconnected")
56 default:
57 }
58 }
59
60 if err != nil {
61 dcontext.GetLogger(ctx).Errorf("unknown error reading request payload: %v", err)
62 return err
63 }
64
65 return nil
66 }
67
View as plain text