golang http2 client 和server 使用非TLS 模式(h2c)

研究了一下 golang 的http2 用法

這里先普及幾個概念

  • h2薄霜,基于TLS之上構(gòu)建的HTTP/2,作為ALPN的標(biāo)識符纸兔,兩個字節(jié)表示惰瓜,0x68, 0x32,即https
  • h2c汉矿,直接在TCP之上構(gòu)建的HTTP/2崎坊,缺乏安全保證,即http
    在HTTP/2 RFC文檔出現(xiàn)之前洲拇,以上版本字段需要添加上草案版本號奈揍,類似于h2-11,h2c-17

首先寫了一個服務(wù)器的代碼


import (
    "fmt"
    "html"
    "net/http"

    "golang.org/x/net/http2"
)

func main() {
    var server http.Server

    http2.VerboseLogs = true
    server.Addr = ":8080"

    http2.ConfigureServer(&server, &http2.Server{})

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "URL: %q\n", html.EscapeString(r.URL.Path))
        ShowRequestInfoHandler(w, r)
    })

    server.ListenAndServe() //不啟用 https 則默認(rèn)只支持http1.x
    //log.Fatal(server.ListenAndServeTLS("localhost.cert", "localhost.key"))
}
func ShowRequestInfoHandler(w http.ResponseWriter, r *http.Request) {

    //  fmt.Fprintf(w, "======")
    //  return

    w.Header().Set("Content-Type", "text/plain")

    fmt.Fprintf(w, "Method: %s\n", r.Method)
    fmt.Fprintf(w, "Protocol: %s\n", r.Proto)
    fmt.Fprintf(w, "Host: %s\n", r.Host)
    fmt.Fprintf(w, "RemoteAddr: %s\n", r.RemoteAddr)
    fmt.Fprintf(w, "RequestURI: %q\n", r.RequestURI)
    fmt.Fprintf(w, "URL: %#v\n", r.URL)
    fmt.Fprintf(w, "Body.ContentLength: %d (-1 means unknown)\n", r.ContentLength)
    fmt.Fprintf(w, "Close: %v (relevant for HTTP/1 only)\n", r.Close)
    fmt.Fprintf(w, "TLS: %#v\n", r.TLS)
    fmt.Fprintf(w, "\nHeaders:\n")

    r.Header.Write(w)
}

由于不想 使用https 就使用了 server.ListenAndServe(),沒想到這里有個坑赋续,等下介紹

既然服務(wù)端使用了http 非 tls 那么 客戶端就使用 非 tls 了男翰,看代碼

package main

import (
  "crypto/tls"
  "fmt"
  "io/ioutil"
  "log"
  "net"
  "net/http"

  "golang.org/x/net/http2"
)

func main() {
  url := "http://localhost:8080/"
  client(url)
}

func client(url string) {
  log.SetFlags(log.Llongfile)
  tr := &http2.Transport{ //可惜服務(wù)端 退化成了 http1.x
      AllowHTTP: true, //充許非加密的鏈接
      // TLSClientConfig: &tls.Config{
      //  InsecureSkipVerify: true,
      // },
      DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
          return net.Dial(netw, addr)
      },
  }

  httpClient := http.Client{Transport: tr}

  resp, err := httpClient.Get(url)
  if err != nil {
      log.Fatal(err)
  }
  defer resp.Body.Close()

  if resp.StatusCode != http.StatusOK {
      fmt.Println("resp StatusCode:", resp.StatusCode)
      return
  }

  body, err := ioutil.ReadAll(resp.Body)
  if err != nil {
      log.Fatal(err)
  }

  fmt.Println("resp.Body:\n", string(body))
}

由于http2 client 沒有暴露 h2c 模式的,所以就 搞了個

AllowHTTP: true, //充許非加密的鏈接

DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
            return net.Dial(netw, addr)
        },

本意是想這樣實現(xiàn)客戶端h2c

搞完了就運行服務(wù)器纽乱,執(zhí)行客戶端蛾绎,結(jié)果打印

Get http://localhost:8080/: unexpected EOF

看的云里霧里,再抓包一看

粘貼圖片.png

服務(wù)器向客戶端發(fā)了一個http1.1 的包迫淹,并且還close 了client 鏈接秘通,為什么會這樣呢

server.ListenAndServe() //不啟用 https 則默認(rèn)只支持http1.x

1.png

既然服務(wù)器只支持http1 了那么客戶端 發(fā)http2的請求,服務(wù)器當(dāng)然要close 鏈接了敛熬。

那么有沒有辦法解決呢肺稀,即服務(wù)器和客戶端都使用 h2c ,客戶端的比較好辦 AllowHTTP: true 充許非加密的鏈接 并且

DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
            return net.Dial(netw, addr)
        },

服務(wù)端考慮使用更低一層的庫http2庫實現(xiàn),主要是使用ServCon直接替換掉net/http/中的serv函數(shù)应民,例如

import (
    "fmt"
    "golang.org/x/net/http2"
    "net/http"

    "net"
    "time"
)

//net/http包默認(rèn)可以采用http2進行服務(wù)话原,在沒有進行https的服務(wù)上開啟H2夕吻,
//需要修改ListenAndServer的默認(rèn)h2服務(wù)

type serverHandler struct {
}

func (sh *serverHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    fmt.Println(req)
    w.Header().Set("server", "h2test")
    w.Write([]byte("this is a http2 test sever"))
}

func main() {
    server := &http.Server{
        Addr:         ":8080",
        Handler:      &serverHandler{},
        ReadTimeout:  5 * time.Second,
        WriteTimeout: 5 * time.Second,
    }
    //http2.Server.ServeConn()
    s2 := &http2.Server{
        IdleTimeout: 1 * time.Minute,
    }
    http2.ConfigureServer(server, s2)
    l, _ := net.Listen("tcp", ":8080")
    defer l.Close()
    fmt.Println("Start server...")
    for {
        rwc, err := l.Accept()
        if err != nil {
            fmt.Println("accept err:", err)
            continue
        }
        go s2.ServeConn(rwc, &http2.ServeConnOpts{BaseConfig: server})

    }
    //http.ListenAndServe(":8888",&serverHandler{})
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市繁仁,隨后出現(xiàn)的幾起案子涉馅,更是在濱河造成了極大的恐慌,老刑警劉巖黄虱,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稚矿,死亡現(xiàn)場離奇詭異,居然都是意外死亡捻浦,警方通過查閱死者的電腦和手機晤揣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來朱灿,“玉大人昧识,你說我怎么就攤上這事〉涟牵” “怎么了跪楞?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長侣灶。 經(jīng)常有香客問我甸祭,道長,這世上最難降的妖魔是什么炫隶? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任淋叶,我火速辦了婚禮,結(jié)果婚禮上伪阶,老公的妹妹穿的比我還像新娘煞檩。我一直安慰自己,他們只是感情好栅贴,可當(dāng)我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布斟湃。 她就那樣靜靜地躺著,像睡著了一般檐薯。 火紅的嫁衣襯著肌膚如雪凝赛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天坛缕,我揣著相機與錄音墓猎,去河邊找鬼。 笑死赚楚,一個胖子當(dāng)著我的面吹牛毙沾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播宠页,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼左胞,長吁一口氣:“原來是場噩夢啊……” “哼寇仓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起烤宙,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤遍烦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后躺枕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體服猪,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年拐云,在試婚紗的時候發(fā)現(xiàn)自己被綠了蔓姚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡慨丐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出泄私,到底是詐尸還是另有隱情房揭,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布晌端,位于F島的核電站捅暴,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏咧纠。R本人自食惡果不足惜蓬痒,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望漆羔。 院中可真熱鬧梧奢,春花似錦、人聲如沸演痒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸟顺。三九已至惦蚊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間讯嫂,已是汗流浹背蹦锋。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留欧芽,地道東北人莉掂。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像渐裸,于是被迫代替她去往敵國和親巫湘。 傳聞我的和親對象是個殘疾皇子装悲,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內(nèi)容