Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 11, 02:15 UTC
templates: preserve colons in humanize time layouts (#8215)
小莳 committed
Oct 14, 2026 at 15:45 UTC
af7620dcc8a3b2edeaa8adc5d2850115286f4658
2 files changed
+91
-1
modules/caddyhttp/templates/humanize_time_layout_test.go
new
+90
@@ -0,0 +1,90 @@
1
+// Copyright 2015 Matthew Holt and The Caddy Authors
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License");
4
+// you may not use this file except in compliance with the License.
5
+// You may obtain a copy of the License at
6
+//
7
+// http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS,
11
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+// See the License for the specific language governing permissions and
13
+// limitations under the License.
14
+
15
+package templates
16
+
17
+import (
18
+ "bytes"
19
+ "fmt"
20
+ "testing"
21
+ "time"
22
+
23
+ "github.com/dustin/go-humanize"
24
+)
25
+
26
+func TestHumanizeTimeLayouts(t *testing.T) {
27
+ for _, tc := range []struct {
28
+ name string
29
+ format string
30
+ input string
31
+ when time.Time
32
+ }{
33
+ {
34
+ name: "default",
35
+ format: "time",
36
+ input: "Sun, 02 Jan 2000 15:04:05 +0000",
37
+ when: time.Date(2000, time.January, 2, 15, 4, 5, 0, time.UTC),
38
+ },
39
+ {
40
+ name: "date only",
41
+ format: "time:2006-Jan-02",
42
+ input: "2000-Jan-02",
43
+ when: time.Date(2000, time.January, 2, 0, 0, 0, 0, time.UTC),
44
+ },
45
+ {
46
+ name: "RFC3339",
47
+ format: "time:" + time.RFC3339,
48
+ input: "2000-01-02T15:04:05Z",
49
+ when: time.Date(2000, time.January, 2, 15, 4, 5, 0, time.UTC),
50
+ },
51
+ {
52
+ name: "explicit default layout",
53
+ format: "time:" + time.RFC1123Z,
54
+ input: "Sun, 02 Jan 2000 15:04:05 +0000",
55
+ when: time.Date(2000, time.January, 2, 15, 4, 5, 0, time.UTC),
56
+ },
57
+ {
58
+ name: "RFC3339 with time zone offset",
59
+ format: "time:" + time.RFC3339,
60
+ input: "2000-01-02T17:34:05+02:30",
61
+ when: time.Date(2000, time.January, 2, 15, 4, 5, 0, time.UTC),
62
+ },
63
+ {
64
+ name: "custom date and time",
65
+ format: "time:2006-01-02 15:04:05",
66
+ input: "2000-01-02 15:04:05",
67
+ when: time.Date(2000, time.January, 2, 15, 4, 5, 0, time.UTC),
68
+ },
69
+ } {
70
+ t.Run(tc.name, func(t *testing.T) {
71
+ c := TemplateContext{}
72
+ buf := bytes.NewBufferString(fmt.Sprintf("{{humanize %q %q}}", tc.format, tc.input))
73
+ wantBefore := humanize.Time(tc.when)
74
+ if err := c.executeTemplateInBuffer("test", buf); err != nil {
75
+ t.Fatalf("rendering humanized time: %v", err)
76
+ }
77
+ wantAfter := humanize.Time(tc.when)
78
+ if got := buf.String(); got != wantBefore && got != wantAfter {
79
+ t.Errorf("expected %q or %q, got %q", wantBefore, wantAfter, got)
80
+ }
81
+ })
82
+ }
83
+}
84
+
85
+func TestHumanizeInvalidTimeLayoutData(t *testing.T) {
86
+ c := TemplateContext{}
87
+ if _, err := c.funcHumanize("time:"+time.RFC3339, "not a timestamp"); err == nil {
88
+ t.Fatal("expected invalid timestamp to return an error")
89
+ }
90
+}
modules/caddyhttp/templates/tplcontext.go
+1
-1
@@ -490,7 +490,7 @@ func (c TemplateContext) funcHTTPError(statusCode int) (bool, error) {
490
func (c TemplateContext) funcHumanize(formatType, data string) (string, error) {
491
// The format type can optionally be followed
492
// by a colon to provide arguments for the format
493
- parts := strings.Split(formatType, ":")
493
+ parts := strings.SplitN(formatType, ":", 2)
494
495
switch parts[0] {
496
case "size":