Skip to content
Permalink
Browse files

(record): Expose the record parser

  • Loading branch information
erbesharat committed Dec 4, 2019
1 parent d9def10 commit 3381fedf6a86928eb1315301a2b3c968ff1cd0ef
Showing with 25 additions and 23 deletions.
  1. +5 −4 path.go
  2. +14 −13 record.go
  3. +3 −3 record_test.go
  4. +2 −2 setup.go
  5. +1 −1 setup_test.go
@@ -144,8 +144,9 @@ func (p *Path) specificMatch(regexes RegexRecords) (*record, error) {
// Add the most specific match's path slice to the request context to use in placeholders
*p.req = *p.req.WithContext(context.WithValue(p.req.Context(), "regexMatches", recordMatch[keys[len(keys)-1]].Submatches))

rec := record{}
if err := rec.Parse(recordMatch[keys[len(keys)-1]].TXT, p.rw, p.req, p.c); err != nil {
var rec record
var err error
if rec, err = ParseRecord(recordMatch[keys[len(keys)-1]].TXT, p.rw, p.req, p.c); err != nil {
return nil, fmt.Errorf("Could not parse record: %s", err)
}

@@ -292,8 +293,8 @@ func getFinalRecord(zone string, from int, c Config, w http.ResponseWriter, r *h
}

txts[0], err = parsePlaceholders(txts[0], r, pathSlice)
rec := record{}
if err = rec.Parse(txts[0], w, r, c); err != nil {
var rec record
if rec, err = ParseRecord(txts[0], w, r, c); err != nil {
return rec, fmt.Errorf("could not parse record: %s", err)
}

@@ -61,8 +61,8 @@ func getRecord(host string, c Config, w http.ResponseWriter, r *http.Request) (r
return record{}, fmt.Errorf("could not parse TXT record with %d records", len(txts))
}

rec := record{}
if err = rec.Parse(txts[0], w, r, c); err != nil {
var rec record
if rec, err = ParseRecord(txts[0], w, r, c); err != nil {
return rec, fmt.Errorf("could not parse record: %s", err)
}

@@ -75,23 +75,24 @@ func getRecord(host string, c Config, w http.ResponseWriter, r *http.Request) (r
// a TXTDirect record struct instance.
// It will return an error if the DNS TXT record is not standard or
// if the record type is not enabled in the TXTDirect's config.
func (r *record) Parse(str string, w http.ResponseWriter, req *http.Request, c Config) error {
func ParseRecord(str string, w http.ResponseWriter, req *http.Request, c Config) (record, error) {
r := record{}
s := strings.Split(str, ";")
for _, l := range s {
switch {
case strings.HasPrefix(l, "code="):
l = strings.TrimPrefix(l, "code=")
i, err := strconv.Atoi(l)
if err != nil {
return fmt.Errorf("could not parse status code: %s", err)
return record{}, fmt.Errorf("could not parse status code: %s", err)
}
r.Code = i

case strings.HasPrefix(l, "from="):
l = strings.TrimPrefix(l, "from=")
l, err := parsePlaceholders(l, req, []string{})
if err != nil {
return err
return record{}, err
}
r.From = l

@@ -103,7 +104,7 @@ func (r *record) Parse(str string, w http.ResponseWriter, req *http.Request, c C
l, err := strconv.ParseBool(strings.TrimPrefix(l, "ref="))
if err != nil {
fallback(w, req, "global", http.StatusMovedPermanently, c)
return err
return record{}, err
}
r.Ref = l

@@ -116,7 +117,7 @@ func (r *record) Parse(str string, w http.ResponseWriter, req *http.Request, c C
l = strings.TrimPrefix(l, "to=")
l, err := parsePlaceholders(l, req, []string{})
if err != nil {
return err
return record{}, err
}
l = ParseURI(l, w, req, c)
r.To = l
@@ -129,7 +130,7 @@ func (r *record) Parse(str string, w http.ResponseWriter, req *http.Request, c C
l = strings.TrimPrefix(l, "v=")
r.Version = l
if r.Version != "txtv0" {
return fmt.Errorf("unhandled version '%s'", r.Version)
return record{}, fmt.Errorf("unhandled version '%s'", r.Version)
}
log.Print("WARN: txtv0 is not suitable for production")

@@ -145,15 +146,15 @@ func (r *record) Parse(str string, w http.ResponseWriter, req *http.Request, c C
default:
tuple := strings.Split(l, "=")
if len(tuple) != 2 {
return fmt.Errorf("arbitrary data not allowed")
return record{}, fmt.Errorf("arbitrary data not allowed")
}
continue
}
if len(l) > 255 {
return fmt.Errorf("TXT record cannot exceed the maximum of 255 characters")
return record{}, fmt.Errorf("TXT record cannot exceed the maximum of 255 characters")
}
if r.Type == "dockerv2" && r.To == "" {
return fmt.Errorf("[txtdirect]: to= field is required in dockerv2 type")
return record{}, fmt.Errorf("[txtdirect]: to= field is required in dockerv2 type")
}
}

@@ -166,10 +167,10 @@ func (r *record) Parse(str string, w http.ResponseWriter, req *http.Request, c C
}

if !contains(c.Enable, r.Type) {
return fmt.Errorf("%s type is not enabled in configuration", r.Type)
return record{}, fmt.Errorf("%s type is not enabled in configuration", r.Type)
}

return nil
return r, nil
}

// Adds the given record to the request's context with "records" key.
@@ -21,7 +21,7 @@ import (
"testing"
)

func TestParse(t *testing.T) {
func TestParseRecord(t *testing.T) {
tests := []struct {
txtRecord string
expected record
@@ -158,13 +158,13 @@ func TestParse(t *testing.T) {
}

for i, test := range tests {
r := record{}
var r record
c := Config{
Enable: []string{test.expected.Type},
}
req, _ := http.NewRequest("GET", "http://example.com?url=https://example.com/testing", nil)
w := httptest.NewRecorder()
err := r.Parse(test.txtRecord, w, req, c)
r, err := ParseRecord(test.txtRecord, w, req, c)

if err != nil {
if test.err == nil || !strings.HasPrefix(err.Error(), test.err.Error()) {
@@ -44,7 +44,7 @@ func init() {

var allOptions = []string{"host", "path", "gometa", "www"}

func parse(c *caddy.Controller) (Config, error) {
func ParseConfig(c *caddy.Controller) (Config, error) {
var enable []string
var redirect string
var resolver string
@@ -160,7 +160,7 @@ func parse(c *caddy.Controller) (Config, error) {
}

func setup(c *caddy.Controller) error {
config, err := parse(c)
config, err := ParseConfig(c)
if err != nil {
return err
}
@@ -300,7 +300,7 @@ func TestCaddyParse(t *testing.T) {
for i, test := range tests {
log.Println(log.Flags())
c := caddy.NewTestController("http", test.input)
conf, err := parse(c)
conf, err := ParseConfig(c)
if !test.shouldErr && err != nil {
t.Errorf("Test %d: Unexpected error %s", i, err)
continue

0 comments on commit 3381fed

Please sign in to comment.
You can’t perform that action at this time.