Skip to content

Commit 60b5512

Browse files
committed
fixup: clarify Cloudflare trace field names
1 parent c6e25c9 commit 60b5512

4 files changed

Lines changed: 28 additions & 28 deletions

File tree

README.markdown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ docker run --rm --network host curlimages/curl:latest --fail --show-error --sile
448448
docker run --rm --network host curlimages/curl:latest --fail --show-error --silent --ipv4 https://connectivity.cloudflareclient.com/cdn-cgi/trace
449449
```
450450

451-
If curl reports `Could not resolve host`, fix DNS resolution in the container network. Any other curl failure means that HTTPS endpoint is unavailable under the tested network and IP family. One failed endpoint does not by itself mean detection must fail, because another endpoint can return a valid response first. However, restrictive outbound policies should allow all three hosts to preserve fallback behavior. If any of the three commands succeeds but detection still times out, check the updater logs for response-validation failures, then try increasing `DETECTION_TIMEOUT` (for example, `DETECTION_TIMEOUT=1m`).
451+
If `curl` reports `Could not resolve host`, fix DNS resolution in the container network. Any other `curl` failure means that HTTPS endpoint is unavailable under the tested network and IP family. One failed endpoint does not by itself mean detection must fail, because another endpoint can return a valid response first. However, restrictive outbound policies should allow all three hosts to preserve fallback behavior. If any of the three commands succeeds but detection still times out, check the updater logs for response-validation failures, then try increasing `DETECTION_TIMEOUT` (for example, `DETECTION_TIMEOUT=1m`).
452452

453453
If that still does not help, please [open a GitHub issue](https://github.com/favonia/cloudflare-ddns/issues/new/choose) and include your setup details, relevant configs with secrets redacted, and any logs you have so that we can investigate further.
454454

internal/provider/protocol/cloudflare_trace.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -262,13 +262,13 @@ func describeCloudflareTraceFailure(failure traceFailure) string {
262262
return fmt.Sprintf("failed to parse the provider URL: %v", failure.cause)
263263
case traceFailureMismatchedH:
264264
return fmt.Sprintf(
265-
"the h field %q does not match the expected host %q; please report this at %s",
265+
`the "h" field %q does not match the expected host %q; please report this at %s`,
266266
failure.observed, failure.expected, pp.IssueReportingURL,
267267
)
268268
case traceFailureWarpOn:
269-
return "the response has warp=on; the detected IP is a Cloudflare WARP egress IP, not your real public IP"
269+
return `the "warp" field is "on"; the detected IP is a Cloudflare WARP egress IP, not your real public IP`
270270
case traceFailureMissingIP:
271-
return "the response does not contain an ip field"
271+
return `the response does not contain an "ip" field`
272272
case traceFailureUnparseableIP:
273273
return fmt.Sprintf("failed to parse the IP address %q", failure.observed)
274274
case traceFailureCloudflareIP:
@@ -304,11 +304,11 @@ func reportCloudflareTraceWinnerWarnings(
304304
var missingFields string
305305
switch {
306306
case missingH && missingWarp:
307-
missingFields = "the h (host) and warp fields"
307+
missingFields = `the "h" (host) and "warp" fields`
308308
case missingH:
309-
missingFields = "the h (host) field"
309+
missingFields = `the "h" (host) field`
310310
case missingWarp:
311-
missingFields = "the warp field"
311+
missingFields = `the "warp" field`
312312
default:
313313
return
314314
}

internal/provider/protocol/cloudflare_trace_test.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ func TestCloudflareTraceGetRawDataReplaysWinnerWarnings(t *testing.T) {
242242
require.True(t, result.Available)
243243
require.Equal(t,
244244
"Cloudflare trace IPv4 detection succeeded via fallback endpoint "+winnerURL+
245-
", but its response is missing the h (host) and warp fields; please report this at "+
245+
", but its response is missing the \"h\" (host) and \"warp\" fields; please report this at "+
246246
"https://github.com/favonia/cloudflare-ddns/issues/new/choose\n",
247247
transcript,
248248
)
@@ -270,7 +270,7 @@ func TestCloudflareTraceGetRawDataReportsMissingWarpFromWinner(t *testing.T) {
270270
require.True(t, result.Available)
271271
require.Equal(t,
272272
"Cloudflare trace IPv4 detection succeeded via primary endpoint "+server.URL+
273-
"/primary, but its response is missing the warp field; please report this at "+
273+
"/primary, but its response is missing the \"warp\" field; please report this at "+
274274
"https://github.com/favonia/cloudflare-ddns/issues/new/choose\n",
275275
output.String(),
276276
)
@@ -488,7 +488,7 @@ func TestCloudflareTraceGetRawData(t *testing.T) {
488488
m.EXPECT().Noticef(pp.EmojiImpossible,
489489
"Cloudflare trace %s detection succeeded via %s endpoint %s, "+
490490
"but its response is missing %s; please report this at %s",
491-
"IPv4", "primary", serverURL, "the h (host) field", pp.IssueReportingURL)
491+
"IPv4", "primary", serverURL, `the "h" (host) field`, pp.IssueReportingURL)
492492
},
493493
},
494494
"4/mismatched-h": { //nolint:exhaustruct // test fixture sets only exercised fields
@@ -499,7 +499,7 @@ func TestCloudflareTraceGetRawData(t *testing.T) {
499499
available: false,
500500
prepareMockPP: func(serverURL string, m *mocks.MockPP) {
501501
expectCloudflareTraceFailure(m, pp.EmojiImpossible, ipnet.IP4, serverURL, fmt.Sprintf(
502-
"the h field %q does not match the expected host %q; please report this at %s",
502+
`the "h" field %q does not match the expected host %q; please report this at %s`,
503503
"wrong.example.com", hostFromURL(serverURL), pp.IssueReportingURL))
504504
},
505505
},
@@ -511,7 +511,7 @@ func TestCloudflareTraceGetRawData(t *testing.T) {
511511
available: false,
512512
prepareMockPP: func(serverURL string, m *mocks.MockPP) {
513513
expectCloudflareTraceFailure(m, pp.EmojiError, ipnet.IP4, serverURL,
514-
"the response has warp=on; the detected IP is a Cloudflare WARP egress IP, not your real public IP")
514+
`the "warp" field is "on"; the detected IP is a Cloudflare WARP egress IP, not your real public IP`)
515515
},
516516
},
517517
"4/missing-warp-warns": { //nolint:exhaustruct // test fixture sets only exercised fields
@@ -524,7 +524,7 @@ func TestCloudflareTraceGetRawData(t *testing.T) {
524524
m.EXPECT().Noticef(pp.EmojiImpossible,
525525
"Cloudflare trace %s detection succeeded via %s endpoint %s, "+
526526
"but its response is missing %s; please report this at %s",
527-
"IPv4", "primary", serverURL, "the warp field", pp.IssueReportingURL)
527+
"IPv4", "primary", serverURL, `the "warp" field`, pp.IssueReportingURL)
528528
},
529529
},
530530
"4/missing-ip": { //nolint:exhaustruct // test fixture sets only exercised fields
@@ -535,7 +535,7 @@ func TestCloudflareTraceGetRawData(t *testing.T) {
535535
available: false,
536536
prepareMockPP: func(serverURL string, m *mocks.MockPP) {
537537
expectCloudflareTraceFailure(m, pp.EmojiError, ipnet.IP4, serverURL,
538-
"the response does not contain an ip field")
538+
`the response does not contain an "ip" field`)
539539
},
540540
},
541541
"4/unparseable-ip": { //nolint:exhaustruct // test fixture sets only exercised fields
@@ -615,7 +615,7 @@ func TestCloudflareTraceGetRawData(t *testing.T) {
615615
available: false,
616616
prepareMockPP: func(serverURL string, m *mocks.MockPP) {
617617
expectCloudflareTraceFailure(m, pp.EmojiError, ipnet.IP4, serverURL,
618-
"the response does not contain an ip field")
618+
`the response does not contain an "ip" field`)
619619
},
620620
},
621621
"4/lines-without-equals": { //nolint:exhaustruct // test fixture sets only exercised fields
@@ -633,7 +633,7 @@ func TestCloudflareTraceGetRawData(t *testing.T) {
633633
available: false,
634634
prepareMockPP: func(serverURL string, m *mocks.MockPP) {
635635
expectCloudflareTraceFailure(m, pp.EmojiError, ipnet.IP6, serverURL,
636-
"the response has warp=on; the detected IP is a Cloudflare WARP egress IP, not your real public IP")
636+
`the "warp" field is "on"; the detected IP is a Cloudflare WARP egress IP, not your real public IP`)
637637
},
638638
},
639639
"4/warp-plus-passes": { //nolint:exhaustruct // test fixture sets only exercised fields
@@ -654,7 +654,7 @@ func TestCloudflareTraceGetRawData(t *testing.T) {
654654
m.EXPECT().Noticef(pp.EmojiImpossible,
655655
"Cloudflare trace %s detection succeeded via %s endpoint %s, "+
656656
"but its response is missing %s; please report this at %s",
657-
"IPv6", "primary", displayServerURL, "the h (host) field", pp.IssueReportingURL)
657+
"IPv6", "primary", displayServerURL, `the "h" (host) field`, pp.IssueReportingURL)
658658
},
659659
},
660660
"6/mismatched-h": { //nolint:exhaustruct // test fixture sets only exercised fields
@@ -665,7 +665,7 @@ func TestCloudflareTraceGetRawData(t *testing.T) {
665665
available: false,
666666
prepareMockPP: func(serverURL string, m *mocks.MockPP) {
667667
expectCloudflareTraceFailure(m, pp.EmojiImpossible, ipnet.IP6, serverURL, fmt.Sprintf(
668-
"the h field %q does not match the expected host %q; please report this at %s",
668+
`the "h" field %q does not match the expected host %q; please report this at %s`,
669669
"wrong.example.com", hostFromURL(serverURL), pp.IssueReportingURL))
670670
},
671671
},

internal/updater/updater_internal_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,8 @@ func captureCloudflareTraceDetectionTranscript(
183183
notifier: msg.NotifierMessage.Format(),
184184
endpoints: append([]string(nil), endpoints...),
185185
requestCounts: [3]int32{requestCounts[0].Load(), requestCounts[1].Load(), requestCounts[2].Load()},
186-
winnerWarnings: strings.Contains(output.String(), "response is missing the h (host)") ||
187-
strings.Contains(output.String(), "response is missing the warp field"),
186+
winnerWarnings: strings.Contains(output.String(), `response is missing the "h" (host)`) ||
187+
strings.Contains(output.String(), `response is missing the "warp" field`),
188188
}
189189

190190
return capture
@@ -243,8 +243,8 @@ func TestCloudflareTraceDetectionTranscript(t *testing.T) {
243243
require.False(t, capture.winnerWarnings)
244244
host := strings.TrimSuffix(strings.TrimPrefix(capture.endpoints[0], "http://"), "/primary")
245245
wantTranscript = fmt.Sprintf(
246-
"Cloudflare trace IPv4 detection via %s failed: the response does not contain an ip field\n"+
247-
"Cloudflare trace IPv4 detection via %s failed: the h field \"wrong.example\" does not match the expected host \"%s\"; please report this at https://github.com/favonia/cloudflare-ddns/issues/new/choose\n"+
246+
"Cloudflare trace IPv4 detection via %s failed: the response does not contain an \"ip\" field\n"+
247+
"Cloudflare trace IPv4 detection via %s failed: the \"h\" field \"wrong.example\" does not match the expected host \"%s\"; please report this at https://github.com/favonia/cloudflare-ddns/issues/new/choose\n"+
248248
"Cloudflare trace IPv4 detection via %s failed: the detected IP address 2001:db8::1 is not a valid IPv4 address\n"+
249249
"No valid IPv4 addresses were detected\n"+
250250
"If your network does not support IPv4, you can stop managing it with IP4_PROVIDER=none\n",
@@ -276,12 +276,12 @@ func TestCloudflareTraceDetectionTranscript(t *testing.T) {
276276
endpointRole string
277277
missingClause string
278278
}{
279-
{name: "primary-winner-missing-h", winnerIndex: 0, endpointRole: "primary", missingClause: "but its response is missing the h (host) field"},
280-
{name: "primary-winner-missing-warp", winnerIndex: 0, endpointRole: "primary", missingClause: "but its response is missing the warp field"},
281-
{name: "primary-winner-missing-both", winnerIndex: 0, endpointRole: "primary", missingClause: "but its response is missing the h (host) and warp fields"},
282-
{name: "fallback-winner-missing-h", winnerIndex: 1, endpointRole: "fallback", missingClause: "but its response is missing the h (host) field"},
283-
{name: "fallback-winner-missing-warp", winnerIndex: 1, endpointRole: "fallback", missingClause: "but its response is missing the warp field"},
284-
{name: "fallback-winner-missing-both", winnerIndex: 1, endpointRole: "fallback", missingClause: "but its response is missing the h (host) and warp fields"},
279+
{name: "primary-winner-missing-h", winnerIndex: 0, endpointRole: "primary", missingClause: `but its response is missing the "h" (host) field`},
280+
{name: "primary-winner-missing-warp", winnerIndex: 0, endpointRole: "primary", missingClause: `but its response is missing the "warp" field`},
281+
{name: "primary-winner-missing-both", winnerIndex: 0, endpointRole: "primary", missingClause: `but its response is missing the "h" (host) and "warp" fields`},
282+
{name: "fallback-winner-missing-h", winnerIndex: 1, endpointRole: "fallback", missingClause: `but its response is missing the "h" (host) field`},
283+
{name: "fallback-winner-missing-warp", winnerIndex: 1, endpointRole: "fallback", missingClause: `but its response is missing the "warp" field`},
284+
{name: "fallback-winner-missing-both", winnerIndex: 1, endpointRole: "fallback", missingClause: `but its response is missing the "h" (host) and "warp" fields`},
285285
} {
286286
t.Run(tc.name, func(t *testing.T) {
287287
t.Parallel()

0 commit comments

Comments
 (0)