mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-07 19:38:49 +03:00
71 lines
1.5 KiB
Go
71 lines
1.5 KiB
Go
|
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
|
||
|
}
|
||
|
}
|
||
|
}
|