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, 08:30 UTC
caddyconfig: cancel HTTP loader requests with context (#7918)
cui fliter committed
Aug 10, 2026 at 13:12 UTC
7d26d34ec6e3360cd4668224ee7d632fcaa465d3
2 files changed
+77
-1
caddyconfig/httploader.go
+1
-1
@@ -95,7 +95,7 @@ func (hl HTTPLoader) LoadConfig(ctx caddy.Context) ([]byte, error) {
95
}
96
97
url := repl.ReplaceAll(hl.URL, "")
98
- req, err := http.NewRequest(method, url, nil)
98
+ req, err := http.NewRequestWithContext(ctx, method, url, nil)
99
if err != nil {
100
return nil, err
101
}
caddyconfig/httploader_test.go
new
+76
@@ -0,0 +1,76 @@
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 caddyconfig
16
+
17
+import (
18
+ "context"
19
+ "errors"
20
+ "net/http"
21
+ "net/http/httptest"
22
+ "testing"
23
+ "time"
24
+
25
+ "github.com/caddyserver/caddy/v2"
26
+)
27
+
28
+func TestHTTPLoaderLoadConfigRespectsContextCancellation(t *testing.T) {
29
+ requestStarted := make(chan struct{})
30
+ requestCanceled := make(chan struct{})
31
+ stopServer := make(chan struct{})
32
+ srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
33
+ close(requestStarted)
34
+ select {
35
+ case <-r.Context().Done():
36
+ close(requestCanceled)
37
+ case <-stopServer:
38
+ }
39
+ }))
40
+ t.Cleanup(func() {
41
+ close(stopServer)
42
+ srv.Close()
43
+ })
44
+
45
+ ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()})
46
+ loader := HTTPLoader{URL: srv.URL}
47
+
48
+ errCh := make(chan error, 1)
49
+ go func() {
50
+ _, err := loader.LoadConfig(ctx)
51
+ errCh <- err
52
+ }()
53
+
54
+ select {
55
+ case <-requestStarted:
56
+ case <-time.After(time.Second):
57
+ t.Fatal("request did not reach test server")
58
+ }
59
+
60
+ cancel()
61
+
62
+ select {
63
+ case err := <-errCh:
64
+ if !errors.Is(err, context.Canceled) {
65
+ t.Fatalf("expected context cancellation error, got %v", err)
66
+ }
67
+ case <-time.After(time.Second):
68
+ t.Fatal("LoadConfig did not return after context cancellation")
69
+ }
70
+
71
+ select {
72
+ case <-requestCanceled:
73
+ case <-time.After(time.Second):
74
+ t.Fatal("request context was not canceled")
75
+ }
76
+}