rule.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. package ingress
  2. import (
  3. "encoding/json"
  4. "regexp"
  5. "strings"
  6. "github.com/cloudflare/cloudflared/ingress/middleware"
  7. )
  8. // Rule routes traffic from a hostname/path on the public internet to the
  9. // service running on the given URL.
  10. type Rule struct {
  11. // Requests for this hostname will be proxied to this rule's service.
  12. Hostname string `json:"hostname"`
  13. // punycodeHostname is an additional optional hostname converted to punycode.
  14. punycodeHostname string
  15. // Path is an optional regex that can specify path-driven ingress rules.
  16. Path *Regexp `json:"path"`
  17. // A (probably local) address. Requests for a hostname which matches this
  18. // rule's hostname pattern will be proxied to the service running on this
  19. // address.
  20. Service OriginService `json:"service"`
  21. // Handlers is a list of functions that acts as a middleware during ProxyHTTP
  22. Handlers []middleware.Handler
  23. // Configure the request cloudflared sends to this specific origin.
  24. Config OriginRequestConfig `json:"originRequest"`
  25. }
  26. // MultiLineString is for outputting rules in a human-friendly way when Cloudflared
  27. // is used as a CLI tool (not as a daemon).
  28. func (r Rule) MultiLineString() string {
  29. var out strings.Builder
  30. if r.Hostname != "" {
  31. out.WriteString("\thostname: ")
  32. out.WriteString(r.Hostname)
  33. out.WriteRune('\n')
  34. }
  35. if r.Path != nil && r.Path.Regexp != nil {
  36. out.WriteString("\tpath: ")
  37. out.WriteString(r.Path.Regexp.String())
  38. out.WriteRune('\n')
  39. }
  40. out.WriteString("\tservice: ")
  41. out.WriteString(r.Service.String())
  42. return out.String()
  43. }
  44. // Matches checks if the rule matches a given hostname/path combination.
  45. func (r *Rule) Matches(hostname, path string) bool {
  46. hostMatch := false
  47. if r.Hostname == "" || r.Hostname == "*" {
  48. hostMatch = true
  49. } else {
  50. hostMatch = matchHost(r.Hostname, hostname)
  51. }
  52. punycodeHostMatch := false
  53. if r.punycodeHostname != "" {
  54. punycodeHostMatch = matchHost(r.punycodeHostname, hostname)
  55. }
  56. pathMatch := r.Path == nil || r.Path.Regexp == nil || r.Path.Regexp.MatchString(path)
  57. return (hostMatch || punycodeHostMatch) && pathMatch
  58. }
  59. // Regexp adds unmarshalling from json for regexp.Regexp
  60. type Regexp struct {
  61. *regexp.Regexp
  62. }
  63. func (r *Regexp) MarshalJSON() ([]byte, error) {
  64. if r.Regexp == nil {
  65. return json.Marshal(nil)
  66. }
  67. return json.Marshal(r.Regexp.String())
  68. }