@marcel91200 / caddy Mirror · read-only / commits / 7d26d34e
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, 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 +}