Skip to content

Commit

Permalink
(record): Expose the record parser
Browse files Browse the repository at this point in the history
  • Loading branch information
erbesharat committed Dec 4, 2019
1 parent d9def10 commit 3381fed
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 23 deletions.
9 changes: 5 additions & 4 deletions path.go
Expand Up @@ -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 // 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)) *p.req = *p.req.WithContext(context.WithValue(p.req.Context(), "regexMatches", recordMatch[keys[len(keys)-1]].Submatches))


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


Expand Down Expand Up @@ -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) txts[0], err = parsePlaceholders(txts[0], r, pathSlice)
rec := record{} var rec record
if err = rec.Parse(txts[0], w, r, c); err != nil { if rec, err = ParseRecord(txts[0], w, r, c); err != nil {
return rec, fmt.Errorf("could not parse record: %s", err) return rec, fmt.Errorf("could not parse record: %s", err)
} }


Expand Down
27 changes: 14 additions & 13 deletions record.go
Expand Up @@ -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)) return record{}, fmt.Errorf("could not parse TXT record with %d records", len(txts))
} }


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


Expand All @@ -75,23 +75,24 @@ func getRecord(host string, c Config, w http.ResponseWriter, r *http.Request) (r
// a TXTDirect record struct instance. // a TXTDirect record struct instance.
// It will return an error if the DNS TXT record is not standard or // 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. // 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, ";") s := strings.Split(str, ";")
for _, l := range s { for _, l := range s {
switch { switch {
case strings.HasPrefix(l, "code="): case strings.HasPrefix(l, "code="):
l = strings.TrimPrefix(l, "code=") l = strings.TrimPrefix(l, "code=")
i, err := strconv.Atoi(l) i, err := strconv.Atoi(l)
if err != nil { 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 r.Code = i


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


Expand All @@ -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=")) l, err := strconv.ParseBool(strings.TrimPrefix(l, "ref="))
if err != nil { if err != nil {
fallback(w, req, "global", http.StatusMovedPermanently, c) fallback(w, req, "global", http.StatusMovedPermanently, c)
return err return record{}, err
} }
r.Ref = l r.Ref = l


Expand All @@ -116,7 +117,7 @@ func (r *record) Parse(str string, w http.ResponseWriter, req *http.Request, c C
l = strings.TrimPrefix(l, "to=") l = strings.TrimPrefix(l, "to=")
l, err := parsePlaceholders(l, req, []string{}) l, err := parsePlaceholders(l, req, []string{})
if err != nil { if err != nil {
return err return record{}, err
} }
l = ParseURI(l, w, req, c) l = ParseURI(l, w, req, c)
r.To = l r.To = l
Expand All @@ -129,7 +130,7 @@ func (r *record) Parse(str string, w http.ResponseWriter, req *http.Request, c C
l = strings.TrimPrefix(l, "v=") l = strings.TrimPrefix(l, "v=")
r.Version = l r.Version = l
if r.Version != "txtv0" { 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") log.Print("WARN: txtv0 is not suitable for production")


Expand All @@ -145,15 +146,15 @@ func (r *record) Parse(str string, w http.ResponseWriter, req *http.Request, c C
default: default:
tuple := strings.Split(l, "=") tuple := strings.Split(l, "=")
if len(tuple) != 2 { if len(tuple) != 2 {
return fmt.Errorf("arbitrary data not allowed") return record{}, fmt.Errorf("arbitrary data not allowed")
} }
continue continue
} }
if len(l) > 255 { 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 == "" { 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")
} }
} }


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


if !contains(c.Enable, r.Type) { 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. // Adds the given record to the request's context with "records" key.
Expand Down
6 changes: 3 additions & 3 deletions record_test.go
Expand Up @@ -21,7 +21,7 @@ import (
"testing" "testing"
) )


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


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


if err != nil { if err != nil {
if test.err == nil || !strings.HasPrefix(err.Error(), test.err.Error()) { if test.err == nil || !strings.HasPrefix(err.Error(), test.err.Error()) {
Expand Down
4 changes: 2 additions & 2 deletions setup.go
Expand Up @@ -44,7 +44,7 @@ func init() {


var allOptions = []string{"host", "path", "gometa", "www"} 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 enable []string
var redirect string var redirect string
var resolver string var resolver string
Expand Down Expand Up @@ -160,7 +160,7 @@ func parse(c *caddy.Controller) (Config, error) {
} }


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

0 comments on commit 3381fed

Please sign in to comment.