github.com/psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/quic/gquic-go/h2quic/request.go (about)

     1  package h2quic
     2  
     3  import (
     4  	"crypto/tls"
     5  	"errors"
     6  	"net/http"
     7  	"net/url"
     8  	"strconv"
     9  	"strings"
    10  
    11  	"golang.org/x/net/http2/hpack"
    12  )
    13  
    14  func requestFromHeaders(headers []hpack.HeaderField) (*http.Request, error) {
    15  	var path, authority, method, contentLengthStr string
    16  	httpHeaders := http.Header{}
    17  
    18  	for _, h := range headers {
    19  		switch h.Name {
    20  		case ":path":
    21  			path = h.Value
    22  		case ":method":
    23  			method = h.Value
    24  		case ":authority":
    25  			authority = h.Value
    26  		case "content-length":
    27  			contentLengthStr = h.Value
    28  		default:
    29  			if !h.IsPseudo() {
    30  				httpHeaders.Add(h.Name, h.Value)
    31  			}
    32  		}
    33  	}
    34  
    35  	// concatenate cookie headers, see https://tools.ietf.org/html/rfc6265#section-5.4
    36  	if len(httpHeaders["Cookie"]) > 0 {
    37  		httpHeaders.Set("Cookie", strings.Join(httpHeaders["Cookie"], "; "))
    38  	}
    39  
    40  	if len(path) == 0 || len(authority) == 0 || len(method) == 0 {
    41  		return nil, errors.New(":path, :authority and :method must not be empty")
    42  	}
    43  
    44  	u, err := url.ParseRequestURI(path)
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  
    49  	var contentLength int64
    50  	if len(contentLengthStr) > 0 {
    51  		contentLength, err = strconv.ParseInt(contentLengthStr, 10, 64)
    52  		if err != nil {
    53  			return nil, err
    54  		}
    55  	}
    56  
    57  	return &http.Request{
    58  		Method:        method,
    59  		URL:           u,
    60  		Proto:         "HTTP/2.0",
    61  		ProtoMajor:    2,
    62  		ProtoMinor:    0,
    63  		Header:        httpHeaders,
    64  		Body:          nil,
    65  		ContentLength: contentLength,
    66  		Host:          authority,
    67  		RequestURI:    path,
    68  		TLS:           &tls.ConnectionState{},
    69  	}, nil
    70  }
    71  
    72  func hostnameFromRequest(req *http.Request) string {
    73  	if req.URL != nil {
    74  		return req.URL.Host
    75  	}
    76  	return ""
    77  }