Browse Source
* httpcaddyfile: First pass at implementing server options * httpcaddyfile: Add listener wrapper support * httpcaddyfile: Sort sbaddrs to make adapt output more deterministic * httpcaddyfile: Add server options adapt tests * httpcaddyfile: Windows line endings lol * caddytest: More windows line endings lol (sorry Matt) * Update caddyconfig/httpcaddyfile/serveroptions.go Co-authored-by: Matt Holt <mholt@users.noreply.github.com> * httpcaddyfile: Reword listener address "matcher" * Apply suggestions from code review Co-authored-by: Matt Holt <mholt@users.noreply.github.com> * httpcaddyfile: Deprecate experimental_http3 option (moved to servers) * httpcaddyfile: Remove validation step, no longer needed Co-authored-by: Matt Holt <mholt@users.noreply.github.com>master
committed by
GitHub
15 changed files with 1084 additions and 658 deletions
@ -0,0 +1,235 @@ |
|||
// 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 httpcaddyfile |
|||
|
|||
import ( |
|||
"encoding/json" |
|||
"fmt" |
|||
|
|||
"github.com/caddyserver/caddy/v2" |
|||
"github.com/caddyserver/caddy/v2/caddyconfig" |
|||
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" |
|||
"github.com/caddyserver/caddy/v2/modules/caddyhttp" |
|||
"github.com/dustin/go-humanize" |
|||
) |
|||
|
|||
// serverOptions collects server config overrides parsed from Caddyfile global options
|
|||
type serverOptions struct { |
|||
// If set, will only apply these options to servers that contain a
|
|||
// listener address that matches exactly. If empty, will apply to all
|
|||
// servers that were not already matched by another serverOptions.
|
|||
ListenerAddress string |
|||
|
|||
// These will all map 1:1 to the caddyhttp.Server struct
|
|||
ListenerWrappersRaw []json.RawMessage |
|||
ReadTimeout caddy.Duration |
|||
ReadHeaderTimeout caddy.Duration |
|||
WriteTimeout caddy.Duration |
|||
IdleTimeout caddy.Duration |
|||
MaxHeaderBytes int |
|||
AllowH2C bool |
|||
ExperimentalHTTP3 bool |
|||
StrictSNIHost *bool |
|||
} |
|||
|
|||
func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (interface{}, error) { |
|||
serverOpts := serverOptions{} |
|||
for d.Next() { |
|||
if d.NextArg() { |
|||
serverOpts.ListenerAddress = d.Val() |
|||
if d.NextArg() { |
|||
return nil, d.ArgErr() |
|||
} |
|||
} |
|||
for nesting := d.Nesting(); d.NextBlock(nesting); { |
|||
switch d.Val() { |
|||
case "listener_wrappers": |
|||
for nesting := d.Nesting(); d.NextBlock(nesting); { |
|||
mod, err := caddy.GetModule("caddy.listeners." + d.Val()) |
|||
if err != nil { |
|||
return nil, fmt.Errorf("finding listener module '%s': %v", d.Val(), err) |
|||
} |
|||
unm, ok := mod.New().(caddyfile.Unmarshaler) |
|||
if !ok { |
|||
return nil, fmt.Errorf("listener module '%s' is not a Caddyfile unmarshaler", mod) |
|||
} |
|||
err = unm.UnmarshalCaddyfile(d.NewFromNextSegment()) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
listenerWrapper, ok := unm.(caddy.ListenerWrapper) |
|||
if !ok { |
|||
return nil, fmt.Errorf("module %s is not a listener wrapper", mod) |
|||
} |
|||
jsonListenerWrapper := caddyconfig.JSONModuleObject( |
|||
listenerWrapper, |
|||
"wrapper", |
|||
listenerWrapper.(caddy.Module).CaddyModule().ID.Name(), |
|||
nil, |
|||
) |
|||
serverOpts.ListenerWrappersRaw = append(serverOpts.ListenerWrappersRaw, jsonListenerWrapper) |
|||
} |
|||
|
|||
case "timeouts": |
|||
for nesting := d.Nesting(); d.NextBlock(nesting); { |
|||
switch d.Val() { |
|||
case "read_body": |
|||
if !d.NextArg() { |
|||
return nil, d.ArgErr() |
|||
} |
|||
dur, err := caddy.ParseDuration(d.Val()) |
|||
if err != nil { |
|||
return nil, d.Errf("parsing read_body timeout duration: %v", err) |
|||
} |
|||
serverOpts.ReadTimeout = caddy.Duration(dur) |
|||
|
|||
case "read_header": |
|||
if !d.NextArg() { |
|||
return nil, d.ArgErr() |
|||
} |
|||
dur, err := caddy.ParseDuration(d.Val()) |
|||
if err != nil { |
|||
return nil, d.Errf("parsing read_header timeout duration: %v", err) |
|||
} |
|||
serverOpts.ReadHeaderTimeout = caddy.Duration(dur) |
|||
|
|||
case "write": |
|||
if !d.NextArg() { |
|||
return nil, d.ArgErr() |
|||
} |
|||
dur, err := caddy.ParseDuration(d.Val()) |
|||
if err != nil { |
|||
return nil, d.Errf("parsing write timeout duration: %v", err) |
|||
} |
|||
serverOpts.WriteTimeout = caddy.Duration(dur) |
|||
|
|||
case "idle": |
|||
if !d.NextArg() { |
|||
return nil, d.ArgErr() |
|||
} |
|||
dur, err := caddy.ParseDuration(d.Val()) |
|||
if err != nil { |
|||
return nil, d.Errf("parsing idle timeout duration: %v", err) |
|||
} |
|||
serverOpts.IdleTimeout = caddy.Duration(dur) |
|||
|
|||
default: |
|||
return nil, d.Errf("unrecognized timeouts option '%s'", d.Val()) |
|||
} |
|||
} |
|||
|
|||
case "max_header_size": |
|||
var sizeStr string |
|||
if !d.AllArgs(&sizeStr) { |
|||
return nil, d.ArgErr() |
|||
} |
|||
size, err := humanize.ParseBytes(sizeStr) |
|||
if err != nil { |
|||
return nil, d.Errf("parsing max_header_size: %v", err) |
|||
} |
|||
serverOpts.MaxHeaderBytes = int(size) |
|||
|
|||
case "protocol": |
|||
for nesting := d.Nesting(); d.NextBlock(nesting); { |
|||
switch d.Val() { |
|||
case "allow_h2c": |
|||
if d.NextArg() { |
|||
return nil, d.ArgErr() |
|||
} |
|||
serverOpts.AllowH2C = true |
|||
|
|||
case "experimental_http3": |
|||
if d.NextArg() { |
|||
return nil, d.ArgErr() |
|||
} |
|||
serverOpts.ExperimentalHTTP3 = true |
|||
|
|||
case "strict_sni_host": |
|||
if d.NextArg() { |
|||
return nil, d.ArgErr() |
|||
} |
|||
trueBool := true |
|||
serverOpts.StrictSNIHost = &trueBool |
|||
|
|||
default: |
|||
return nil, d.Errf("unrecognized protocol option '%s'", d.Val()) |
|||
} |
|||
} |
|||
|
|||
default: |
|||
return nil, d.Errf("unrecognized servers option '%s'", d.Val()) |
|||
} |
|||
} |
|||
} |
|||
return serverOpts, nil |
|||
} |
|||
|
|||
// applyServerOptions sets the server options on the appropriate servers
|
|||
func applyServerOptions( |
|||
servers map[string]*caddyhttp.Server, |
|||
options map[string]interface{}, |
|||
warnings *[]caddyconfig.Warning, |
|||
) error { |
|||
// If experimental HTTP/3 is enabled, enable it on each server.
|
|||
// We already know there won't be a conflict with serverOptions because
|
|||
// we validated earlier that "experimental_http3" cannot be set at the same
|
|||
// time as "servers"
|
|||
if enableH3, ok := options["experimental_http3"].(bool); ok && enableH3 { |
|||
*warnings = append(*warnings, caddyconfig.Warning{Message: "the 'experimental_http3' global option is deprecated, please use the 'servers > protocol > experimental_http3' option instead"}) |
|||
for _, srv := range servers { |
|||
srv.ExperimentalHTTP3 = true |
|||
} |
|||
} |
|||
|
|||
serverOpts, ok := options["servers"].([]serverOptions) |
|||
if !ok { |
|||
return nil |
|||
} |
|||
|
|||
for _, server := range servers { |
|||
// find the options that apply to this server
|
|||
opts := func() *serverOptions { |
|||
for _, entry := range serverOpts { |
|||
if entry.ListenerAddress == "" { |
|||
return &entry |
|||
} |
|||
for _, listener := range server.Listen { |
|||
if entry.ListenerAddress == listener { |
|||
return &entry |
|||
} |
|||
} |
|||
} |
|||
return nil |
|||
}() |
|||
|
|||
// if none apply, then move to the next server
|
|||
if opts == nil { |
|||
continue |
|||
} |
|||
|
|||
// set all the options
|
|||
server.ListenerWrappersRaw = opts.ListenerWrappersRaw |
|||
server.ReadTimeout = opts.ReadTimeout |
|||
server.ReadHeaderTimeout = opts.ReadHeaderTimeout |
|||
server.WriteTimeout = opts.WriteTimeout |
|||
server.IdleTimeout = opts.IdleTimeout |
|||
server.MaxHeaderBytes = opts.MaxHeaderBytes |
|||
server.AllowH2C = opts.AllowH2C |
|||
server.ExperimentalHTTP3 = opts.ExperimentalHTTP3 |
|||
server.StrictSNIHost = opts.StrictSNIHost |
|||
} |
|||
|
|||
return nil |
|||
} |
@ -0,0 +1,83 @@ |
|||
{ |
|||
servers { |
|||
timeouts { |
|||
idle 90s |
|||
} |
|||
} |
|||
servers :80 { |
|||
timeouts { |
|||
idle 60s |
|||
} |
|||
} |
|||
servers :443 { |
|||
timeouts { |
|||
idle 30s |
|||
} |
|||
} |
|||
} |
|||
|
|||
foo.com { |
|||
} |
|||
|
|||
http://bar.com { |
|||
} |
|||
|
|||
:8080 { |
|||
} |
|||
|
|||
---------- |
|||
{ |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":443" |
|||
], |
|||
"idle_timeout": 30000000000, |
|||
"routes": [ |
|||
{ |
|||
"match": [ |
|||
{ |
|||
"host": [ |
|||
"foo.com" |
|||
] |
|||
} |
|||
], |
|||
"terminal": true |
|||
} |
|||
] |
|||
}, |
|||
"srv1": { |
|||
"listen": [ |
|||
":80" |
|||
], |
|||
"idle_timeout": 60000000000, |
|||
"routes": [ |
|||
{ |
|||
"match": [ |
|||
{ |
|||
"host": [ |
|||
"bar.com" |
|||
] |
|||
} |
|||
], |
|||
"terminal": true |
|||
} |
|||
], |
|||
"automatic_https": { |
|||
"skip": [ |
|||
"bar.com" |
|||
] |
|||
} |
|||
}, |
|||
"srv2": { |
|||
"listen": [ |
|||
":8080" |
|||
], |
|||
"idle_timeout": 90000000000 |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,62 @@ |
|||
{ |
|||
servers { |
|||
listener_wrappers { |
|||
tls |
|||
} |
|||
timeouts { |
|||
read_body 30s |
|||
read_header 30s |
|||
write 30s |
|||
idle 30s |
|||
} |
|||
max_header_size 100MB |
|||
protocol { |
|||
allow_h2c |
|||
experimental_http3 |
|||
strict_sni_host |
|||
} |
|||
} |
|||
} |
|||
|
|||
foo.com { |
|||
} |
|||
|
|||
---------- |
|||
{ |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":443" |
|||
], |
|||
"listener_wrappers": [ |
|||
{ |
|||
"wrapper": "tls" |
|||
} |
|||
], |
|||
"read_timeout": 30000000000, |
|||
"read_header_timeout": 30000000000, |
|||
"write_timeout": 30000000000, |
|||
"idle_timeout": 30000000000, |
|||
"max_header_bytes": 100000000, |
|||
"routes": [ |
|||
{ |
|||
"match": [ |
|||
{ |
|||
"host": [ |
|||
"foo.com" |
|||
] |
|||
} |
|||
], |
|||
"terminal": true |
|||
} |
|||
], |
|||
"strict_sni_host": true, |
|||
"experimental_http3": true, |
|||
"allow_h2c": true |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -1,52 +1,52 @@ |
|||
:80 |
|||
handle_path /api/v1/* { |
|||
respond "API v1" |
|||
} |
|||
---------- |
|||
{ |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":80" |
|||
], |
|||
"routes": [ |
|||
{ |
|||
"match": [ |
|||
{ |
|||
"path": [ |
|||
"/api/v1/*" |
|||
] |
|||
} |
|||
], |
|||
"handle": [ |
|||
{ |
|||
"handler": "subroute", |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "rewrite", |
|||
"strip_path_prefix": "/api/v1" |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"body": "API v1", |
|||
"handler": "static_response" |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
:80 |
|||
handle_path /api/v1/* { |
|||
respond "API v1" |
|||
} |
|||
---------- |
|||
{ |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":80" |
|||
], |
|||
"routes": [ |
|||
{ |
|||
"match": [ |
|||
{ |
|||
"path": [ |
|||
"/api/v1/*" |
|||
] |
|||
} |
|||
], |
|||
"handle": [ |
|||
{ |
|||
"handler": "subroute", |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "rewrite", |
|||
"strip_path_prefix": "/api/v1" |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"body": "API v1", |
|||
"handler": "static_response" |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -1,105 +1,105 @@ |
|||
:80 { |
|||
handle /api/* { |
|||
respond "api" |
|||
} |
|||
|
|||
handle_path /static/* { |
|||
respond "static" |
|||
} |
|||
|
|||
handle { |
|||
respond "handle" |
|||
} |
|||
} |
|||
---------- |
|||
{ |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":80" |
|||
], |
|||
"routes": [ |
|||
{ |
|||
"group": "group3", |
|||
"match": [ |
|||
{ |
|||
"path": [ |
|||
"/static/*" |
|||
] |
|||
} |
|||
], |
|||
"handle": [ |
|||
{ |
|||
"handler": "subroute", |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "rewrite", |
|||
"strip_path_prefix": "/static" |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"body": "static", |
|||
"handler": "static_response" |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"group": "group3", |
|||
"match": [ |
|||
{ |
|||
"path": [ |
|||
"/api/*" |
|||
] |
|||
} |
|||
], |
|||
"handle": [ |
|||
{ |
|||
"handler": "subroute", |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"body": "api", |
|||
"handler": "static_response" |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"group": "group3", |
|||
"handle": [ |
|||
{ |
|||
"handler": "subroute", |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"body": "handle", |
|||
"handler": "static_response" |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
:80 { |
|||
handle /api/* { |
|||
respond "api" |
|||
} |
|||
|
|||
handle_path /static/* { |
|||
respond "static" |
|||
} |
|||
|
|||
handle { |
|||
respond "handle" |
|||
} |
|||
} |
|||
---------- |
|||
{ |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":80" |
|||
], |
|||
"routes": [ |
|||
{ |
|||
"group": "group3", |
|||
"match": [ |
|||
{ |
|||
"path": [ |
|||
"/static/*" |
|||
] |
|||
} |
|||
], |
|||
"handle": [ |
|||
{ |
|||
"handler": "subroute", |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "rewrite", |
|||
"strip_path_prefix": "/static" |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"body": "static", |
|||
"handler": "static_response" |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"group": "group3", |
|||
"match": [ |
|||
{ |
|||
"path": [ |
|||
"/api/*" |
|||
] |
|||
} |
|||
], |
|||
"handle": [ |
|||
{ |
|||
"handler": "subroute", |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"body": "api", |
|||
"handler": "static_response" |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"group": "group3", |
|||
"handle": [ |
|||
{ |
|||
"handler": "subroute", |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"body": "handle", |
|||
"handler": "static_response" |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -1,49 +1,49 @@ |
|||
example.com |
|||
|
|||
import testdata/import_respond.txt Groot Rocket |
|||
import testdata/import_respond.txt you "the confused man" |
|||
---------- |
|||
{ |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":443" |
|||
], |
|||
"routes": [ |
|||
{ |
|||
"match": [ |
|||
{ |
|||
"host": [ |
|||
"example.com" |
|||
] |
|||
} |
|||
], |
|||
"handle": [ |
|||
{ |
|||
"handler": "subroute", |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"body": "'I am Groot', hears Rocket", |
|||
"handler": "static_response" |
|||
}, |
|||
{ |
|||
"body": "'I am you', hears the confused man", |
|||
"handler": "static_response" |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
], |
|||
"terminal": true |
|||
} |
|||
] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
example.com |
|||
|
|||
import testdata/import_respond.txt Groot Rocket |
|||
import testdata/import_respond.txt you "the confused man" |
|||
---------- |
|||
{ |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":443" |
|||
], |
|||
"routes": [ |
|||
{ |
|||
"match": [ |
|||
{ |
|||
"host": [ |
|||
"example.com" |
|||
] |
|||
} |
|||
], |
|||
"handle": [ |
|||
{ |
|||
"handler": "subroute", |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"body": "'I am Groot', hears Rocket", |
|||
"handler": "static_response" |
|||
}, |
|||
{ |
|||
"body": "'I am you', hears the confused man", |
|||
"handler": "static_response" |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
], |
|||
"terminal": true |
|||
} |
|||
] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -1,83 +1,83 @@ |
|||
(logging) { |
|||
log { |
|||
output file /var/log/caddy/{args.0}.access.log |
|||
} |
|||
} |
|||
|
|||
a.example.com { |
|||
import logging a.example.com |
|||
} |
|||
|
|||
b.example.com { |
|||
import logging b.example.com |
|||
} |
|||
---------- |
|||
{ |
|||
"logging": { |
|||
"logs": { |
|||
"default": { |
|||
"exclude": [ |
|||
"http.log.access.log0", |
|||
"http.log.access.log1" |
|||
] |
|||
}, |
|||
"log0": { |
|||
"writer": { |
|||
"filename": "/var/log/caddy/a.example.com.access.log", |
|||
"output": "file" |
|||
}, |
|||
"include": [ |
|||
"http.log.access.log0" |
|||
] |
|||
}, |
|||
"log1": { |
|||
"writer": { |
|||
"filename": "/var/log/caddy/b.example.com.access.log", |
|||
"output": "file" |
|||
}, |
|||
"include": [ |
|||
"http.log.access.log1" |
|||
] |
|||
} |
|||
} |
|||
}, |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":443" |
|||
], |
|||
"routes": [ |
|||
{ |
|||
"match": [ |
|||
{ |
|||
"host": [ |
|||
"a.example.com" |
|||
] |
|||
} |
|||
], |
|||
"terminal": true |
|||
}, |
|||
{ |
|||
"match": [ |
|||
{ |
|||
"host": [ |
|||
"b.example.com" |
|||
] |
|||
} |
|||
], |
|||
"terminal": true |
|||
} |
|||
], |
|||
"logs": { |
|||
"logger_names": { |
|||
"a.example.com": "log0", |
|||
"b.example.com": "log1" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
(logging) { |
|||
log { |
|||
output file /var/log/caddy/{args.0}.access.log |
|||
} |
|||
} |
|||
|
|||
a.example.com { |
|||
import logging a.example.com |
|||
} |
|||
|
|||
b.example.com { |
|||
import logging b.example.com |
|||
} |
|||
---------- |
|||
{ |
|||
"logging": { |
|||
"logs": { |
|||
"default": { |
|||
"exclude": [ |
|||
"http.log.access.log0", |
|||
"http.log.access.log1" |
|||
] |
|||
}, |
|||
"log0": { |
|||
"writer": { |
|||
"filename": "/var/log/caddy/a.example.com.access.log", |
|||
"output": "file" |
|||
}, |
|||
"include": [ |
|||
"http.log.access.log0" |
|||
] |
|||
}, |
|||
"log1": { |
|||
"writer": { |
|||
"filename": "/var/log/caddy/b.example.com.access.log", |
|||
"output": "file" |
|||
}, |
|||
"include": [ |
|||
"http.log.access.log1" |
|||
] |
|||
} |
|||
} |
|||
}, |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":443" |
|||
], |
|||
"routes": [ |
|||
{ |
|||
"match": [ |
|||
{ |
|||
"host": [ |
|||
"a.example.com" |
|||
] |
|||
} |
|||
], |
|||
"terminal": true |
|||
}, |
|||
{ |
|||
"match": [ |
|||
{ |
|||
"host": [ |
|||
"b.example.com" |
|||
] |
|||
} |
|||
], |
|||
"terminal": true |
|||
} |
|||
], |
|||
"logs": { |
|||
"logger_names": { |
|||
"a.example.com": "log0", |
|||
"b.example.com": "log1" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -1,69 +1,69 @@ |
|||
:80 |
|||
|
|||
log { |
|||
output stdout |
|||
format filter { |
|||
wrap console |
|||
fields { |
|||
request>headers>Authorization delete |
|||
request>headers>Server delete |
|||
request>remote_addr ip_mask { |
|||
ipv4 24 |
|||
ipv6 32 |
|||
} |
|||
} |
|||
} |
|||
} |
|||
---------- |
|||
{ |
|||
"logging": { |
|||
"logs": { |
|||
"default": { |
|||
"exclude": [ |
|||
"http.log.access.log0" |
|||
] |
|||
}, |
|||
"log0": { |
|||
"writer": { |
|||
"output": "stdout" |
|||
}, |
|||
"encoder": { |
|||
"fields": { |
|||
"request\u003eheaders\u003eAuthorization": { |
|||
"filter": "delete" |
|||
}, |
|||
"request\u003eheaders\u003eServer": { |
|||
"filter": "delete" |
|||
}, |
|||
"request\u003eremote_addr": { |
|||
"filter": "ip_mask", |
|||
"ipv4_cidr": 24, |
|||
"ipv6_cidr": 32 |
|||
} |
|||
}, |
|||
"format": "filter", |
|||
"wrap": { |
|||
"format": "console" |
|||
} |
|||
}, |
|||
"include": [ |
|||
"http.log.access.log0" |
|||
] |
|||
} |
|||
} |
|||
}, |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":80" |
|||
], |
|||
"logs": { |
|||
"default_logger_name": "log0" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
:80 |
|||
|
|||
log { |
|||
output stdout |
|||
format filter { |
|||
wrap console |
|||
fields { |
|||
request>headers>Authorization delete |
|||
request>headers>Server delete |
|||
request>remote_addr ip_mask { |
|||
ipv4 24 |
|||
ipv6 32 |
|||
} |
|||
} |
|||
} |
|||
} |
|||
---------- |
|||
{ |
|||
"logging": { |
|||
"logs": { |
|||
"default": { |
|||
"exclude": [ |
|||
"http.log.access.log0" |
|||
] |
|||
}, |
|||
"log0": { |
|||
"writer": { |
|||
"output": "stdout" |
|||
}, |
|||
"encoder": { |
|||
"fields": { |
|||
"request\u003eheaders\u003eAuthorization": { |
|||
"filter": "delete" |
|||
}, |
|||
"request\u003eheaders\u003eServer": { |
|||
"filter": "delete" |
|||
}, |
|||
"request\u003eremote_addr": { |
|||
"filter": "ip_mask", |
|||
"ipv4_cidr": 24, |
|||
"ipv6_cidr": 32 |
|||
} |
|||
}, |
|||
"format": "filter", |
|||
"wrap": { |
|||
"format": "console" |
|||
} |
|||
}, |
|||
"include": [ |
|||
"http.log.access.log0" |
|||
] |
|||
} |
|||
} |
|||
}, |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":80" |
|||
], |
|||
"logs": { |
|||
"default_logger_name": "log0" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -1,132 +1,132 @@ |
|||
:8886 |
|||
|
|||
route { |
|||
# Add trailing slash for directory requests |
|||
@canonicalPath { |
|||
file { |
|||
try_files {path}/index.php |
|||
} |
|||
not path */ |
|||
} |
|||
redir @canonicalPath {path}/ 308 |
|||
|
|||
# If the requested file does not exist, try index files |
|||
@indexFiles { |
|||
file { |
|||
try_files {path} {path}/index.php index.php |
|||
split_path .php |
|||
} |
|||
} |
|||
rewrite @indexFiles {http.matchers.file.relative} |
|||
|
|||
# Proxy PHP files to the FastCGI responder |
|||
@phpFiles { |
|||
path *.php |
|||
} |
|||
reverse_proxy @phpFiles 127.0.0.1:9000 { |
|||
transport fastcgi { |
|||
split .php |
|||
} |
|||
} |
|||
} |
|||
---------- |
|||
{ |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":8886" |
|||
], |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "subroute", |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "static_response", |
|||
"headers": { |
|||
"Location": [ |
|||
"{http.request.uri.path}/" |
|||
] |
|||
}, |
|||
"status_code": 308 |
|||
} |
|||
], |
|||
"match": [ |
|||
{ |
|||
"file": { |
|||
"try_files": [ |
|||
"{http.request.uri.path}/index.php" |
|||
] |
|||
}, |
|||
"not": [ |
|||
{ |
|||
"path": [ |
|||
"*/" |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "rewrite", |
|||
"uri": "{http.matchers.file.relative}" |
|||
} |
|||
], |
|||
"match": [ |
|||
{ |
|||
"file": { |
|||
"split_path": [ |
|||
".php" |
|||
], |
|||
"try_files": [ |
|||
"{http.request.uri.path}", |
|||
"{http.request.uri.path}/index.php", |
|||
"index.php" |
|||
] |
|||
} |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "reverse_proxy", |
|||
"transport": { |
|||
"protocol": "fastcgi", |
|||
"split_path": [ |
|||
".php" |
|||
] |
|||
}, |
|||
"upstreams": [ |
|||
{ |
|||
"dial": "127.0.0.1:9000" |
|||
} |
|||
] |
|||
} |
|||
], |
|||
"match": [ |
|||
{ |
|||
"path": [ |
|||
"*.php" |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
:8886 |
|||
|
|||
route { |
|||
# Add trailing slash for directory requests |
|||
@canonicalPath { |
|||
file { |
|||
try_files {path}/index.php |
|||
} |
|||
not path */ |
|||
} |
|||
redir @canonicalPath {path}/ 308 |
|||
|
|||
# If the requested file does not exist, try index files |
|||
@indexFiles { |
|||
file { |
|||
try_files {path} {path}/index.php index.php |
|||
split_path .php |
|||
} |
|||
} |
|||
rewrite @indexFiles {http.matchers.file.relative} |
|||
|
|||
# Proxy PHP files to the FastCGI responder |
|||
@phpFiles { |
|||
path *.php |
|||
} |
|||
reverse_proxy @phpFiles 127.0.0.1:9000 { |
|||
transport fastcgi { |
|||
split .php |
|||
} |
|||
} |
|||
} |
|||
---------- |
|||
{ |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":8886" |
|||
], |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "subroute", |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "static_response", |
|||
"headers": { |
|||
"Location": [ |
|||
"{http.request.uri.path}/" |
|||
] |
|||
}, |
|||
"status_code": 308 |
|||
} |
|||
], |
|||
"match": [ |
|||
{ |
|||
"file": { |
|||
"try_files": [ |
|||
"{http.request.uri.path}/index.php" |
|||
] |
|||
}, |
|||
"not": [ |
|||
{ |
|||
"path": [ |
|||
"*/" |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "rewrite", |
|||
"uri": "{http.matchers.file.relative}" |
|||
} |
|||
], |
|||
"match": [ |
|||
{ |
|||
"file": { |
|||
"split_path": [ |
|||
".php" |
|||
], |
|||
"try_files": [ |
|||
"{http.request.uri.path}", |
|||
"{http.request.uri.path}/index.php", |
|||
"index.php" |
|||
] |
|||
} |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "reverse_proxy", |
|||
"transport": { |
|||
"protocol": "fastcgi", |
|||
"split_path": [ |
|||
".php" |
|||
] |
|||
}, |
|||
"upstreams": [ |
|||
{ |
|||
"dial": "127.0.0.1:9000" |
|||
} |
|||
] |
|||
} |
|||
], |
|||
"match": [ |
|||
{ |
|||
"path": [ |
|||
"*.php" |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -1,112 +1,112 @@ |
|||
:8884 |
|||
|
|||
@api host example.com |
|||
php_fastcgi @api localhost:9000 |
|||
---------- |
|||
{ |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":8884" |
|||
], |
|||
"routes": [ |
|||
{ |
|||
"match": [ |
|||
{ |
|||
"host": [ |
|||
"example.com" |
|||
] |
|||
} |
|||
], |
|||
"handle": [ |
|||
{ |
|||
"handler": "subroute", |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "static_response", |
|||
"headers": { |
|||
"Location": [ |
|||
"{http.request.uri.path}/" |
|||
] |
|||
}, |
|||
"status_code": 308 |
|||
} |
|||
], |
|||
"match": [ |
|||
{ |
|||
"file": { |
|||
"try_files": [ |
|||
"{http.request.uri.path}/index.php" |
|||
] |
|||
}, |
|||
"not": [ |
|||
{ |
|||
"path": [ |
|||
"*/" |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "rewrite", |
|||
"uri": "{http.matchers.file.relative}" |
|||
} |
|||
], |
|||
"match": [ |
|||
{ |
|||
"file": { |
|||
"split_path": [ |
|||
".php" |
|||
], |
|||
"try_files": [ |
|||
"{http.request.uri.path}", |
|||
"{http.request.uri.path}/index.php", |
|||
"index.php" |
|||
] |
|||
} |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "reverse_proxy", |
|||
"transport": { |
|||
"protocol": "fastcgi", |
|||
"split_path": [ |
|||
".php" |
|||
] |
|||
}, |
|||
"upstreams": [ |
|||
{ |
|||
"dial": "localhost:9000" |
|||
} |
|||
] |
|||
} |
|||
], |
|||
"match": [ |
|||
{ |
|||
"path": [ |
|||
"*.php" |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
:8884 |
|||
|
|||
@api host example.com |
|||
php_fastcgi @api localhost:9000 |
|||
---------- |
|||
{ |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":8884" |
|||
], |
|||
"routes": [ |
|||
{ |
|||
"match": [ |
|||
{ |
|||
"host": [ |
|||
"example.com" |
|||
] |
|||
} |
|||
], |
|||
"handle": [ |
|||
{ |
|||
"handler": "subroute", |
|||
"routes": [ |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "static_response", |
|||
"headers": { |
|||
"Location": [ |
|||
"{http.request.uri.path}/" |
|||
] |
|||
}, |
|||
"status_code": 308 |
|||
} |
|||
], |
|||
"match": [ |
|||
{ |
|||
"file": { |
|||
"try_files": [ |
|||
"{http.request.uri.path}/index.php" |
|||
] |
|||
}, |
|||
"not": [ |
|||
{ |
|||
"path": [ |
|||
"*/" |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "rewrite", |
|||
"uri": "{http.matchers.file.relative}" |
|||
} |
|||
], |
|||
"match": [ |
|||
{ |
|||
"file": { |
|||
"split_path": [ |
|||
".php" |
|||
], |
|||
"try_files": [ |
|||
"{http.request.uri.path}", |
|||
"{http.request.uri.path}/index.php", |
|||
"index.php" |
|||
] |
|||
} |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "reverse_proxy", |
|||
"transport": { |
|||
"protocol": "fastcgi", |
|||
"split_path": [ |
|||
".php" |
|||
] |
|||
}, |
|||
"upstreams": [ |
|||
{ |
|||
"dial": "localhost:9000" |
|||
} |
|||
] |
|||
} |
|||
], |
|||
"match": [ |
|||
{ |
|||
"path": [ |
|||
"*.php" |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -1,51 +1,51 @@ |
|||
:80 |
|||
|
|||
respond 200 |
|||
|
|||
@untrusted not remote_ip 10.1.1.0/24 |
|||
respond @untrusted 401 |
|||
---------- |
|||
{ |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":80" |
|||
], |
|||
"routes": [ |
|||
{ |
|||
"match": [ |
|||
{ |
|||
"not": [ |
|||
{ |
|||
"remote_ip": { |
|||
"ranges": [ |
|||
"10.1.1.0/24" |
|||
] |
|||
} |
|||
} |
|||
] |
|||
} |
|||
], |
|||
"handle": [ |
|||
{ |
|||
"handler": "static_response", |
|||
"status_code": 401 |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "static_response", |
|||
"status_code": 200 |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
:80 |
|||
|
|||
respond 200 |
|||
|
|||
@untrusted not remote_ip 10.1.1.0/24 |
|||
respond @untrusted 401 |
|||
---------- |
|||
{ |
|||
"apps": { |
|||
"http": { |
|||
"servers": { |
|||
"srv0": { |
|||
"listen": [ |
|||
":80" |
|||
], |
|||
"routes": [ |
|||
{ |
|||
"match": [ |
|||
{ |
|||
"not": [ |
|||
{ |
|||
"remote_ip": { |
|||
"ranges": [ |
|||
"10.1.1.0/24" |
|||
] |
|||
} |
|||
} |
|||
] |
|||
} |
|||
], |
|||
"handle": [ |
|||
{ |
|||
"handler": "static_response", |
|||
"status_code": 401 |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"handle": [ |
|||
{ |
|||
"handler": "static_response", |
|||
"status_code": 200 |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
Loading…
Reference in new issue