diff options
author | Garry Filakhtov <[email protected]> | 2019-11-23 22:54:46 +1100 |
---|---|---|
committer | Garry Filakhtov <[email protected]> | 2019-11-23 23:32:44 +1100 |
commit | 8f93aa61da6e66cbd13de96ef53e476556d391a7 (patch) | |
tree | d90152357098325521ab4e93f59f98cc151d5df2 /service/http/response.go | |
parent | b81f2b121eb3a49372662d0bc9c19c53366f33fc (diff) |
Provide support for HTTP/2 trailers
Neither PHP nor PSR-7 do not natively support HTTP trailers. Golang
provides support and this commit enables trailers emulation. When PHP
sends a "Trailer" header in response, supplying a comma separated list
of headers they will be converted by RoadRunner to HTTP/2 trailers.
Diffstat (limited to 'service/http/response.go')
-rw-r--r-- | service/http/response.go | 58 |
1 files changed, 49 insertions, 9 deletions
diff --git a/service/http/response.go b/service/http/response.go index 8bd770ec..8dda87c7 100644 --- a/service/http/response.go +++ b/service/http/response.go @@ -2,9 +2,11 @@ package http import ( "encoding/json" - "github.com/spiral/roadrunner" "io" "net/http" + "regexp" + + "github.com/spiral/roadrunner" ) // Response handles PSR7 response logic. @@ -31,16 +33,16 @@ func NewResponse(p *roadrunner.Payload) (*Response, error) { // Write writes response headers, status and body into ResponseWriter. func (r *Response) Write(w http.ResponseWriter) error { + p, h := handlePushHeaders(r.Headers) + if pusher, ok := w.(http.Pusher); ok { + for _, v := range p { + pusher.Push(v, nil) + } + } + + h = handleTrailers(h) for n, h := range r.Headers { for _, v := range h { - if n == "http2-push" { - if pusher, ok := w.(http.Pusher); ok { - pusher.Push(v, nil) - } - - continue - } - w.Header().Add(n, v) } } @@ -59,3 +61,41 @@ func (r *Response) Write(w http.ResponseWriter) error { return nil } + +func handlePushHeaders(h map[string][]string) ([]string, map[string][]string) { + var p []string + pushHeader, ok := h["http2-push"] + if !ok { + return p, h + } + + for _, v := range pushHeader { + p = append(p, v) + } + + delete(h, "http2-push") + + return p, h +} + +func handleTrailers(h map[string][]string) map[string][]string { + trailers, ok := h["trailer"] + if !ok { + return h + } + + zp := regexp.MustCompile(` *, *`) + for _, tr := range trailers { + for _, n := range zp.Split(tr, -1) { + if v, ok := h[n]; ok { + h["Trailer:"+n] = v + + delete(h, n) + } + } + } + + delete(h, "trailer") + + return h +} |