caddy/caddyhttp/push/handler.go

71 lines
1.5 KiB
Go
Raw Normal View History

package push
import (
"net/http"
"strings"
"github.com/mholt/caddy/caddyhttp/httpserver"
)
func (h Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
pusher, hasPusher := w.(http.Pusher)
// No Pusher, no cry
if !hasPusher {
return h.Next.ServeHTTP(w, r)
}
// This is request for the pushed resource - it should not be recursive
if _, exists := r.Header[pushHeader]; exists {
return h.Next.ServeHTTP(w, r)
}
// Serve file first
code, err := h.Next.ServeHTTP(w, r)
if flusher, ok := w.(http.Flusher); ok {
flusher.Flush()
}
outer:
for _, rule := range h.Rules {
if httpserver.Path(r.URL.Path).Matches(rule.Path) {
for _, resource := range rule.Resources {
pushErr := pusher.Push(resource.Path, &http.PushOptions{
Method: resource.Method,
Header: resource.Header,
})
if pushErr != nil {
// If we cannot push (either not supported or concurrent streams are full - break)
break outer
}
}
}
}
if links, exists := w.Header()["Link"]; exists {
h.pushLinks(pusher, links)
}
return code, err
}
func (h Middleware) pushLinks(pusher http.Pusher, links []string) {
outer:
for _, link := range links {
parts := strings.Split(link, ";")
if link == "" || strings.HasSuffix(link, "nopush") {
continue
}
target := strings.TrimSuffix(strings.TrimPrefix(parts[0], "<"), ">")
err := pusher.Push(target, &http.PushOptions{Method: http.MethodGet})
if err != nil {
break outer
}
}
}