summaryrefslogtreecommitdiff
path: root/service/http/response.go
diff options
context:
space:
mode:
authorGarry Filakhtov <[email protected]>2019-11-23 22:54:46 +1100
committerGarry Filakhtov <[email protected]>2019-11-23 23:32:44 +1100
commit8f93aa61da6e66cbd13de96ef53e476556d391a7 (patch)
treed90152357098325521ab4e93f59f98cc151d5df2 /service/http/response.go
parentb81f2b121eb3a49372662d0bc9c19c53366f33fc (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.go58
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
+}