diff --git a/ip/resolver/decoder/text.go b/ip/resolver/decoder/text.go new file mode 100644 index 0000000..e322988 --- /dev/null +++ b/ip/resolver/decoder/text.go @@ -0,0 +1,19 @@ +package decoder + +import ( + "bufio" + "io" + "strings" +) + +// Text decoder that expects the IP address +// to be on the first line of the response. +// The decoder will only trim trailing and leading whitespace. +func Text(r io.Reader) (string, error) { + line, err := bufio.NewReader(r).ReadString('\n') + if err == nil || err == io.EOF { + line = strings.TrimRight(line, "\r\n") + line = strings.TrimSpace(line) + } + return line, err +} diff --git a/ip/resolver/decoder/text_test.go b/ip/resolver/decoder/text_test.go new file mode 100644 index 0000000..a8c4350 --- /dev/null +++ b/ip/resolver/decoder/text_test.go @@ -0,0 +1,46 @@ +package decoder_test + +import ( + "io" + "strings" + "testing" + + "dnsupdater/ip/resolver/decoder" + + "github.com/stretchr/testify/assert" +) + +func TestService_Name(t *testing.T) { + tests := []struct { + name string + input string + expected string + expectError error + }{ + { + name: "simple", + input: "192.168.0.1", + expected: "192.168.0.1", + expectError: io.EOF, + }, + { + name: "whitespace", + input: " 192.168.0.1 ", + expected: "192.168.0.1", + expectError: io.EOF, + }, + { + name: "newline", + input: "192.168.0.1\r\nmore stuff", + expected: "192.168.0.1", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ip, err := decoder.Text(strings.NewReader(test.input)) + assert.ErrorIs(t, err, test.expectError) + assert.Equal(t, test.expected, ip) + }) + } +} diff --git a/ip/resolver/http/service.go b/ip/resolver/http/service.go index 5f5e6ec..cdb52bb 100644 --- a/ip/resolver/http/service.go +++ b/ip/resolver/http/service.go @@ -1,15 +1,14 @@ package http import ( - "bufio" "context" "io" "net" "net/http" - "strings" httputils "dnsupdater/http" "dnsupdater/ip/internal" + "dnsupdater/ip/resolver/decoder" ) type Decoder func(io.Reader) (string, error) @@ -32,14 +31,7 @@ func (s Service) Lookup(ctx context.Context) (net.IP, error) { } if s.Decoder == nil { - s.Decoder = func(r io.Reader) (string, error) { - line, err := bufio.NewReader(r).ReadString('\n') - if err == nil || err == io.EOF { - line = strings.TrimRight(line, "\r\n") - line = strings.TrimSpace(line) - } - return line, err - } + s.Decoder = decoder.Text } body, err := s.Decoder(resp.Body)