From f38ca8ab55ab0681a2dd7f98e87abf4f40d7dcb7 Mon Sep 17 00:00:00 2001 From: Dylan Carney Date: Tue, 4 Jun 2019 14:53:19 -0700 Subject: [PATCH 1/2] Changes regex used in nginx log_format parser to allow for newlines/trailing whitespace. --- parser.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/parser.go b/parser.go index 6e4d950..40ac0c4 100644 --- a/parser.go +++ b/parser.go @@ -68,7 +68,7 @@ func (parser *Parser) ParseString(line string) (entry *Entry, err error) { // the given log format. func NewNginxParser(conf io.Reader, name string) (parser *Parser, err error) { scanner := bufio.NewScanner(conf) - re := regexp.MustCompile(fmt.Sprintf(`^\s*log_format\s+%v\s+(.+)\s*$`, name)) + re := regexp.MustCompile(fmt.Sprintf(`^\s*log_format\s+%s\s*(.*)\s*$`, name)) found := false var format string for scanner.Scan() { @@ -81,13 +81,18 @@ func NewNginxParser(conf io.Reader, name string) (parser *Parser, err error) { continue } found = true + // remove the "log_format " from the line, leaving only the (potential) + // formatting directives. line = formatDef[1] } else { line = scanner.Text() } - // Look for a definition end + // Look for the end of the definition re = regexp.MustCompile(`^\s*(.*?)\s*(;|$)`) lineSplit := re.FindStringSubmatch(line) + + // If there are any formatting directives on this line, + // add them to the format string if l := len(lineSplit[1]); l > 2 { format += lineSplit[1][1 : l-1] } From 63c893c6c220706bd3f5e77472d61f0503b3d9af Mon Sep 17 00:00:00 2001 From: Dylan Carney Date: Tue, 4 Jun 2019 14:54:03 -0700 Subject: [PATCH 2/2] Adds additional test cases for nginx log_format parser --- parser_test.go | 44 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/parser_test.go b/parser_test.go index 90e7007..195366a 100644 --- a/parser_test.go +++ b/parser_test.go @@ -81,8 +81,9 @@ func TestParser(t *testing.T) { Convey("Nginx format parser", func() { expected := "$remote_addr - $remote_user [$time_local] \"$request\" $status \"$http_referer\" \"$http_user_agent\"" - conf := strings.NewReader(` - http { + + testCases := []string{ + `http { include conf/mime.types; log_format minimal '$remote_addr [$time_local] "$request"'; log_format main '$remote_addr - $remote_user [$time_local] ' @@ -92,11 +93,40 @@ func TestParser(t *testing.T) { '"$request" $status $bytes_sent ' '"$http_referer" "$http_user_agent" ' '"$http_range" "$sent_http_content_range"'; - } - `) - parser, err := NewNginxParser(conf, "main") - So(err, ShouldBeNil) - So(parser.format, ShouldEqual, expected) + }`, + + // Note that the line containing the log_format directive ("log_format main") has NO trailing whitespace. + // This is perfectly valid nginx config. + `http { + include conf/mime.types; + log_format minimal '$remote_addr [$time_local] "$request"'; + log_format main +'$remote_addr - $remote_user [$time_local] ' +'"$request" $status ' +'"$http_referer" "$http_user_agent"'; + }`, + + // Similar to the above, but contains both trailing whitespace and empty lines in the log_format def + // This is perfectly valid nginx config. + ` + http { + include conf/mime.types; + log_format minimal '$remote_addr [$time_local] "$request"'; + log_format main + +'$remote_addr - $remote_user [$time_local] ' + +'"$request" $status ' + +'"$http_referer" "$http_user_agent"'; + }`, + } + + for _, conf := range testCases { + parser, err := NewNginxParser(strings.NewReader(conf), "main") + So(err, ShouldBeNil) + So(parser.format, ShouldEqual, expected) + } }) }) }