From 8464020f7c87451068ad8984b23fdbaab5898bee Mon Sep 17 00:00:00 2001 From: M-A Date: Sat, 14 Jan 2017 17:54:27 -0500 Subject: [PATCH] Add {whenISO} to record timestamp in ISO 8601 format in UTC. (#1353) * Add {whenISO} to record timestamp in ISO 8601 format in UTC. ISO 8601 is the standard time format and is easy to parse. This change assumes users desiring ISO 8016 generally prefer UTC for simplicity. This results in {whenISO} to be significantly shorter than {when}: {when} = "02/Jan/2006:15:04:05 +0000" {whenISO} = "2006-01-02T15:04:12Z" Add unit test to verify both, as there was no unit test for {when}. * Rename {whenISO} to {when_iso} --- caddyhttp/httpserver/replacer.go | 7 ++++++- caddyhttp/httpserver/replacer_test.go | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/caddyhttp/httpserver/replacer.go b/caddyhttp/httpserver/replacer.go index b112e8354..0278eb510 100644 --- a/caddyhttp/httpserver/replacer.go +++ b/caddyhttp/httpserver/replacer.go @@ -23,6 +23,8 @@ var requestReplacer = strings.NewReplacer( "\n", "\\n", ) +var now = time.Now + // Replacer is a type which can replace placeholder // substrings in a string with actual values from a // http.Request and ResponseRecorder. Always use @@ -249,7 +251,9 @@ func (r *replacer) getSubstitution(key string) string { case "{uri_escaped}": return url.QueryEscape(r.request.URL.RequestURI()) case "{when}": - return time.Now().Format(timeFormat) + return now().Format(timeFormat) + case "{when_iso}": + return now().UTC().Format(timeFormatISOUTC) case "{file}": _, file := path.Split(r.request.URL.Path) return file @@ -311,6 +315,7 @@ func (r *replacer) Set(key, value string) { const ( timeFormat = "02/Jan/2006:15:04:05 -0700" + timeFormatISOUTC = "2006-01-02T15:04:05Z" // ISO 8601 with timezone to be assumed as UTC headerContentType = "Content-Type" contentTypeJSON = "application/json" contentTypeXML = "application/xml" diff --git a/caddyhttp/httpserver/replacer_test.go b/caddyhttp/httpserver/replacer_test.go index fb5535496..e03aed81c 100644 --- a/caddyhttp/httpserver/replacer_test.go +++ b/caddyhttp/httpserver/replacer_test.go @@ -53,6 +53,13 @@ func TestReplace(t *testing.T) { t.Fatal("Failed to determine hostname\n") } + old := now + now = func() time.Time { + return time.Date(2006, 1, 2, 15, 4, 5, 02, time.FixedZone("hardcoded", -7)) + } + defer func() { + now = old + }() testCases := []struct { template string expect string @@ -61,6 +68,8 @@ func TestReplace(t *testing.T) { {"This host is {host}.", "This host is localhost."}, {"This request method is {method}.", "This request method is POST."}, {"The response status is {status}.", "The response status is 200."}, + {"{when}", "02/Jan/2006:15:04:05 +0000"}, + {"{when_iso}", "2006-01-02T15:04:12Z"}, {"The Custom header is {>Custom}.", "The Custom header is foobarbaz."}, {"The CustomAdd header is {>CustomAdd}.", "The CustomAdd header is caddy."}, {"The request is {request}.", "The request is POST / HTTP/1.1\\r\\nHost: localhost\\r\\nCustom: foobarbaz\\r\\nCustomadd: caddy\\r\\nShorterval: 1\\r\\n\\r\\n."},