cloudflared-mirror/ingress/rule.go

68 lines
2.0 KiB
Go

package ingress
import (
"encoding/json"
"regexp"
"strings"
)
// 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.
Hostname string `json:"hostname"`
// Path is an optional regex that can specify path-driven ingress rules.
Path *Regexp `json:"path"`
// 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.
Service OriginService `json:"service"`
// Location is an optional string specifying the Service path, which
// replaces the first subdirectory of the Hostname path
Location string `json:"location"`
// Configure the request cloudflared sends to this specific origin.
Config OriginRequestConfig `json:"originRequest"`
}
// 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')
}
if r.Path != nil && r.Path.Regexp != nil {
out.WriteString("\tpath: ")
out.WriteString(r.Path.Regexp.String())
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 {
hostMatch := r.Hostname == "" || r.Hostname == "*" || matchHost(r.Hostname, hostname)
pathMatch := r.Path == nil || r.Path.Regexp == nil || r.Path.Regexp.MatchString(path)
return hostMatch && pathMatch
}
// 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())
}