mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
6cea1f239d
* push: Implement HTTP/2 server push (close #3551) * push: Abstract header ops by embedding into new struct type This will allow us to add more fields to customize headers in push-specific ways in the future. * push: Ensure Link resources are pushed before response is written * Change header name from X-Caddy-Push to Caddy-Push
99 lines
3 KiB
Go
99 lines
3 KiB
Go
// Copyright 2015 Matthew Holt and The Caddy Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package push
|
|
|
|
import (
|
|
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
|
|
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
|
|
"github.com/caddyserver/caddy/v2/modules/caddyhttp/headers"
|
|
)
|
|
|
|
func init() {
|
|
httpcaddyfile.RegisterHandlerDirective("push", parseCaddyfile)
|
|
}
|
|
|
|
// parseCaddyfile sets up the push handler. Syntax:
|
|
//
|
|
// push [<matcher>] [<resource>] {
|
|
// [GET|HEAD] <resource>
|
|
// headers {
|
|
// [+]<field> [<value|regexp> [<replacement>]]
|
|
// -<field>
|
|
// }
|
|
// }
|
|
//
|
|
// A single resource can be specified inline without opening a
|
|
// block for the most common/simple case. Or, a block can be
|
|
// opened and multiple resources can be specified, one per
|
|
// line, optionally preceded by the method. The headers
|
|
// subdirective can be used to customize the headers that
|
|
// are set on each (synthetic) push request, using the same
|
|
// syntax as the 'header' directive for request headers.
|
|
// Placeholders are accepted in resource and header field
|
|
// name and value and replacement tokens.
|
|
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
|
|
handler := new(Handler)
|
|
|
|
for h.Next() {
|
|
if h.NextArg() {
|
|
handler.Resources = append(handler.Resources, Resource{Target: h.Val()})
|
|
}
|
|
|
|
// optional block
|
|
for outerNesting := h.Nesting(); h.NextBlock(outerNesting); {
|
|
switch h.Val() {
|
|
case "headers":
|
|
if h.NextArg() {
|
|
return nil, h.ArgErr()
|
|
}
|
|
for innerNesting := h.Nesting(); h.NextBlock(innerNesting); {
|
|
// include current token, which we treat as an argument here
|
|
args := []string{h.Val()}
|
|
args = append(args, h.RemainingArgs()...)
|
|
|
|
if handler.Headers == nil {
|
|
handler.Headers = new(HeaderConfig)
|
|
}
|
|
switch len(args) {
|
|
case 1:
|
|
headers.CaddyfileHeaderOp(&handler.Headers.HeaderOps, args[0], "", "")
|
|
case 2:
|
|
headers.CaddyfileHeaderOp(&handler.Headers.HeaderOps, args[0], args[1], "")
|
|
case 3:
|
|
headers.CaddyfileHeaderOp(&handler.Headers.HeaderOps, args[0], args[1], args[2])
|
|
default:
|
|
return nil, h.ArgErr()
|
|
}
|
|
}
|
|
|
|
case "GET", "HEAD":
|
|
method := h.Val()
|
|
if !h.NextArg() {
|
|
return nil, h.ArgErr()
|
|
}
|
|
target := h.Val()
|
|
handler.Resources = append(handler.Resources, Resource{
|
|
Method: method,
|
|
Target: target,
|
|
})
|
|
|
|
default:
|
|
handler.Resources = append(handler.Resources, Resource{Target: h.Val()})
|
|
}
|
|
}
|
|
}
|
|
|
|
return handler, nil
|
|
}
|