From 27ecc7f384bbfc98b28dc73881968897fb8c9a8a Mon Sep 17 00:00:00 2001 From: dev Date: Wed, 3 Apr 2019 11:47:27 -0400 Subject: Protocol and Caddyscript matchers * Added matcher to determine what protocol the request is being made by - grpc, tls, http * Added ability to run caddyscript in a matcher to evaluate the http request * Added TLS field to caddyscript request time * Added a library to manipulate and compare a new caddyscript time type * Library for regex in starlark --- modules/caddyhttp/caddyhttp.go | 2 -- modules/caddyhttp/matchers.go | 62 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 10 deletions(-) (limited to 'modules/caddyhttp') diff --git a/modules/caddyhttp/caddyhttp.go b/modules/caddyhttp/caddyhttp.go index 059af62..179ad50 100644 --- a/modules/caddyhttp/caddyhttp.go +++ b/modules/caddyhttp/caddyhttp.go @@ -32,9 +32,7 @@ type httpModuleConfig struct { func (hc *httpModuleConfig) Run() error { // TODO: Either prevent overlapping listeners on different servers, or combine them into one - // TODO: A way to loop requests back through, so have them start the matching over again, but keeping any mutations - for _, srv := range hc.Servers { // set up the routes for i, route := range srv.Routes { diff --git a/modules/caddyhttp/matchers.go b/modules/caddyhttp/matchers.go index 59f1838..ab179d8 100644 --- a/modules/caddyhttp/matchers.go +++ b/modules/caddyhttp/matchers.go @@ -1,10 +1,24 @@ package caddyhttp import ( + "log" "net/http" "strings" "bitbucket.org/lightcodelabs/caddy2" + "bitbucket.org/lightcodelabs/caddy2/internal/caddyscript" + "go.starlark.net/starlark" +) + +// TODO: Matchers should probably support regex of some sort... performance trade-offs? +type ( + matchHost []string + matchPath []string + matchMethod []string + matchQuery map[string][]string + matchHeader map[string][]string + matchProtocol string + matchScript string ) func init() { @@ -28,17 +42,47 @@ func init() { Name: "http.matchers.header", New: func() (interface{}, error) { return matchHeader{}, nil }, }) + caddy2.RegisterModule(caddy2.Module{ + Name: "http.matchers.protocol", + New: func() (interface{}, error) { return new(matchProtocol), nil }, + }) + caddy2.RegisterModule(caddy2.Module{ + Name: "http.matchers.caddyscript", + New: func() (interface{}, error) { return new(matchScript), nil }, + }) } -// TODO: Matchers should probably support regex of some sort... performance trade-offs? +func (m matchScript) Match(r *http.Request) bool { + input := string(m) + thread := new(starlark.Thread) + env := caddyscript.MatcherEnv(r) + val, err := starlark.Eval(thread, "", input, env) + if err != nil { + log.Printf("caddyscript for matcher is invalid: attempting to evaluate expression `%v` error `%v`", input, err) + return false + } -type ( - matchHost []string - matchPath []string - matchMethod []string - matchQuery map[string][]string - matchHeader map[string][]string -) + return val.String() == "True" +} + +func (m matchProtocol) Match(r *http.Request) bool { + switch string(m) { + case "grpc": + if r.Header.Get("content-type") == "application/grpc" { + return true + } + case "https": + if r.TLS != nil { + return true + } + case "http": + if r.TLS == nil { + return true + } + } + + return false +} func (m matchHost) Match(r *http.Request) bool { for _, host := range m { @@ -99,4 +143,6 @@ var ( _ RouteMatcher = matchMethod{} _ RouteMatcher = matchQuery{} _ RouteMatcher = matchHeader{} + _ RouteMatcher = new(matchProtocol) + _ RouteMatcher = new(matchScript) ) -- cgit v1.2.3