httpcaddyfile: Rewrite `root` and `rewrite` parsing to allow omitting matcher (#5844)

This commit is contained in:
Francis Lavoie 2024-01-15 11:57:08 -05:00 committed by GitHub
parent f3e849e49f
commit 5e2f1b5ced
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 296 additions and 12 deletions

View File

@ -41,7 +41,7 @@ func init() {
RegisterDirective("bind", parseBind)
RegisterDirective("tls", parseTLS)
RegisterHandlerDirective("fs", parseFilesystem)
RegisterHandlerDirective("root", parseRoot)
RegisterDirective("root", parseRoot)
RegisterHandlerDirective("vars", parseVars)
RegisterHandlerDirective("redir", parseRedir)
RegisterHandlerDirective("respond", parseRespond)
@ -645,18 +645,45 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
// parseRoot parses the root directive. Syntax:
//
// root [<matcher>] <path>
func parseRoot(h Helper) (caddyhttp.MiddlewareHandler, error) {
var root string
for h.Next() {
func parseRoot(h Helper) ([]ConfigValue, error) {
// consume directive name
if !h.NextArg() {
return nil, h.ArgErr()
}
// count the tokens to determine what to do
argsCount := h.CountRemainingArgs()
if argsCount == 0 {
return nil, h.Errf("too few arguments; must have at least a root path")
}
if argsCount > 2 {
return nil, h.Errf("too many arguments; should only be a matcher and a path")
}
// with only one arg, assume it's a root path with no matcher token
if argsCount == 1 {
if !h.NextArg() {
return nil, h.ArgErr()
}
root = h.Val()
if h.NextArg() {
return nil, h.ArgErr()
}
return h.NewRoute(nil, caddyhttp.VarsMiddleware{"root": h.Val()}), nil
}
return caddyhttp.VarsMiddleware{"root": root}, nil
// parse the matcher token into a matcher set
userMatcherSet, err := h.ExtractMatcherSet()
if err != nil {
return nil, err
}
// consume directive name, again, because extracting matcher does a reset
if !h.NextArg() {
return nil, h.ArgErr()
}
// advance to the root path
if !h.NextArg() {
return nil, h.ArgErr()
}
// make the route with the matcher
return h.NewRoute(userMatcherSet, caddyhttp.VarsMiddleware{"root": h.Val()}), nil
}
// parseFilesystem parses the fs directive. Syntax:

View File

@ -0,0 +1,112 @@
:8080
# With explicit wildcard matcher
route {
rewrite * /a
}
# With path matcher
route {
rewrite /path /b
}
# With named matcher
route {
@named method GET
rewrite @named /c
}
# With no matcher, assumed to be wildcard
route {
rewrite /d
}
----------
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":8080"
],
"routes": [
{
"handle": [
{
"handler": "subroute",
"routes": [
{
"group": "group0",
"handle": [
{
"handler": "rewrite",
"uri": "/a"
}
]
}
]
},
{
"handler": "subroute",
"routes": [
{
"group": "group1",
"handle": [
{
"handler": "rewrite",
"uri": "/b"
}
],
"match": [
{
"path": [
"/path"
]
}
]
}
]
},
{
"handler": "subroute",
"routes": [
{
"group": "group2",
"handle": [
{
"handler": "rewrite",
"uri": "/c"
}
],
"match": [
{
"method": [
"GET"
]
}
]
}
]
},
{
"handler": "subroute",
"routes": [
{
"group": "group3",
"handle": [
{
"handler": "rewrite",
"uri": "/d"
}
]
}
]
}
]
}
]
}
}
}
}
}

View File

@ -0,0 +1,108 @@
:8080
# With explicit wildcard matcher
route {
root * /a
}
# With path matcher
route {
root /path /b
}
# With named matcher
route {
@named method GET
root @named /c
}
# With no matcher, assumed to be wildcard
route {
root /d
}
----------
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":8080"
],
"routes": [
{
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"handler": "vars",
"root": "/a"
}
]
}
]
},
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"handler": "vars",
"root": "/b"
}
],
"match": [
{
"path": [
"/path"
]
}
]
}
]
},
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"handler": "vars",
"root": "/c"
}
],
"match": [
{
"method": [
"GET"
]
}
]
}
]
},
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"handler": "vars",
"root": "/d"
}
]
}
]
}
]
}
]
}
}
}
}
}

View File

@ -26,7 +26,7 @@ import (
)
func init() {
httpcaddyfile.RegisterHandlerDirective("rewrite", parseCaddyfileRewrite)
httpcaddyfile.RegisterDirective("rewrite", parseCaddyfileRewrite)
httpcaddyfile.RegisterHandlerDirective("method", parseCaddyfileMethod)
httpcaddyfile.RegisterHandlerDirective("uri", parseCaddyfileURI)
httpcaddyfile.RegisterDirective("handle_path", parseCaddyfileHandlePath)
@ -38,7 +38,44 @@ func init() {
//
// Only URI components which are given in <to> will be set in the resulting URI.
// See the docs for the rewrite handler for more information.
func parseCaddyfileRewrite(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
func parseCaddyfileRewrite(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) {
// consume directive name
if !h.NextArg() {
return nil, h.ArgErr()
}
// count the tokens to determine what to do
argsCount := h.CountRemainingArgs()
if argsCount == 0 {
return nil, h.Errf("too few arguments; must have at least a rewrite URI")
}
if argsCount > 2 {
return nil, h.Errf("too many arguments; should only be a matcher and a URI")
}
// with only one arg, assume it's a rewrite URI with no matcher token
if argsCount == 1 {
if !h.NextArg() {
return nil, h.ArgErr()
}
return h.NewRoute(nil, Rewrite{URI: h.Val()}), nil
}
// parse the matcher token into a matcher set
userMatcherSet, err := h.ExtractMatcherSet()
if err != nil {
return nil, err
}
// consume directive name, again, because extracting matcher does a reset
if !h.NextArg() {
return nil, h.ArgErr()
}
// advance to the rewrite URI
if !h.NextArg() {
return nil, h.ArgErr()
}
var rewr Rewrite
for h.Next() {
if !h.NextArg() {
@ -49,7 +86,7 @@ func parseCaddyfileRewrite(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler,
return nil, h.ArgErr()
}
}
return rewr, nil
return h.NewRoute(userMatcherSet, Rewrite{URI: h.Val()}), nil
}
// parseCaddyfileMethod sets up a basic method rewrite handler from Caddyfile tokens. Syntax: