MCPcopy Create free account
hub / github.com/docker/secrets-engine / ServeHTTP

Method ServeHTTP

x/ipc/hijack.go:115–165  ·  view source on GitHub ↗

ServeHTTP hijacks the underlying connection of a http request. The underlying connection can then be reused to send any data, i.e., it gives a universal duplex connection to the client. Important notes to keep this stable: - The hijacked `net.Conn` is only guaranteed to be valid while the request ha

(w http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

113// https://github.com/moby/moby/blob/e2ead4526d9416bd90502c710751839e55d739f2/daemon/server/router/container/exec.go#L118
114// https://cs.opensource.google/go/go/+/master:src/net/http/httputil/reverseproxy.go;l=750;drc=4ab1aec00799f91e96182cbbffd1de405cd52e93
115func (h *hijackHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
116 // Important: Do not write anything (e.g. headers) before the hijack!
117 hj, ok := w.(http.Hijacker)
118 if !ok {
119 http.Error(w, "hijacking connection", http.StatusInternalServerError)
120 return
121 }
122
123 conn, brw, hijackErr := hj.Hijack()
124 if errors.Is(hijackErr, http.ErrNotSupported) {
125 h.logger.Errorf("can't switch protocols using non-Hijacker ResponseWriter")
126 return
127 }
128
129 if hijackErr != nil {
130 h.logger.Errorf("Hijack failed on protocol switch: %v", hijackErr)
131 return
132 }
133
134 defer func() { _ = conn.Close() }() // Might have already been called inside the callback -> ignore double close error
135
136 done := make(chan struct{})
137 go func() {
138 defer close(done)
139
140 resp := &http.Response{
141 StatusCode: http.StatusSwitchingProtocols,
142 Proto: r.Proto,
143 Header: w.Header(),
144 }
145 resp.Header.Set("Connection", "upgrade")
146 resp.Header.Set("Upgrade", "tcp")
147 if err := resp.Write(brw); err != nil {
148 h.logger.Errorf("writing response: %v", err)
149 return
150 }
151 if err := brw.Flush(); err != nil {
152 h.logger.Errorf("flushing response: %v", err)
153 return
154 }
155
156 // The server still owns net.Conn. When this handler returns, conn gets closed.
157 // However, the callback might have to call Close() to abort/unblock any pending/blocking Read().
158 h.cb(r.Context(), conn)
159 }()
160
161 select {
162 case <-done:
163 case <-r.Context().Done():
164 }
165}
166
167func NewHijackAcceptor(logger logging.Logger, cb func(context.Context, io.ReadWriteCloser)) (string, http.Handler) {
168 return hijackPath, &hijackHandler{logger: logger, cb: cb, ackTimeout: hijackTimeout}

Callers 5

NewPluginServiceHandlerFunction · 0.80
NewVersionServiceHandlerFunction · 0.80

Calls 5

SetMethod · 0.80
ErrorfMethod · 0.65
CloseMethod · 0.65
ErrorMethod · 0.45
WriteMethod · 0.45

Tested by

no test coverage detected