mirror of
https://github.com/caddyserver/caddy.git
synced 2025-03-23 05:49:27 +01:00
httpcaddyfile: Configure servers via global options (#3836)
* 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>
This commit is contained in:
parent
4a641f6c6f
commit
3cfefeb0f7
15 changed files with 1084 additions and 658 deletions
|
@ -18,6 +18,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
@ -163,6 +164,13 @@ func (st *ServerType) consolidateAddrMappings(addrToServerBlocks map[string][]se
|
||||||
|
|
||||||
sbaddrs = append(sbaddrs, a)
|
sbaddrs = append(sbaddrs, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sort them by their first address (we know there will always be at least one)
|
||||||
|
// to avoid problems with non-deterministic ordering (makes tests flaky)
|
||||||
|
sort.Slice(sbaddrs, func(i, j int) bool {
|
||||||
|
return sbaddrs[i].addresses[0] < sbaddrs[j].addresses[0]
|
||||||
|
})
|
||||||
|
|
||||||
return sbaddrs
|
return sbaddrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -218,13 +218,6 @@ func (st ServerType) Setup(inputServerBlocks []caddyfile.ServerBlock,
|
||||||
return nil, warnings, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// if experimental HTTP/3 is enabled, enable it on each server
|
|
||||||
if enableH3, ok := options["experimental_http3"].(bool); ok && enableH3 {
|
|
||||||
for _, srv := range httpApp.Servers {
|
|
||||||
srv.ExperimentalHTTP3 = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// extract any custom logs, and enforce configured levels
|
// extract any custom logs, and enforce configured levels
|
||||||
var customLogs []namedCustomLog
|
var customLogs []namedCustomLog
|
||||||
var hasDefaultLog bool
|
var hasDefaultLog bool
|
||||||
|
@ -311,23 +304,54 @@ func (ServerType) evaluateGlobalOptionsBlock(serverBlocks []serverBlock, options
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, segment := range serverBlocks[0].block.Segments {
|
for _, segment := range serverBlocks[0].block.Segments {
|
||||||
dir := segment.Directive()
|
opt := segment.Directive()
|
||||||
var val interface{}
|
var val interface{}
|
||||||
var err error
|
var err error
|
||||||
disp := caddyfile.NewDispenser(segment)
|
disp := caddyfile.NewDispenser(segment)
|
||||||
|
|
||||||
dirFunc, ok := registeredGlobalOptions[dir]
|
optFunc, ok := registeredGlobalOptions[opt]
|
||||||
if !ok {
|
if !ok {
|
||||||
tkn := segment[0]
|
tkn := segment[0]
|
||||||
return nil, fmt.Errorf("%s:%d: unrecognized global option: %s", tkn.File, tkn.Line, dir)
|
return nil, fmt.Errorf("%s:%d: unrecognized global option: %s", tkn.File, tkn.Line, opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
val, err = dirFunc(disp)
|
val, err = optFunc(disp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("parsing caddyfile tokens for '%s': %v", dir, err)
|
return nil, fmt.Errorf("parsing caddyfile tokens for '%s': %v", opt, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
options[dir] = val
|
// As a special case, fold multiple "servers" options together
|
||||||
|
// in an array instead of overwriting a possible existing value
|
||||||
|
if opt == "servers" {
|
||||||
|
existingOpts, ok := options[opt].([]serverOptions)
|
||||||
|
if !ok {
|
||||||
|
existingOpts = []serverOptions{}
|
||||||
|
}
|
||||||
|
serverOpts, ok := val.(serverOptions)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("unexpected type from 'servers' global options")
|
||||||
|
}
|
||||||
|
options[opt] = append(existingOpts, serverOpts)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
options[opt] = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we got "servers" options, we'll sort them by their listener address
|
||||||
|
if serverOpts, ok := options["servers"].([]serverOptions); ok {
|
||||||
|
sort.Slice(serverOpts, func(i, j int) bool {
|
||||||
|
return len(serverOpts[i].ListenerAddress) > len(serverOpts[j].ListenerAddress)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Reject the config if there are duplicate listener address
|
||||||
|
seen := make(map[string]bool)
|
||||||
|
for _, entry := range serverOpts {
|
||||||
|
if _, alreadySeen := seen[entry.ListenerAddress]; alreadySeen {
|
||||||
|
return nil, fmt.Errorf("cannot have 'servers' global options with duplicate listener addresses: %s", entry.ListenerAddress)
|
||||||
|
}
|
||||||
|
seen[entry.ListenerAddress] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return serverBlocks[1:], nil
|
return serverBlocks[1:], nil
|
||||||
|
@ -602,6 +626,11 @@ func (st *ServerType) serversFromPairings(
|
||||||
servers[fmt.Sprintf("srv%d", i)] = srv
|
servers[fmt.Sprintf("srv%d", i)] = srv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := applyServerOptions(servers, options, warnings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return servers, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ func init() {
|
||||||
RegisterGlobalOption("local_certs", parseOptTrue)
|
RegisterGlobalOption("local_certs", parseOptTrue)
|
||||||
RegisterGlobalOption("key_type", parseOptSingleString)
|
RegisterGlobalOption("key_type", parseOptSingleString)
|
||||||
RegisterGlobalOption("auto_https", parseOptAutoHTTPS)
|
RegisterGlobalOption("auto_https", parseOptAutoHTTPS)
|
||||||
|
RegisterGlobalOption("servers", parseServerOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseOptTrue(d *caddyfile.Dispenser) (interface{}, error) {
|
func parseOptTrue(d *caddyfile.Dispenser) (interface{}, error) {
|
||||||
|
@ -361,3 +362,7 @@ func parseOptAutoHTTPS(d *caddyfile.Dispenser) (interface{}, error) {
|
||||||
}
|
}
|
||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseServerOptions(d *caddyfile.Dispenser) (interface{}, error) {
|
||||||
|
return unmarshalCaddyfileServerOptions(d)
|
||||||
|
}
|
||||||
|
|
235
caddyconfig/httpcaddyfile/serveroptions.go
Normal file
235
caddyconfig/httpcaddyfile/serveroptions.go
Normal file
|
@ -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
|
:80
|
||||||
handle_path /api/v1/* {
|
handle_path /api/v1/* {
|
||||||
respond "API v1"
|
respond "API v1"
|
||||||
}
|
}
|
||||||
----------
|
----------
|
||||||
{
|
{
|
||||||
"apps": {
|
"apps": {
|
||||||
"http": {
|
"http": {
|
||||||
"servers": {
|
"servers": {
|
||||||
"srv0": {
|
"srv0": {
|
||||||
"listen": [
|
"listen": [
|
||||||
":80"
|
":80"
|
||||||
],
|
],
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"match": [
|
"match": [
|
||||||
{
|
{
|
||||||
"path": [
|
"path": [
|
||||||
"/api/v1/*"
|
"/api/v1/*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "subroute",
|
"handler": "subroute",
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "rewrite",
|
"handler": "rewrite",
|
||||||
"strip_path_prefix": "/api/v1"
|
"strip_path_prefix": "/api/v1"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"body": "API v1",
|
"body": "API v1",
|
||||||
"handler": "static_response"
|
"handler": "static_response"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,105 +1,105 @@
|
||||||
:80 {
|
:80 {
|
||||||
handle /api/* {
|
handle /api/* {
|
||||||
respond "api"
|
respond "api"
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_path /static/* {
|
handle_path /static/* {
|
||||||
respond "static"
|
respond "static"
|
||||||
}
|
}
|
||||||
|
|
||||||
handle {
|
handle {
|
||||||
respond "handle"
|
respond "handle"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----------
|
----------
|
||||||
{
|
{
|
||||||
"apps": {
|
"apps": {
|
||||||
"http": {
|
"http": {
|
||||||
"servers": {
|
"servers": {
|
||||||
"srv0": {
|
"srv0": {
|
||||||
"listen": [
|
"listen": [
|
||||||
":80"
|
":80"
|
||||||
],
|
],
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"group": "group3",
|
"group": "group3",
|
||||||
"match": [
|
"match": [
|
||||||
{
|
{
|
||||||
"path": [
|
"path": [
|
||||||
"/static/*"
|
"/static/*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "subroute",
|
"handler": "subroute",
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "rewrite",
|
"handler": "rewrite",
|
||||||
"strip_path_prefix": "/static"
|
"strip_path_prefix": "/static"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"body": "static",
|
"body": "static",
|
||||||
"handler": "static_response"
|
"handler": "static_response"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "group3",
|
"group": "group3",
|
||||||
"match": [
|
"match": [
|
||||||
{
|
{
|
||||||
"path": [
|
"path": [
|
||||||
"/api/*"
|
"/api/*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "subroute",
|
"handler": "subroute",
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"body": "api",
|
"body": "api",
|
||||||
"handler": "static_response"
|
"handler": "static_response"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "group3",
|
"group": "group3",
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "subroute",
|
"handler": "subroute",
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"body": "handle",
|
"body": "handle",
|
||||||
"handler": "static_response"
|
"handler": "static_response"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,49 +1,49 @@
|
||||||
example.com
|
example.com
|
||||||
|
|
||||||
import testdata/import_respond.txt Groot Rocket
|
import testdata/import_respond.txt Groot Rocket
|
||||||
import testdata/import_respond.txt you "the confused man"
|
import testdata/import_respond.txt you "the confused man"
|
||||||
----------
|
----------
|
||||||
{
|
{
|
||||||
"apps": {
|
"apps": {
|
||||||
"http": {
|
"http": {
|
||||||
"servers": {
|
"servers": {
|
||||||
"srv0": {
|
"srv0": {
|
||||||
"listen": [
|
"listen": [
|
||||||
":443"
|
":443"
|
||||||
],
|
],
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"match": [
|
"match": [
|
||||||
{
|
{
|
||||||
"host": [
|
"host": [
|
||||||
"example.com"
|
"example.com"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "subroute",
|
"handler": "subroute",
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"body": "'I am Groot', hears Rocket",
|
"body": "'I am Groot', hears Rocket",
|
||||||
"handler": "static_response"
|
"handler": "static_response"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"body": "'I am you', hears the confused man",
|
"body": "'I am you', hears the confused man",
|
||||||
"handler": "static_response"
|
"handler": "static_response"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"terminal": true
|
"terminal": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,83 +1,83 @@
|
||||||
(logging) {
|
(logging) {
|
||||||
log {
|
log {
|
||||||
output file /var/log/caddy/{args.0}.access.log
|
output file /var/log/caddy/{args.0}.access.log
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a.example.com {
|
a.example.com {
|
||||||
import logging a.example.com
|
import logging a.example.com
|
||||||
}
|
}
|
||||||
|
|
||||||
b.example.com {
|
b.example.com {
|
||||||
import logging b.example.com
|
import logging b.example.com
|
||||||
}
|
}
|
||||||
----------
|
----------
|
||||||
{
|
{
|
||||||
"logging": {
|
"logging": {
|
||||||
"logs": {
|
"logs": {
|
||||||
"default": {
|
"default": {
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"http.log.access.log0",
|
"http.log.access.log0",
|
||||||
"http.log.access.log1"
|
"http.log.access.log1"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"log0": {
|
"log0": {
|
||||||
"writer": {
|
"writer": {
|
||||||
"filename": "/var/log/caddy/a.example.com.access.log",
|
"filename": "/var/log/caddy/a.example.com.access.log",
|
||||||
"output": "file"
|
"output": "file"
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"http.log.access.log0"
|
"http.log.access.log0"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"log1": {
|
"log1": {
|
||||||
"writer": {
|
"writer": {
|
||||||
"filename": "/var/log/caddy/b.example.com.access.log",
|
"filename": "/var/log/caddy/b.example.com.access.log",
|
||||||
"output": "file"
|
"output": "file"
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"http.log.access.log1"
|
"http.log.access.log1"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"apps": {
|
"apps": {
|
||||||
"http": {
|
"http": {
|
||||||
"servers": {
|
"servers": {
|
||||||
"srv0": {
|
"srv0": {
|
||||||
"listen": [
|
"listen": [
|
||||||
":443"
|
":443"
|
||||||
],
|
],
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"match": [
|
"match": [
|
||||||
{
|
{
|
||||||
"host": [
|
"host": [
|
||||||
"a.example.com"
|
"a.example.com"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"terminal": true
|
"terminal": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"match": [
|
"match": [
|
||||||
{
|
{
|
||||||
"host": [
|
"host": [
|
||||||
"b.example.com"
|
"b.example.com"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"terminal": true
|
"terminal": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"logs": {
|
"logs": {
|
||||||
"logger_names": {
|
"logger_names": {
|
||||||
"a.example.com": "log0",
|
"a.example.com": "log0",
|
||||||
"b.example.com": "log1"
|
"b.example.com": "log1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,69 +1,69 @@
|
||||||
:80
|
:80
|
||||||
|
|
||||||
log {
|
log {
|
||||||
output stdout
|
output stdout
|
||||||
format filter {
|
format filter {
|
||||||
wrap console
|
wrap console
|
||||||
fields {
|
fields {
|
||||||
request>headers>Authorization delete
|
request>headers>Authorization delete
|
||||||
request>headers>Server delete
|
request>headers>Server delete
|
||||||
request>remote_addr ip_mask {
|
request>remote_addr ip_mask {
|
||||||
ipv4 24
|
ipv4 24
|
||||||
ipv6 32
|
ipv6 32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----------
|
----------
|
||||||
{
|
{
|
||||||
"logging": {
|
"logging": {
|
||||||
"logs": {
|
"logs": {
|
||||||
"default": {
|
"default": {
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"http.log.access.log0"
|
"http.log.access.log0"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"log0": {
|
"log0": {
|
||||||
"writer": {
|
"writer": {
|
||||||
"output": "stdout"
|
"output": "stdout"
|
||||||
},
|
},
|
||||||
"encoder": {
|
"encoder": {
|
||||||
"fields": {
|
"fields": {
|
||||||
"request\u003eheaders\u003eAuthorization": {
|
"request\u003eheaders\u003eAuthorization": {
|
||||||
"filter": "delete"
|
"filter": "delete"
|
||||||
},
|
},
|
||||||
"request\u003eheaders\u003eServer": {
|
"request\u003eheaders\u003eServer": {
|
||||||
"filter": "delete"
|
"filter": "delete"
|
||||||
},
|
},
|
||||||
"request\u003eremote_addr": {
|
"request\u003eremote_addr": {
|
||||||
"filter": "ip_mask",
|
"filter": "ip_mask",
|
||||||
"ipv4_cidr": 24,
|
"ipv4_cidr": 24,
|
||||||
"ipv6_cidr": 32
|
"ipv6_cidr": 32
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"format": "filter",
|
"format": "filter",
|
||||||
"wrap": {
|
"wrap": {
|
||||||
"format": "console"
|
"format": "console"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"http.log.access.log0"
|
"http.log.access.log0"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"apps": {
|
"apps": {
|
||||||
"http": {
|
"http": {
|
||||||
"servers": {
|
"servers": {
|
||||||
"srv0": {
|
"srv0": {
|
||||||
"listen": [
|
"listen": [
|
||||||
":80"
|
":80"
|
||||||
],
|
],
|
||||||
"logs": {
|
"logs": {
|
||||||
"default_logger_name": "log0"
|
"default_logger_name": "log0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,132 +1,132 @@
|
||||||
:8886
|
:8886
|
||||||
|
|
||||||
route {
|
route {
|
||||||
# Add trailing slash for directory requests
|
# Add trailing slash for directory requests
|
||||||
@canonicalPath {
|
@canonicalPath {
|
||||||
file {
|
file {
|
||||||
try_files {path}/index.php
|
try_files {path}/index.php
|
||||||
}
|
}
|
||||||
not path */
|
not path */
|
||||||
}
|
}
|
||||||
redir @canonicalPath {path}/ 308
|
redir @canonicalPath {path}/ 308
|
||||||
|
|
||||||
# If the requested file does not exist, try index files
|
# If the requested file does not exist, try index files
|
||||||
@indexFiles {
|
@indexFiles {
|
||||||
file {
|
file {
|
||||||
try_files {path} {path}/index.php index.php
|
try_files {path} {path}/index.php index.php
|
||||||
split_path .php
|
split_path .php
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rewrite @indexFiles {http.matchers.file.relative}
|
rewrite @indexFiles {http.matchers.file.relative}
|
||||||
|
|
||||||
# Proxy PHP files to the FastCGI responder
|
# Proxy PHP files to the FastCGI responder
|
||||||
@phpFiles {
|
@phpFiles {
|
||||||
path *.php
|
path *.php
|
||||||
}
|
}
|
||||||
reverse_proxy @phpFiles 127.0.0.1:9000 {
|
reverse_proxy @phpFiles 127.0.0.1:9000 {
|
||||||
transport fastcgi {
|
transport fastcgi {
|
||||||
split .php
|
split .php
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----------
|
----------
|
||||||
{
|
{
|
||||||
"apps": {
|
"apps": {
|
||||||
"http": {
|
"http": {
|
||||||
"servers": {
|
"servers": {
|
||||||
"srv0": {
|
"srv0": {
|
||||||
"listen": [
|
"listen": [
|
||||||
":8886"
|
":8886"
|
||||||
],
|
],
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "subroute",
|
"handler": "subroute",
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "static_response",
|
"handler": "static_response",
|
||||||
"headers": {
|
"headers": {
|
||||||
"Location": [
|
"Location": [
|
||||||
"{http.request.uri.path}/"
|
"{http.request.uri.path}/"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"status_code": 308
|
"status_code": 308
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
{
|
{
|
||||||
"file": {
|
"file": {
|
||||||
"try_files": [
|
"try_files": [
|
||||||
"{http.request.uri.path}/index.php"
|
"{http.request.uri.path}/index.php"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"not": [
|
"not": [
|
||||||
{
|
{
|
||||||
"path": [
|
"path": [
|
||||||
"*/"
|
"*/"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "rewrite",
|
"handler": "rewrite",
|
||||||
"uri": "{http.matchers.file.relative}"
|
"uri": "{http.matchers.file.relative}"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
{
|
{
|
||||||
"file": {
|
"file": {
|
||||||
"split_path": [
|
"split_path": [
|
||||||
".php"
|
".php"
|
||||||
],
|
],
|
||||||
"try_files": [
|
"try_files": [
|
||||||
"{http.request.uri.path}",
|
"{http.request.uri.path}",
|
||||||
"{http.request.uri.path}/index.php",
|
"{http.request.uri.path}/index.php",
|
||||||
"index.php"
|
"index.php"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "reverse_proxy",
|
"handler": "reverse_proxy",
|
||||||
"transport": {
|
"transport": {
|
||||||
"protocol": "fastcgi",
|
"protocol": "fastcgi",
|
||||||
"split_path": [
|
"split_path": [
|
||||||
".php"
|
".php"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"upstreams": [
|
"upstreams": [
|
||||||
{
|
{
|
||||||
"dial": "127.0.0.1:9000"
|
"dial": "127.0.0.1:9000"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
{
|
{
|
||||||
"path": [
|
"path": [
|
||||||
"*.php"
|
"*.php"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,112 +1,112 @@
|
||||||
:8884
|
:8884
|
||||||
|
|
||||||
@api host example.com
|
@api host example.com
|
||||||
php_fastcgi @api localhost:9000
|
php_fastcgi @api localhost:9000
|
||||||
----------
|
----------
|
||||||
{
|
{
|
||||||
"apps": {
|
"apps": {
|
||||||
"http": {
|
"http": {
|
||||||
"servers": {
|
"servers": {
|
||||||
"srv0": {
|
"srv0": {
|
||||||
"listen": [
|
"listen": [
|
||||||
":8884"
|
":8884"
|
||||||
],
|
],
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"match": [
|
"match": [
|
||||||
{
|
{
|
||||||
"host": [
|
"host": [
|
||||||
"example.com"
|
"example.com"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "subroute",
|
"handler": "subroute",
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "static_response",
|
"handler": "static_response",
|
||||||
"headers": {
|
"headers": {
|
||||||
"Location": [
|
"Location": [
|
||||||
"{http.request.uri.path}/"
|
"{http.request.uri.path}/"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"status_code": 308
|
"status_code": 308
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
{
|
{
|
||||||
"file": {
|
"file": {
|
||||||
"try_files": [
|
"try_files": [
|
||||||
"{http.request.uri.path}/index.php"
|
"{http.request.uri.path}/index.php"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"not": [
|
"not": [
|
||||||
{
|
{
|
||||||
"path": [
|
"path": [
|
||||||
"*/"
|
"*/"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "rewrite",
|
"handler": "rewrite",
|
||||||
"uri": "{http.matchers.file.relative}"
|
"uri": "{http.matchers.file.relative}"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
{
|
{
|
||||||
"file": {
|
"file": {
|
||||||
"split_path": [
|
"split_path": [
|
||||||
".php"
|
".php"
|
||||||
],
|
],
|
||||||
"try_files": [
|
"try_files": [
|
||||||
"{http.request.uri.path}",
|
"{http.request.uri.path}",
|
||||||
"{http.request.uri.path}/index.php",
|
"{http.request.uri.path}/index.php",
|
||||||
"index.php"
|
"index.php"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "reverse_proxy",
|
"handler": "reverse_proxy",
|
||||||
"transport": {
|
"transport": {
|
||||||
"protocol": "fastcgi",
|
"protocol": "fastcgi",
|
||||||
"split_path": [
|
"split_path": [
|
||||||
".php"
|
".php"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"upstreams": [
|
"upstreams": [
|
||||||
{
|
{
|
||||||
"dial": "localhost:9000"
|
"dial": "localhost:9000"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
{
|
{
|
||||||
"path": [
|
"path": [
|
||||||
"*.php"
|
"*.php"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,51 +1,51 @@
|
||||||
:80
|
:80
|
||||||
|
|
||||||
respond 200
|
respond 200
|
||||||
|
|
||||||
@untrusted not remote_ip 10.1.1.0/24
|
@untrusted not remote_ip 10.1.1.0/24
|
||||||
respond @untrusted 401
|
respond @untrusted 401
|
||||||
----------
|
----------
|
||||||
{
|
{
|
||||||
"apps": {
|
"apps": {
|
||||||
"http": {
|
"http": {
|
||||||
"servers": {
|
"servers": {
|
||||||
"srv0": {
|
"srv0": {
|
||||||
"listen": [
|
"listen": [
|
||||||
":80"
|
":80"
|
||||||
],
|
],
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"match": [
|
"match": [
|
||||||
{
|
{
|
||||||
"not": [
|
"not": [
|
||||||
{
|
{
|
||||||
"remote_ip": {
|
"remote_ip": {
|
||||||
"ranges": [
|
"ranges": [
|
||||||
"10.1.1.0/24"
|
"10.1.1.0/24"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "static_response",
|
"handler": "static_response",
|
||||||
"status_code": 401
|
"status_code": 401
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "static_response",
|
"handler": "static_response",
|
||||||
"status_code": 200
|
"status_code": 200
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
|
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -231,6 +232,8 @@ func (tlsPlaceholderWrapper) CaddyModule() caddy.ModuleInfo {
|
||||||
|
|
||||||
func (tlsPlaceholderWrapper) WrapListener(ln net.Listener) net.Listener { return ln }
|
func (tlsPlaceholderWrapper) WrapListener(ln net.Listener) net.Listener { return ln }
|
||||||
|
|
||||||
|
func (tlsPlaceholderWrapper) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { return nil }
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// DefaultHTTPPort is the default port for HTTP.
|
// DefaultHTTPPort is the default port for HTTP.
|
||||||
DefaultHTTPPort = 80
|
DefaultHTTPPort = 80
|
||||||
|
@ -241,3 +244,4 @@ const (
|
||||||
|
|
||||||
// Interface guard
|
// Interface guard
|
||||||
var _ caddy.ListenerWrapper = (*tlsPlaceholderWrapper)(nil)
|
var _ caddy.ListenerWrapper = (*tlsPlaceholderWrapper)(nil)
|
||||||
|
var _ caddyfile.Unmarshaler = (*tlsPlaceholderWrapper)(nil)
|
||||||
|
|
Loading…
Add table
Reference in a new issue