github.com/endocode/docker@v1.4.2-0.20160113120958-46eb4700391e/pkg/authorization/response.go (about) 1 package authorization 2 3 import ( 4 "bufio" 5 "bytes" 6 "encoding/json" 7 "fmt" 8 "net" 9 "net/http" 10 ) 11 12 // ResponseModifier allows authorization plugins to read and modify the content of the http.response 13 type ResponseModifier interface { 14 http.ResponseWriter 15 16 // RawBody returns the current http content 17 RawBody() []byte 18 19 // RawHeaders returns the current content of the http headers 20 RawHeaders() ([]byte, error) 21 22 // StatusCode returns the current status code 23 StatusCode() int 24 25 // OverrideBody replace the body of the HTTP reply 26 OverrideBody(b []byte) 27 28 // OverrideHeader replace the headers of the HTTP reply 29 OverrideHeader(b []byte) error 30 31 // OverrideStatusCode replaces the status code of the HTTP reply 32 OverrideStatusCode(statusCode int) 33 34 // Flush flushes all data to the HTTP response 35 Flush() error 36 } 37 38 // NewResponseModifier creates a wrapper to an http.ResponseWriter to allow inspecting and modifying the content 39 func NewResponseModifier(rw http.ResponseWriter) ResponseModifier { 40 return &responseModifier{rw: rw, header: make(http.Header)} 41 } 42 43 // responseModifier is used as an adapter to http.ResponseWriter in order to manipulate and explore 44 // the http request/response from docker daemon 45 type responseModifier struct { 46 // The original response writer 47 rw http.ResponseWriter 48 status int 49 // body holds the response body 50 body []byte 51 // header holds the response header 52 header http.Header 53 // statusCode holds the response status code 54 statusCode int 55 } 56 57 // WriterHeader stores the http status code 58 func (rm *responseModifier) WriteHeader(s int) { 59 rm.statusCode = s 60 } 61 62 // Header returns the internal http header 63 func (rm *responseModifier) Header() http.Header { 64 return rm.header 65 } 66 67 // Header returns the internal http header 68 func (rm *responseModifier) StatusCode() int { 69 return rm.statusCode 70 } 71 72 // Override replace the body of the HTTP reply 73 func (rm *responseModifier) OverrideBody(b []byte) { 74 rm.body = b 75 } 76 77 func (rm *responseModifier) OverrideStatusCode(statusCode int) { 78 rm.statusCode = statusCode 79 } 80 81 // Override replace the headers of the HTTP reply 82 func (rm *responseModifier) OverrideHeader(b []byte) error { 83 header := http.Header{} 84 if err := json.Unmarshal(b, &header); err != nil { 85 return err 86 } 87 rm.header = header 88 return nil 89 } 90 91 // Write stores the byte array inside content 92 func (rm *responseModifier) Write(b []byte) (int, error) { 93 rm.body = append(rm.body, b...) 94 return len(b), nil 95 } 96 97 // Body returns the response body 98 func (rm *responseModifier) RawBody() []byte { 99 return rm.body 100 } 101 102 func (rm *responseModifier) RawHeaders() ([]byte, error) { 103 var b bytes.Buffer 104 if err := rm.header.Write(&b); err != nil { 105 return nil, err 106 } 107 return b.Bytes(), nil 108 } 109 110 // Hijack returns the internal connection of the wrapped http.ResponseWriter 111 func (rm *responseModifier) Hijack() (net.Conn, *bufio.ReadWriter, error) { 112 hijacker, ok := rm.rw.(http.Hijacker) 113 if !ok { 114 return nil, nil, fmt.Errorf("Internal reponse writer doesn't support the Hijacker interface") 115 } 116 return hijacker.Hijack() 117 } 118 119 // Flush flushes all data to the HTTP response 120 func (rm *responseModifier) Flush() error { 121 // Copy the status code 122 if rm.statusCode > 0 { 123 rm.rw.WriteHeader(rm.statusCode) 124 } 125 126 // Copy the header 127 for k, vv := range rm.header { 128 for _, v := range vv { 129 rm.rw.Header().Add(k, v) 130 } 131 } 132 133 // Write body 134 _, err := rm.rw.Write(rm.body) 135 return err 136 }