2020-10-15 21:41:03 +00:00
|
|
|
package ingress
|
|
|
|
|
|
|
|
import (
|
2022-03-14 17:51:10 +00:00
|
|
|
"encoding/json"
|
2020-10-15 21:41:03 +00:00
|
|
|
"regexp"
|
|
|
|
"strings"
|
2022-09-22 13:04:47 +00:00
|
|
|
|
|
|
|
"github.com/cloudflare/cloudflared/ingress/middleware"
|
2020-10-15 21:41:03 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Rule routes traffic from a hostname/path on the public internet to the
|
|
|
|
// service running on the given URL.
|
|
|
|
type Rule struct {
|
|
|
|
// Requests for this hostname will be proxied to this rule's service.
|
2022-03-14 17:51:10 +00:00
|
|
|
Hostname string `json:"hostname"`
|
2020-10-15 21:41:03 +00:00
|
|
|
|
2022-09-22 23:19:06 +00:00
|
|
|
// punycodeHostname is an additional optional hostname converted to punycode.
|
|
|
|
punycodeHostname string
|
|
|
|
|
2020-10-15 21:41:03 +00:00
|
|
|
// Path is an optional regex that can specify path-driven ingress rules.
|
2022-03-14 17:51:10 +00:00
|
|
|
Path *Regexp `json:"path"`
|
2020-10-15 21:41:03 +00:00
|
|
|
|
2022-09-29 16:32:59 +00:00
|
|
|
// PathReplacement is an optional regexp replacement string for Path,
|
|
|
|
// that gets sent to the Service
|
|
|
|
PathReplacement string `json:"pathReplacement"`
|
|
|
|
|
2020-10-15 21:41:03 +00:00
|
|
|
// A (probably local) address. Requests for a hostname which matches this
|
|
|
|
// rule's hostname pattern will be proxied to the service running on this
|
|
|
|
// address.
|
2022-03-14 17:51:10 +00:00
|
|
|
Service OriginService `json:"service"`
|
2020-10-15 21:41:03 +00:00
|
|
|
|
2022-09-21 14:17:44 +00:00
|
|
|
// Handlers is a list of functions that acts as a middleware during ProxyHTTP
|
2022-09-22 13:04:47 +00:00
|
|
|
Handlers []middleware.Handler
|
2022-09-21 14:17:44 +00:00
|
|
|
|
2020-10-15 21:41:03 +00:00
|
|
|
// Configure the request cloudflared sends to this specific origin.
|
2022-03-14 17:51:10 +00:00
|
|
|
Config OriginRequestConfig `json:"originRequest"`
|
2020-10-15 21:41:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// MultiLineString is for outputting rules in a human-friendly way when Cloudflared
|
|
|
|
// is used as a CLI tool (not as a daemon).
|
|
|
|
func (r Rule) MultiLineString() string {
|
|
|
|
var out strings.Builder
|
|
|
|
if r.Hostname != "" {
|
|
|
|
out.WriteString("\thostname: ")
|
|
|
|
out.WriteString(r.Hostname)
|
|
|
|
out.WriteRune('\n')
|
|
|
|
}
|
2022-03-14 17:51:10 +00:00
|
|
|
if r.Path != nil && r.Path.Regexp != nil {
|
2020-10-15 21:41:03 +00:00
|
|
|
out.WriteString("\tpath: ")
|
2022-03-14 17:51:10 +00:00
|
|
|
out.WriteString(r.Path.Regexp.String())
|
2020-10-15 21:41:03 +00:00
|
|
|
out.WriteRune('\n')
|
|
|
|
}
|
|
|
|
out.WriteString("\tservice: ")
|
|
|
|
out.WriteString(r.Service.String())
|
|
|
|
return out.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Matches checks if the rule matches a given hostname/path combination.
|
|
|
|
func (r *Rule) Matches(hostname, path string) bool {
|
2022-09-22 23:19:06 +00:00
|
|
|
hostMatch := false
|
|
|
|
if r.Hostname == "" || r.Hostname == "*" {
|
|
|
|
hostMatch = true
|
|
|
|
} else {
|
|
|
|
hostMatch = matchHost(r.Hostname, hostname)
|
|
|
|
}
|
|
|
|
punycodeHostMatch := false
|
|
|
|
if r.punycodeHostname != "" {
|
|
|
|
punycodeHostMatch = matchHost(r.punycodeHostname, hostname)
|
|
|
|
}
|
2022-03-14 17:51:10 +00:00
|
|
|
pathMatch := r.Path == nil || r.Path.Regexp == nil || r.Path.Regexp.MatchString(path)
|
2022-09-22 23:19:06 +00:00
|
|
|
return (hostMatch || punycodeHostMatch) && pathMatch
|
2020-10-15 21:41:03 +00:00
|
|
|
}
|
2022-03-14 17:51:10 +00:00
|
|
|
|
|
|
|
// Regexp adds unmarshalling from json for regexp.Regexp
|
|
|
|
type Regexp struct {
|
|
|
|
*regexp.Regexp
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *Regexp) MarshalJSON() ([]byte, error) {
|
|
|
|
if r.Regexp == nil {
|
|
|
|
return json.Marshal(nil)
|
|
|
|
}
|
|
|
|
return json.Marshal(r.Regexp.String())
|
|
|
|
}
|