mirror of
https://github.com/caddyserver/caddy.git
synced 2025-02-24 16:59:00 +01:00
Rename and export some types, other minor changes
This commit is contained in:
parent
8ae0d6a509
commit
f9d93ead4e
7 changed files with 151 additions and 106 deletions
|
@ -22,29 +22,31 @@ func init() {
|
||||||
|
|
||||||
err := caddy2.RegisterModule(caddy2.Module{
|
err := caddy2.RegisterModule(caddy2.Module{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
New: func() (interface{}, error) { return new(httpModuleConfig), nil },
|
New: func() (interface{}, error) { return new(App), nil },
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpModuleConfig struct {
|
// App is the HTTP app for Caddy.
|
||||||
HTTPPort int `json:"http_port"`
|
type App struct {
|
||||||
HTTPSPort int `json:"https_port"`
|
HTTPPort int `json:"http_port"`
|
||||||
GracePeriod caddy2.Duration `json:"grace_period"`
|
HTTPSPort int `json:"https_port"`
|
||||||
Servers map[string]*httpServerConfig `json:"servers"`
|
GracePeriod caddy2.Duration `json:"grace_period"`
|
||||||
|
Servers map[string]*Server `json:"servers"`
|
||||||
|
|
||||||
servers []*http.Server
|
servers []*http.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hc *httpModuleConfig) Provision() error {
|
// Provision sets up the app.
|
||||||
|
func (hc *App) Provision() error {
|
||||||
for _, srv := range hc.Servers {
|
for _, srv := range hc.Servers {
|
||||||
err := srv.Routes.setup()
|
err := srv.Routes.Provision()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("setting up server routes: %v", err)
|
return fmt.Errorf("setting up server routes: %v", err)
|
||||||
}
|
}
|
||||||
err = srv.Errors.Routes.setup()
|
err = srv.Errors.Routes.Provision()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("setting up server error handling routes: %v", err)
|
return fmt.Errorf("setting up server error handling routes: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -53,7 +55,8 @@ func (hc *httpModuleConfig) Provision() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hc *httpModuleConfig) Validate() error {
|
// Validate ensures the app's configuration is valid.
|
||||||
|
func (hc *App) Validate() error {
|
||||||
// each server must use distinct listener addresses
|
// each server must use distinct listener addresses
|
||||||
lnAddrs := make(map[string]string)
|
lnAddrs := make(map[string]string)
|
||||||
for srvName, srv := range hc.Servers {
|
for srvName, srv := range hc.Servers {
|
||||||
|
@ -74,7 +77,8 @@ func (hc *httpModuleConfig) Validate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hc *httpModuleConfig) Start(handle caddy2.Handle) error {
|
// Start runs the app. It sets up automatic HTTPS if enabled.
|
||||||
|
func (hc *App) Start(handle caddy2.Handle) error {
|
||||||
err := hc.automaticHTTPS(handle)
|
err := hc.automaticHTTPS(handle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("enabling automatic HTTPS: %v", err)
|
return fmt.Errorf("enabling automatic HTTPS: %v", err)
|
||||||
|
@ -129,7 +133,7 @@ func (hc *httpModuleConfig) Start(handle caddy2.Handle) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop gracefully shuts down the HTTP server.
|
// Stop gracefully shuts down the HTTP server.
|
||||||
func (hc *httpModuleConfig) Stop() error {
|
func (hc *App) Stop() error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
if hc.GracePeriod > 0 {
|
if hc.GracePeriod > 0 {
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
|
@ -145,7 +149,7 @@ func (hc *httpModuleConfig) Stop() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hc *httpModuleConfig) automaticHTTPS(handle caddy2.Handle) error {
|
func (hc *App) automaticHTTPS(handle caddy2.Handle) error {
|
||||||
tlsAppIface, err := handle.App("tls")
|
tlsAppIface, err := handle.App("tls")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getting tls app: %v", err)
|
return fmt.Errorf("getting tls app: %v", err)
|
||||||
|
@ -153,7 +157,7 @@ func (hc *httpModuleConfig) automaticHTTPS(handle caddy2.Handle) error {
|
||||||
tlsApp := tlsAppIface.(*caddytls.TLS)
|
tlsApp := tlsAppIface.(*caddytls.TLS)
|
||||||
|
|
||||||
lnAddrMap := make(map[string]struct{})
|
lnAddrMap := make(map[string]struct{})
|
||||||
var redirRoutes routeList
|
var redirRoutes RouteList
|
||||||
|
|
||||||
for srvName, srv := range hc.Servers {
|
for srvName, srv := range hc.Servers {
|
||||||
srv.tlsApp = tlsApp
|
srv.tlsApp = tlsApp
|
||||||
|
@ -222,7 +226,7 @@ func (hc *httpModuleConfig) automaticHTTPS(handle caddy2.Handle) error {
|
||||||
}
|
}
|
||||||
redirTo += "{request.uri}"
|
redirTo += "{request.uri}"
|
||||||
|
|
||||||
redirRoutes = append(redirRoutes, serverRoute{
|
redirRoutes = append(redirRoutes, ServerRoute{
|
||||||
matchers: []RouteMatcher{
|
matchers: []RouteMatcher{
|
||||||
matchProtocol("http"),
|
matchProtocol("http"),
|
||||||
matchHost(domains),
|
matchHost(domains),
|
||||||
|
@ -255,7 +259,7 @@ func (hc *httpModuleConfig) automaticHTTPS(handle caddy2.Handle) error {
|
||||||
}
|
}
|
||||||
lnAddrs = append(lnAddrs, addr)
|
lnAddrs = append(lnAddrs, addr)
|
||||||
}
|
}
|
||||||
hc.Servers["auto_https_redirects"] = &httpServerConfig{
|
hc.Servers["auto_https_redirects"] = &Server{
|
||||||
Listen: lnAddrs,
|
Listen: lnAddrs,
|
||||||
Routes: redirRoutes,
|
Routes: redirRoutes,
|
||||||
DisableAutoHTTPS: true,
|
DisableAutoHTTPS: true,
|
||||||
|
@ -265,7 +269,7 @@ func (hc *httpModuleConfig) automaticHTTPS(handle caddy2.Handle) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hc *httpModuleConfig) listenerTaken(network, address string) bool {
|
func (hc *App) listenerTaken(network, address string) bool {
|
||||||
for _, srv := range hc.Servers {
|
for _, srv := range hc.Servers {
|
||||||
for _, addr := range srv.Listen {
|
for _, addr := range srv.Listen {
|
||||||
netw, addrs, err := parseListenAddr(addr)
|
netw, addrs, err := parseListenAddr(addr)
|
||||||
|
@ -284,12 +288,13 @@ func (hc *httpModuleConfig) listenerTaken(network, address string) bool {
|
||||||
|
|
||||||
var defaultALPN = []string{"h2", "http/1.1"}
|
var defaultALPN = []string{"h2", "http/1.1"}
|
||||||
|
|
||||||
type httpServerConfig struct {
|
// Server is an HTTP server.
|
||||||
|
type Server struct {
|
||||||
Listen []string `json:"listen"`
|
Listen []string `json:"listen"`
|
||||||
ReadTimeout caddy2.Duration `json:"read_timeout"`
|
ReadTimeout caddy2.Duration `json:"read_timeout"`
|
||||||
ReadHeaderTimeout caddy2.Duration `json:"read_header_timeout"`
|
ReadHeaderTimeout caddy2.Duration `json:"read_header_timeout"`
|
||||||
HiddenFiles []string `json:"hidden_files"` // TODO:... experimenting with shared/common state
|
HiddenFiles []string `json:"hidden_files"` // TODO:... experimenting with shared/common state
|
||||||
Routes routeList `json:"routes"`
|
Routes RouteList `json:"routes"`
|
||||||
Errors httpErrorConfig `json:"errors"`
|
Errors httpErrorConfig `json:"errors"`
|
||||||
TLSConnPolicies caddytls.ConnectionPolicies `json:"tls_connection_policies"`
|
TLSConnPolicies caddytls.ConnectionPolicies `json:"tls_connection_policies"`
|
||||||
DisableAutoHTTPS bool `json:"disable_auto_https"`
|
DisableAutoHTTPS bool `json:"disable_auto_https"`
|
||||||
|
@ -299,23 +304,24 @@ type httpServerConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpErrorConfig struct {
|
type httpErrorConfig struct {
|
||||||
Routes routeList `json:"routes"`
|
Routes RouteList `json:"routes"`
|
||||||
// TODO: some way to configure the logging of errors, probably? standardize the logging configuration first.
|
// TODO: some way to configure the logging of errors, probably? standardize
|
||||||
|
// the logging configuration first.
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeHTTP is the entry point for all HTTP requests.
|
// ServeHTTP is the entry point for all HTTP requests.
|
||||||
func (s httpServerConfig) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (s Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
if s.tlsApp.HandleHTTPChallenge(w, r) {
|
if s.tlsApp.HandleHTTPChallenge(w, r) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up the replacer
|
// set up the replacer
|
||||||
repl := &Replacer{req: r, resp: w, custom: make(map[string]string)}
|
repl := NewReplacer(r, w)
|
||||||
ctx := context.WithValue(r.Context(), ReplacerCtxKey, repl)
|
ctx := context.WithValue(r.Context(), ReplacerCtxKey, repl)
|
||||||
r = r.WithContext(ctx)
|
r = r.WithContext(ctx)
|
||||||
|
|
||||||
// build and execute the main middleware chain
|
// build and execute the main middleware chain
|
||||||
stack := s.Routes.buildMiddlewareChain(w, r)
|
stack := s.Routes.BuildHandlerChain(w, r)
|
||||||
err := executeMiddlewareChain(w, r, stack)
|
err := executeMiddlewareChain(w, r, stack)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// add the error value to the request context so
|
// add the error value to the request context so
|
||||||
|
@ -328,7 +334,7 @@ func (s httpServerConfig) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
// TODO: implement a default error handler?
|
// TODO: implement a default error handler?
|
||||||
log.Printf("[ERROR] %s", err)
|
log.Printf("[ERROR] %s", err)
|
||||||
} else {
|
} else {
|
||||||
errStack := s.Errors.Routes.buildMiddlewareChain(w, r)
|
errStack := s.Errors.Routes.BuildHandlerChain(w, r)
|
||||||
err := executeMiddlewareChain(w, r, errStack)
|
err := executeMiddlewareChain(w, r, errStack)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: what should we do if the error handler has an error?
|
// TODO: what should we do if the error handler has an error?
|
||||||
|
@ -411,6 +417,7 @@ func parseListenAddr(a string) (network string, addrs []string, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
host = NewReplacer(nil, nil).Replace(host, "")
|
||||||
ports := strings.SplitN(port, "-", 2)
|
ports := strings.SplitN(port, "-", 2)
|
||||||
if len(ports) == 1 {
|
if len(ports) == 1 {
|
||||||
ports = append(ports, ports[0])
|
ports = append(ports, ports[0])
|
||||||
|
@ -474,9 +481,6 @@ func (mrw middlewareResponseWriter) Write(b []byte) (int, error) {
|
||||||
return mrw.ResponseWriterWrapper.Write(b)
|
return mrw.ResponseWriterWrapper.Write(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReplacerCtxKey is the context key for the request's replacer.
|
|
||||||
const ReplacerCtxKey caddy2.CtxKey = "replacer"
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// DefaultHTTPPort is the default port for HTTP.
|
// DefaultHTTPPort is the default port for HTTP.
|
||||||
DefaultHTTPPort = 80
|
DefaultHTTPPort = 80
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package caddyhttp
|
package caddyhttp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
@ -114,6 +115,11 @@ func TestJoinListenerAddr(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseListenerAddr(t *testing.T) {
|
func TestParseListenerAddr(t *testing.T) {
|
||||||
|
hostname, err := os.Hostname()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Cannot ascertain system hostname: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
for i, tc := range []struct {
|
for i, tc := range []struct {
|
||||||
input string
|
input string
|
||||||
expectNetwork string
|
expectNetwork string
|
||||||
|
@ -170,6 +176,11 @@ func TestParseListenerAddr(t *testing.T) {
|
||||||
expectNetwork: "tcp",
|
expectNetwork: "tcp",
|
||||||
expectAddrs: []string{"localhost:0"},
|
expectAddrs: []string{"localhost:0"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
input: "{system.hostname}:0",
|
||||||
|
expectNetwork: "tcp",
|
||||||
|
expectAddrs: []string{hostname + ":0"},
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
actualNetwork, actualAddrs, err := parseListenAddr(tc.input)
|
actualNetwork, actualAddrs, err := parseListenAddr(tc.input)
|
||||||
if tc.expectErr && err == nil {
|
if tc.expectErr && err == nil {
|
||||||
|
|
|
@ -205,7 +205,7 @@ func TestPathREMatcher(t *testing.T) {
|
||||||
|
|
||||||
// set up the fake request and its Replacer
|
// set up the fake request and its Replacer
|
||||||
req := &http.Request{URL: &url.URL{Path: tc.input}}
|
req := &http.Request{URL: &url.URL{Path: tc.input}}
|
||||||
repl := &Replacer{req: req, resp: httptest.NewRecorder(), custom: make(map[string]string)}
|
repl := NewReplacer(req, httptest.NewRecorder())
|
||||||
ctx := context.WithValue(req.Context(), ReplacerCtxKey, repl)
|
ctx := context.WithValue(req.Context(), ReplacerCtxKey, repl)
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
|
|
||||||
|
@ -322,7 +322,7 @@ func TestHeaderREMatcher(t *testing.T) {
|
||||||
|
|
||||||
// set up the fake request and its Replacer
|
// set up the fake request and its Replacer
|
||||||
req := &http.Request{Header: tc.input, URL: new(url.URL)}
|
req := &http.Request{Header: tc.input, URL: new(url.URL)}
|
||||||
repl := &Replacer{req: req, resp: httptest.NewRecorder(), custom: make(map[string]string)}
|
repl := NewReplacer(req, httptest.NewRecorder())
|
||||||
ctx := context.WithValue(req.Context(), ReplacerCtxKey, repl)
|
ctx := context.WithValue(req.Context(), ReplacerCtxKey, repl)
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
|
|
||||||
|
|
|
@ -5,18 +5,31 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"bitbucket.org/lightcodelabs/caddy2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Replacer can replace values in strings based
|
// Replacer can replace values in strings based
|
||||||
// on a request and/or response writer. The zero
|
// on a request and/or response writer. The zero
|
||||||
// Replacer is not valid; it must be initialized
|
// Replacer is not valid; use NewReplacer() to
|
||||||
// within this package.
|
// initialize one.
|
||||||
type Replacer struct {
|
type Replacer struct {
|
||||||
req *http.Request
|
req *http.Request
|
||||||
resp http.ResponseWriter
|
resp http.ResponseWriter
|
||||||
custom map[string]string
|
custom map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewReplacer makes a new Replacer, initializing all necessary
|
||||||
|
// fields. The request and response writer are optional, but
|
||||||
|
// necessary for most replacements to work.
|
||||||
|
func NewReplacer(req *http.Request, rw http.ResponseWriter) *Replacer {
|
||||||
|
return &Replacer{
|
||||||
|
req: req,
|
||||||
|
resp: rw,
|
||||||
|
custom: make(map[string]string),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Map sets a custom variable mapping to a value.
|
// Map sets a custom variable mapping to a value.
|
||||||
func (r *Replacer) Map(variable, value string) {
|
func (r *Replacer) Map(variable, value string) {
|
||||||
r.custom[variable] = value
|
r.custom[variable] = value
|
||||||
|
@ -48,28 +61,6 @@ func (r *Replacer) replaceAll(input, empty string, mapping map[string]string) st
|
||||||
|
|
||||||
func (r *Replacer) defaults() map[string]string {
|
func (r *Replacer) defaults() map[string]string {
|
||||||
m := map[string]string{
|
m := map[string]string{
|
||||||
"request.host": func() string {
|
|
||||||
host, _, err := net.SplitHostPort(r.req.Host)
|
|
||||||
if err != nil {
|
|
||||||
return r.req.Host // OK; there probably was no port
|
|
||||||
}
|
|
||||||
return host
|
|
||||||
}(),
|
|
||||||
"request.hostport": r.req.Host, // may include both host and port
|
|
||||||
"request.method": r.req.Method,
|
|
||||||
"request.port": func() string {
|
|
||||||
// if there is no port, there will be an error; in
|
|
||||||
// that case, port is the empty string anyway
|
|
||||||
_, port, _ := net.SplitHostPort(r.req.Host)
|
|
||||||
return port
|
|
||||||
}(),
|
|
||||||
"request.scheme": func() string {
|
|
||||||
if r.req.TLS != nil {
|
|
||||||
return "https"
|
|
||||||
}
|
|
||||||
return "http"
|
|
||||||
}(),
|
|
||||||
"request.uri": r.req.URL.RequestURI(),
|
|
||||||
"system.hostname": func() string {
|
"system.hostname": func() string {
|
||||||
// OK if there is an error; just return empty string
|
// OK if there is an error; just return empty string
|
||||||
name, _ := os.Hostname()
|
name, _ := os.Hostname()
|
||||||
|
@ -77,22 +68,51 @@ func (r *Replacer) defaults() map[string]string {
|
||||||
}(),
|
}(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: why should header fields, cookies, and query params get special treatment like this?
|
if r.req != nil {
|
||||||
// maybe they should be scoped by words like "request.header." just like everything else.
|
m["request.host"] = func() string {
|
||||||
for field, vals := range r.req.Header {
|
host, _, err := net.SplitHostPort(r.req.Host)
|
||||||
m[">"+strings.ToLower(field)] = strings.Join(vals, ",")
|
if err != nil {
|
||||||
}
|
return r.req.Host // OK; there probably was no port
|
||||||
for field, vals := range r.resp.Header() {
|
}
|
||||||
m["<"+strings.ToLower(field)] = strings.Join(vals, ",")
|
return host
|
||||||
}
|
}()
|
||||||
for _, cookie := range r.req.Cookies() {
|
m["request.hostport"] = r.req.Host // may include both host and port
|
||||||
m["~"+cookie.Name] = cookie.Value
|
m["request.method"] = r.req.Method
|
||||||
}
|
m["request.port"] = func() string {
|
||||||
for param, vals := range r.req.URL.Query() {
|
// if there is no port, there will be an error; in
|
||||||
m["?"+param] = strings.Join(vals, ",")
|
// that case, port is the empty string anyway
|
||||||
|
_, port, _ := net.SplitHostPort(r.req.Host)
|
||||||
|
return port
|
||||||
|
}()
|
||||||
|
m["request.scheme"] = func() string {
|
||||||
|
if r.req.TLS != nil {
|
||||||
|
return "https"
|
||||||
|
}
|
||||||
|
return "http"
|
||||||
|
}()
|
||||||
|
m["request.uri"] = r.req.URL.RequestURI()
|
||||||
|
m["request.uri.path"] = r.req.URL.Path
|
||||||
|
|
||||||
|
// TODO: why should header fields, cookies, and query params get special treatment like this?
|
||||||
|
// maybe they should be scoped by words like "request.header." just like everything else.
|
||||||
|
for field, vals := range r.req.Header {
|
||||||
|
m[">"+strings.ToLower(field)] = strings.Join(vals, ",")
|
||||||
|
}
|
||||||
|
for field, vals := range r.resp.Header() {
|
||||||
|
m["<"+strings.ToLower(field)] = strings.Join(vals, ",")
|
||||||
|
}
|
||||||
|
for _, cookie := range r.req.Cookies() {
|
||||||
|
m["~"+cookie.Name] = cookie.Value
|
||||||
|
}
|
||||||
|
for param, vals := range r.req.URL.Query() {
|
||||||
|
m["?"+param] = strings.Join(vals, ",")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
const phOpen, phClose = "{", "}"
|
const phOpen, phClose = "{", "}"
|
||||||
|
|
||||||
|
// ReplacerCtxKey is the context key for the request's replacer.
|
||||||
|
const ReplacerCtxKey caddy2.CtxKey = "replacer"
|
||||||
|
|
|
@ -8,7 +8,10 @@ import (
|
||||||
"bitbucket.org/lightcodelabs/caddy2"
|
"bitbucket.org/lightcodelabs/caddy2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type serverRoute struct {
|
// ServerRoute represents a set of matching rules,
|
||||||
|
// middlewares, and a responder for handling HTTP
|
||||||
|
// requests.
|
||||||
|
type ServerRoute struct {
|
||||||
Matchers map[string]json.RawMessage `json:"match"`
|
Matchers map[string]json.RawMessage `json:"match"`
|
||||||
Apply []json.RawMessage `json:"apply"`
|
Apply []json.RawMessage `json:"apply"`
|
||||||
Respond json.RawMessage `json:"respond"`
|
Respond json.RawMessage `json:"respond"`
|
||||||
|
@ -21,9 +24,49 @@ type serverRoute struct {
|
||||||
responder Handler
|
responder Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
type routeList []serverRoute
|
// RouteList is a list of server routes that can
|
||||||
|
// create a middleware chain.
|
||||||
|
type RouteList []ServerRoute
|
||||||
|
|
||||||
func (routes routeList) buildMiddlewareChain(w http.ResponseWriter, r *http.Request) Handler {
|
// Provision sets up all the routes by loading the modules.
|
||||||
|
func (routes RouteList) Provision() error {
|
||||||
|
for i, route := range routes {
|
||||||
|
// matchers
|
||||||
|
for modName, rawMsg := range route.Matchers {
|
||||||
|
val, err := caddy2.LoadModule("http.matchers."+modName, rawMsg)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("loading matcher module '%s': %v", modName, err)
|
||||||
|
}
|
||||||
|
routes[i].matchers = append(routes[i].matchers, val.(RouteMatcher))
|
||||||
|
}
|
||||||
|
routes[i].Matchers = nil // allow GC to deallocate - TODO: Does this help?
|
||||||
|
|
||||||
|
// middleware
|
||||||
|
for j, rawMsg := range route.Apply {
|
||||||
|
mid, err := caddy2.LoadModuleInline("middleware", "http.middleware", rawMsg)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("loading middleware module in position %d: %v", j, err)
|
||||||
|
}
|
||||||
|
routes[i].middleware = append(routes[i].middleware, mid.(MiddlewareHandler))
|
||||||
|
}
|
||||||
|
routes[i].Apply = nil // allow GC to deallocate - TODO: Does this help?
|
||||||
|
|
||||||
|
// responder
|
||||||
|
if route.Respond != nil {
|
||||||
|
resp, err := caddy2.LoadModuleInline("responder", "http.responders", route.Respond)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("loading responder module: %v", err)
|
||||||
|
}
|
||||||
|
routes[i].responder = resp.(Handler)
|
||||||
|
}
|
||||||
|
routes[i].Respond = nil // allow GC to deallocate - TODO: Does this help?
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildHandlerChain creates a chain of handlers by
|
||||||
|
// applying all the matching routes.
|
||||||
|
func (routes RouteList) BuildHandlerChain(w http.ResponseWriter, r *http.Request) Handler {
|
||||||
if len(routes) == 0 {
|
if len(routes) == 0 {
|
||||||
return emptyHandler
|
return emptyHandler
|
||||||
}
|
}
|
||||||
|
@ -68,38 +111,3 @@ routeLoop:
|
||||||
|
|
||||||
return stack
|
return stack
|
||||||
}
|
}
|
||||||
|
|
||||||
func (routes routeList) setup() error {
|
|
||||||
for i, route := range routes {
|
|
||||||
// matchers
|
|
||||||
for modName, rawMsg := range route.Matchers {
|
|
||||||
val, err := caddy2.LoadModule("http.matchers."+modName, rawMsg)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("loading matcher module '%s': %v", modName, err)
|
|
||||||
}
|
|
||||||
routes[i].matchers = append(routes[i].matchers, val.(RouteMatcher))
|
|
||||||
}
|
|
||||||
routes[i].Matchers = nil // allow GC to deallocate - TODO: Does this help?
|
|
||||||
|
|
||||||
// middleware
|
|
||||||
for j, rawMsg := range route.Apply {
|
|
||||||
mid, err := caddy2.LoadModuleInline("middleware", "http.middleware", rawMsg)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("loading middleware module in position %d: %v", j, err)
|
|
||||||
}
|
|
||||||
routes[i].middleware = append(routes[i].middleware, mid.(MiddlewareHandler))
|
|
||||||
}
|
|
||||||
routes[i].Apply = nil // allow GC to deallocate - TODO: Does this help?
|
|
||||||
|
|
||||||
// responder
|
|
||||||
if route.Respond != nil {
|
|
||||||
resp, err := caddy2.LoadModuleInline("responder", "http.responders", route.Respond)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("loading responder module: %v", err)
|
|
||||||
}
|
|
||||||
routes[i].responder = resp.(Handler)
|
|
||||||
}
|
|
||||||
routes[i].Respond = nil // allow GC to deallocate - TODO: Does this help?
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static implements a simple responder for static responses.
|
// Static implements a simple responder for static responses.
|
||||||
// It is Caddy's default responder. TODO: Or is it?
|
|
||||||
type Static struct {
|
type Static struct {
|
||||||
StatusCode int `json:"status_code"`
|
StatusCode int `json:"status_code"`
|
||||||
Headers http.Header `json:"headers"`
|
Headers http.Header `json:"headers"`
|
||||||
|
|
|
@ -85,6 +85,9 @@ func (cp *ConnectionPolicy) buildStandardTLSConfig(handle caddy2.Handle) error {
|
||||||
NextProtos: cp.ALPN,
|
NextProtos: cp.ALPN,
|
||||||
PreferServerCipherSuites: true,
|
PreferServerCipherSuites: true,
|
||||||
GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||||
|
// TODO: Must fix https://github.com/mholt/caddy/issues/2588
|
||||||
|
// (allow customizing the selection of a very specific certificate
|
||||||
|
// based on the ClientHelloInfo)
|
||||||
cfgTpl, err := tlsApp.getConfigForName(hello.ServerName)
|
cfgTpl, err := tlsApp.getConfigForName(hello.ServerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("getting config for name %s: %v", hello.ServerName, err)
|
return nil, fmt.Errorf("getting config for name %s: %v", hello.ServerName, err)
|
||||||
|
|
Loading…
Reference in a new issue