@marcel91200 / caddy Mirror · read-only / commits / af7620dc
Fork 0

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":