go - 如何从状态为 101 切换协议(protocol)的响应中读取正文

标签 go kubernetes spdy

我连接到 Kubernetes 集群中的服务器,使用 POST 请求和 header 来升级请求。我正在使用以下功能:

func PostRequest(client *http.Client, url string, bodyData []byte) (*http.Response, error){
    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(bodyData))
    //req.Header.Set("Authorization", "Bearer " + BEARER_TOKEN)
    req.Header.Set("X-Stream-Protocol-Version", "v2.channel.k8s.io")
    req.Header.Set("X-Stream-Protocol-Version", "channel.k8s.io")
    req.Header.Set("Upgrade", "SPDY/3.1")
    req.Header.Set("Connection","upgrade")
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

    resp, err := (*client).Do(req)

    return resp, err
}

收到回复后,我试图阅读它,但当我阅读正文时它卡住了:
url2 := "https://<serveri_ip>:10250/exec/default/mypod/mycontainer?command=ls&command=/&input=1&output=1&tty=1"

resp, err := PostRequest(api.GlobalClient, url2, []byte(""))
fmt.Println(r.Status)
fmt.Println(r.Header)
bodyBytes, err := ioutil.ReadAll(r.Body) // -> it stuck here
fmt.Println(string(bodyBytes))  

我想它试图打开 websocket,所以我尝试使用 gorilla websocket library像那样:
u := url.URL{Scheme: "ws", Host: "<node_ip>:10250", Path: "/exec/default/mypod/mycontainer?command=ls&command=/&input=1&output=1&tty=1"}

interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)

c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
if err != nil {
  log.Fatal("dial:", err)
}
defer c.Close()

但是它打印了一个错误:

2020/04/04 20:51:25 dial:websocket: bad handshake



我做错了什么?
如何从状态“切换协议(protocol)”中读取响应正文

最佳答案

我设法用 Kubernetes go-client 做到了图书馆:

package main

import (
    "crypto/tls"
    "fmt"
    "net/http"
    "net/url"
    "os"
    "time"

    restclient "k8s.io/client-go/rest"
    "k8s.io/client-go/tools/remotecommand"
)


func main(){

    /*req.Header.Add("X-Stream-Protocol-Version", "v4.channel.k8s.io")
    req.Header.Add("X-Stream-Protocol-Version", "v3.channel.k8s.io")
    req.Header.Add("X-Stream-Protocol-Version", "v2.channel.k8s.io")
    req.Header.Add("X-Stream-Protocol-Version", "channel.k8s.io")
    req.Header.Add("Connection", "upgrade")
    req.Header.Add("Upgrade", "SPDY/3.1")*/
    //url2 := "https://123.123.123.123:10250/exec/default/my-pod/nginx?command=ls&command=/&input=1&output=1&tty=1"
    tr := &http.Transport{
        MaxIdleConns:       10,
        IdleConnTimeout:    30 * time.Second,
        DisableCompression: true,
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    }

    config := &restclient.Config{
        Host:                "https://123.123.123.123:10250",
        APIPath:             "/exec/default/my-pod/nginx",
        TLSClientConfig:     restclient.TLSClientConfig{
            Insecure: true,
        },
        Transport:           tr,
    }

    url3 := &url.URL{
        Scheme:     "https",
        Opaque:     "",
        User:       nil,
        Host:       "123.123.123.123:10250",
        Path:       "/exec/default/my-pod/nginx",
        RawPath:    "",
        RawQuery:   "command=ls&command=/&input=1&output=1&tty=1",
    }
    exec, err := remotecommand.NewSPDYExecutor(config, "POST", url3)
    if err != nil {
        fmt.Println(err)
    }

    // Thanks for this blog post https://www.henryxieblogs.com/2019/05/
    err = exec.Stream(remotecommand.StreamOptions{
        Stdin:  os.Stdin,
        Stdout: os.Stdout,
        Stderr: os.Stderr,
        Tty:true,
    })

    fmt.Println(err)
}

关于go - 如何从状态为 101 切换协议(protocol)的响应中读取正文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61033553/

相关文章:

go - 使用路径式 amazon aws sdk go

kubernetes - 没有可用的卷区域,无法安装Jupyterhub集线器Pod

kubernetes - 一个或多个容器没有资源限制-VS Code Kubernetes工具中的警告

java - 从 Netty 5 中的多路复用 channel 传送

seo - 共享主机上的 SPDY 和 SEO 语义

go - 在具有基础字段的任何结构数组上调用方法

golang,使用结构作为函数的参数

kubernetes - Kubernetes CPU 限制是如何实现的?

javascript - Express.js 的 http2 协议(protocol)的最佳选择

go - 从函数返回数据