mirror of
https://github.com/containers/podman.git
synced 2025-10-18 03:33:32 +08:00
Fix: Hijacking v2 endpoints to follow rfc 7230 semantics
After this patch v2 hijacking endpoints, exec/start and containers/attach follow rfc 7230 specification. Connection will only be upgraded, if client specifies upgrade headers: For tcp connections: Connection: Upgrade Upgrade: tcp For unix socket connections: Connection: Upgrade Upgrade: sock There are currently no checks if upgrade type actually matches with available protocols. Implementation just protocol that client requested Signed-off-by: Sami Korhonen <skorhone@gmail.com>
This commit is contained in:
@ -1,8 +1,12 @@
|
||||
package compat
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/v2/libpod"
|
||||
"github.com/containers/libpod/v2/libpod/define"
|
||||
@ -12,12 +16,6 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// AttachHeader is the literal header sent for upgraded/hijacked connections for
|
||||
// attach, sourced from Docker at:
|
||||
// https://raw.githubusercontent.com/moby/moby/b95fad8e51bd064be4f4e58a996924f343846c85/api/server/router/container/container_routes.go
|
||||
// Using literally to ensure compatibility with existing clients.
|
||||
const AttachHeader = "HTTP/1.1 101 UPGRADED\r\nContent-Type: application/vnd.docker.raw-stream\r\nConnection: Upgrade\r\nUpgrade: tcp\r\n\r\n"
|
||||
|
||||
func AttachContainer(w http.ResponseWriter, r *http.Request) {
|
||||
runtime := r.Context().Value("runtime").(*libpod.Runtime)
|
||||
decoder := r.Context().Value("decoder").(*schema.Decoder)
|
||||
@ -98,21 +96,11 @@ func AttachContainer(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Hijack the connection
|
||||
hijacker, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
utils.InternalServerError(w, errors.Errorf("unable to hijack connection"))
|
||||
return
|
||||
}
|
||||
|
||||
connection, buffer, err := hijacker.Hijack()
|
||||
connection, buffer, err := AttachConnection(w, r)
|
||||
if err != nil {
|
||||
utils.InternalServerError(w, errors.Wrapf(err, "error hijacking connection"))
|
||||
utils.InternalServerError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintf(connection, AttachHeader)
|
||||
|
||||
logrus.Debugf("Hijack for attach of container %s successful", ctr.ID())
|
||||
|
||||
// Perform HTTP attach.
|
||||
@ -126,3 +114,39 @@ func AttachContainer(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
logrus.Debugf("Attach for container %s completed successfully", ctr.ID())
|
||||
}
|
||||
|
||||
func AttachConnection(w http.ResponseWriter, r *http.Request) (net.Conn, *bufio.ReadWriter, error) {
|
||||
// Hijack the connection
|
||||
hijacker, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
return nil, nil, errors.Errorf("unable to hijack connection")
|
||||
}
|
||||
|
||||
connection, buffer, err := hijacker.Hijack()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "error hijacking connection")
|
||||
}
|
||||
|
||||
WriteAttachHeaders(r, connection)
|
||||
|
||||
return connection, buffer, nil
|
||||
}
|
||||
|
||||
func WriteAttachHeaders(r *http.Request, connection io.Writer) {
|
||||
// AttachHeader is the literal header sent for upgraded/hijacked connections for
|
||||
// attach, sourced from Docker at:
|
||||
// https://raw.githubusercontent.com/moby/moby/b95fad8e51bd064be4f4e58a996924f343846c85/api/server/router/container/container_routes.go
|
||||
// Using literally to ensure compatibility with existing clients.
|
||||
c := r.Header.Get("Connection")
|
||||
proto := r.Header.Get("Upgrade")
|
||||
if len(proto) == 0 || !strings.EqualFold(c, "Upgrade") {
|
||||
// OK - can't upgrade if not requested or protocol is not specified
|
||||
fmt.Fprintf(connection,
|
||||
"HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
|
||||
} else {
|
||||
// Upraded
|
||||
fmt.Fprintf(connection,
|
||||
"HTTP/1.1 101 UPGRADED\r\nContent-Type: application/vnd.docker.raw-stream\r\nConnection: Upgrade\r\nUpgrade: %s\r\n\r\n",
|
||||
proto)
|
||||
}
|
||||
}
|
||||
|
@ -173,21 +173,11 @@ func ExecStartHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Hijack the connection
|
||||
hijacker, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
utils.InternalServerError(w, errors.Errorf("unable to hijack connection"))
|
||||
return
|
||||
}
|
||||
|
||||
connection, buffer, err := hijacker.Hijack()
|
||||
connection, buffer, err := AttachConnection(w, r)
|
||||
if err != nil {
|
||||
utils.InternalServerError(w, errors.Wrapf(err, "error hijacking connection"))
|
||||
utils.InternalServerError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintf(connection, AttachHeader)
|
||||
|
||||
logrus.Debugf("Hijack for attach of container %s exec session %s successful", sessionCtr.ID(), sessionID)
|
||||
|
||||
if err := sessionCtr.ExecHTTPStartAndAttach(sessionID, connection, buffer, nil, nil, nil); err != nil {
|
||||
|
Reference in New Issue
Block a user