How to read HTTP / 2 push frames from net / http request

I am trying to write a Go client to test our http / 2 infrastructure. I would like to make an http request https://mydomain.tld/somePageand expect to receive an html response along with several advanced resources. I would like these clicks to be successful and they will not work if they are not.

It’s not clear to me if any part of the standard library provides this functionality that I need.

I can see the answer and check the protocol version for detecting http2.

I can see the headers Linkin the answers from sites like https://http2-push.appspot.com/ that send push, but I don’t quite understand the relationship between the Link headers and the actual Push Promise frames. You can get link headers via http 1.1, so I'm not sure if one guarantees that a click will happen.

The http2 package has a lower level Framerthat I can use to check for raw frames, but to be honest, I have no idea how to install it and give it the initial request.

Is there any example of how the go client can verify the correct configuration of http2 redirected resources?

+6
source share
2 answers

Framer golang.org/x/net/http2 , , http.Client. , . .

, PUSH_PROMISE. , Go Push. . ( stdlib).

, - . , - , .

package main

import (
    "bytes"
    "crypto/tls"
    "io"
    "io/ioutil"
    "log"
    "net"
    "net/http"
    "os"

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

func main() {
    buf := &bytes.Buffer{}
    transport := &http2.Transport{DialTLS: dialT(buf)}
    client := &http.Client{Transport: transport}

    res, err := client.Get("https://http2-push.appspot.com/")
    if err != nil {
            log.Fatal(err)
    }

    res.Body.Close()
    res.Write(os.Stdout)

    framer := http2.NewFramer(ioutil.Discard, buf)
    for {
            f, err := framer.ReadFrame()
            if err == io.EOF || err == io.ErrUnexpectedEOF {
                    break
            }
            switch err.(type) {
            case nil:
                    log.Println(f)
            case http2.ConnectionError:
                    // Ignore. There will be many errors of type "PROTOCOL_ERROR, DATA
                    // frame with stream ID 0". Presumably we are abusing the framer.
            default:
                    log.Println(err, framer.ErrorDetail())
            }
    }
}

// dialT returns a connection that writes everything that is read to w.
func dialT(w io.Writer) func(network, addr string, cfg *tls.Config) (net.Conn, error) {
    return func(network, addr string, cfg *tls.Config) (net.Conn, error) {
            conn, err := tls.Dial(network, addr, cfg)
            return &tConn{conn, w}, err
    }
}

type tConn struct {
    net.Conn
    T io.Writer // receives everything that is read from Conn
}

func (w *tConn) Read(b []byte) (n int, err error) {
    n, err = w.Conn.Read(b)
    w.T.Write(b)
    return
}
+3

A patch .

"http2: , PUSH_PROMISE "

( github "", , , .)

0

Source: https://habr.com/ru/post/1017085/


All Articles