Repository: kubernetes/kubernetes
File: staging/src/k8s.io/apiserver/pkg/util/proxy/streamtranslator_test.go (Go)

Code before:
		})
	}
}

// streamContext encapsulates the structures necessary to communicate through
// a SPDY connection, including the Reader/Writer streams.
type streamContext struct {
	conn         io.Closer
	stdinStream  io.ReadCloser
	stdoutStream io.WriteCloser
	stderrStream io.WriteCloser
	resizeStream io.ReadCloser
	resizeChan   chan remotecommand.TerminalSize
	writeStatus  func(status *apierrors.StatusError) error
}

type streamAndReply struct {
	httpstream.Stream
	replySent <-chan struct{}
}

// CreateSPDYServerStreams upgrades the passed HTTP request to a SPDY bi-directional streaming
// connection with remote command streams defined in passed options. Returns a streamContext
// structure containing the Reader/Writer streams to communicate through the SDPY connection.
// Returns an error if unable to upgrade the HTTP connection to a SPDY connection.
func createSPDYServerStreams(w http.ResponseWriter, req *http.Request, opts Options) (*streamContext, error) {
	_, err := httpstream.Handshake(req, w, []string{rcconstants.StreamProtocolV4Name})
	if err != nil {
		fmt.Printf("\n[DEBUG] Handshake Failed. Analyzing the Request:\n")

		// 1. Validate the Request Line (Method/URL/Proto)
		// If these are empty or weird, the server read garbage bytes as the request line.
		fmt.Printf("Method: '%s'\n", req.Method)
		fmt.Printf("URL:    '%s'\n", req.URL.String())
		fmt.Printf("Proto:  '%s'\n", req.Proto)

		// 2. Check ContentLength
		// An upgrade request should usually have 0 content length.
		// If this is > 0, the server might be reading a previous request's BODY as this request.
		fmt.Printf("ContentLength: %d\n", req.ContentLength)

		// 3. Peek at the Body
		// If the connection is desynchronized, the "real" headers might be stuck in the body buffer.
		// We try to read 50 bytes to see if there is text hiding there.
		if req.Body != nil {
			peekBuf := make([]byte, 50)
			n, _ := req.Body.Read(peekBuf)
			if n > 0 {
				fmt.Printf("Body Peek (first %d bytes): %q\n", n, peekBuf[:n])
			} else {
				fmt.Println("Body Peek: [Empty]")

Review comment (suggestion):
pass in `t *testing.T` and use t.Log instead of fmt.Print, then lgtm

Code after:
		})
	}
}

// streamContext encapsulates the structures necessary to communicate through
// a SPDY connection, including the Reader/Writer streams.
type streamContext struct {
	conn         io.Closer
	stdinStream  io.ReadCloser
	stdoutStream io.WriteCloser
	stderrStream io.WriteCloser
	resizeStream io.ReadCloser
	resizeChan   chan remotecommand.TerminalSize
	writeStatus  func(status *apierrors.StatusError) error
}

type streamAndReply struct {
	httpstream.Stream
	replySent <-chan struct{}
}

// CreateSPDYServerStreams upgrades the passed HTTP request to a SPDY bi-directional streaming
// connection with remote command streams defined in passed options. Returns a streamContext
// structure containing the Reader/Writer streams to communicate through the SDPY connection.
// Returns an error if unable to upgrade the HTTP connection to a SPDY connection.
func createSPDYServerStreams(t *testing.T, w http.ResponseWriter, req *http.Request, opts Options) (*streamContext, error) {
	_, err := httpstream.Handshake(req, w, []string{rcconstants.StreamProtocolV4Name})
	if err != nil {
		t.Log("------------------- [DEBUG] HANDSHAKE FAILED -------------------")
		t.Logf("Method:        %s", req.Method)
		t.Logf("URL:           %s", req.URL.String())
		t.Logf("Proto:         %s", req.Proto)
		t.Logf("Header Count:  %d", len(req.Header))
		t.Logf("ContentLength: %d", req.ContentLength) // Should be zero for upgrade request
		// Dump the request in its entirety.
		dump, err := httputil.DumpRequest(req, true)
		if err != nil {
			t.Logf("DumpRequest failed: %v", err)
		} else {
			t.Logf("Full HTTP Request Dump:\n%s", dump)
		}

		return nil, err
	}

	upgrader := spdy.NewResponseUpgrader()
	streamCh := make(chan streamAndReply)
	conn := upgrader.UpgradeResponse(w, req, func(stream httpstream.Stream, replySent <-chan struct{}) error {
		streamCh <- streamAndReply{Stream: stream, replySent: replySent}
		return nil
	})