DDNS Callback Provider 实战指南:把 IP 变更推送到任意 Webhook 或 HTTP API
网络CLI【免费下载链接】DDNS自动更新域名解析到本机IP,支持dnspod,阿里DNS,CloudFlare,华为云,DNSCOM...项目地址https://gitcode.com/gh_mirrors/dd/DDNS点击查看免费下载本文基于 DDNS 项目的docs/en/providers/callback.md文档系统讲解 Callback Provider 的完整配置方法、GET/POST 请求机制与变量替换规则并结合 ddns/provider/callback.py 的源码实现剖析其 HTTP 响应判定、失败重试与缓存写入的底层逻辑。读完你可以把 DDNS 的 IP 更新请求转发到任意自定义 HTTP API 或 Webhook并能正确处理endpoint/id/token三个参数的组合以及变量替换的边界情况。一、Callback Provider 是什么Callback Provider 是 DDNS 内置的一个通用自定义回调接口dns取值固定为callback它允许把每次 DDNS 更新请求转发到任意自定义的 HTTP API 端点或 Webhook。相比其他必须适配特定云厂商 API 的 Provider它具备三个特点请求地址完全由用户自定义支持 GET 和 POST 两种方法支持内置变量替换__DOMAIN__、__IP__等请求时自动填充不解析响应体内容仅以 HTTP 状态码判定成败。从源码结构看CallbackProvider 继承自 SimpleProvider 抽象基类只实现了set_record一个方法简单型 Provider 的统一接口并显式声明了三个类属性class CallbackProvider(SimpleProvider): endpoint # 无固定 API endpoint直接用 id 作为 URL content_type TYPE_JSON # POST 请求体按 application/json 编码 decode_response False # 响应体不做 JSON 解码原样返回 _require_http_success True # 只有 2xx 状态码才算成功其中_require_http_success True是理解后文HTTP 响应判定一节的关键它让基类把所有非 2xx 响应一律视为失败而不是像多数 Provider 那样把响应体解析为 JSON 结果。二、基本配置参数参数说明必填示例id回调 URL 地址支持变量替换✅https://api.example.com/ddns?domain__DOMAIN__ip__IP__tokenPOST 请求参数JSON 对象或 JSON 字符串为空时使用 GET 请求可选{api_key: your_key}或{\api_key\: \your_key\}endpoint可选的 API 端点地址不参与变量替换可选https://api.example.com/ddnsdns固定值callback表示使用回调方式✅callback四个参数在配置加载时由 ddns/config/config.py 统一提取id、token、endpoint均在公共字段列表中再经 ddns/main.py 中的run()传入 Provider 构造函数。三、完整配置示例{ $schema: https://ddns.newfuture.cc/schema/v4.1.json, dns: callback, endpoint: https://api.example.com, // endpoint 可以和 id 参数合并 id: /ddns?domain__DOMAIN__ip__IP__, // endpoint 和 id 不能同时为空 token: , // 空字符串表示使用 GET 请求有值时使用 POST 请求 index4: [url:http://api.ipify.org, public], index6: public, ipv4: ddns.newfuture.cc, ipv6: [ddns.newfuture.cc, ipv6.ddns.newfuture.cc] }公用参数说明除上述四个专属参数外Callback Provider 支持以下公用配置项完整取值说明参见 配置文件格式参数说明类型取值范围/选项默认值参数类型index4IPv4 来源数组参考配置default公用配置index6IPv6 来源数组参考配置default公用配置ipv4IPv4 域名数组域名列表无公用配置ipv6IPv6 域名数组域名列表无公用配置proxy代理设置数组参考配置无公用网络sslSSL 验证布尔/字符串auto、true、falseauto公用网络cache缓存设置布尔/字符串true、false、filepathtrue公用配置log日志配置对象参考配置无公用配置注意ttl和line两个公用参数与 Callback Provider 直接相关ddns/main.py 在调用set_record时会把config.ttl和config.line作为关键字参数传入它们随后会被填充到__TTL__和__LINE__变量中见第六节。四、请求方式GET 与 POST请求方法由token是否为空自动决定方法条件描述GETtoken为空使用 URL 查询参数POSTtoken非空使用 JSON 请求体GET 请求示例{ $schema: https://ddns.newfuture.cc/schema/v4.1.json, dns: callback, id: https://api.example.com/update?domain__DOMAIN__ip__IP__type__RECORDTYPE__, index4: [url:http://api.ipify.org, public], ipv4: ddns.newfuture.cc }变量替换后实际发出的请求为GET https://api.example.com/update?domainddns.newfuture.ccip192.168.1.100typeAPOST 请求示例{ $schema: https://ddns.newfuture.cc/schema/v4.1.json, dns: callback, endpoint: https://api.example.com, token: { api_key: your_secret_key, domain: __DOMAIN__, value: __IP__ }, index4: [url:http://api.ipify.org, public], ipv4: ddns.newfuture.cc }POST https://api.example.com Content-Type: application/json { api_key: your_secret_key, domain: ddns.newfuture.cc, value: 192.168.1.100 }POST 场景下token支持两种写法直接写 JSON 对象或写一个 JSON 字符串源码中通过jsondecode(token)反序列化后再逐值替换变量。如果token字符串不是合法 JSON反序列化会抛出ValueError这一点在 tests/test_provider_callback.py 的test_json_decode_error_handling中有明确验证。五、HTTP 响应判定与缓存机制Callback 对响应的判定规则非常明确仅将最终 HTTP 状态为 200–299的响应视为成功允许响应体为空例如 HTTP 204HTTP 404、429 及所有其他非 2xx 状态均视为失败本次 IP不会写入成功缓存下一次同步时仍会重试Callback不解析HTTP 200 响应体中的自定义业务错误。如果要报告更新失败回调接口应当返回适当的非 2xx HTTP 状态码。这些规则在源码中有对应的实现链条基类 SimpleProvider._http 中400/401/403/5xx 会直接抛出RuntimeError对于其他非 2xx 状态由于CallbackProvider._require_http_success True会在 第 269–270 行 抛出自定义HTTP error [状态码]异常CallbackProvider.set_record 用try/except捕获所有异常并返回False2xx 空响应体res非None的空串则返回True主流程 update_ip 只在result为真时才执行cache[cache_key] address写入缓存——这就是失败不缓存、后续重试的机制来源。tests/test_provider_callback.py 中的TestCallbackProviderHTTPResponses测试类用隔离的磁盘缓存完整验证了这条链条对 404/400/429 响应断言update_ip返回False且缓存文件内容为空{}对 200/201/204/299 空响应断言成功并写入{domain :A: address}随后再次同步时因缓存命中不再发出任何 HTTP 请求见 _assert_failure_retries。此外 test_http_200_business_error_body_is_not_interpreted 验证了{success: false, ...}这类 200 业务错误体不会被解读仍判定为成功。一个实用细节基类的 _mask_sensitive_data 会在输出请求 URL 和响应日志前对token做打码保留首尾 2 字符 ***因此即使把密钥放在token中日志里也不会出现明文。六、变量替换机制详解Callback Provider 支持以下内置变量在请求时自动替换变量说明示例值__DOMAIN__完整域名sub.example.com__IP__IP 地址IPv4 或 IPv6192.168.1.100或2001:db8::1__RECORDTYPE__DNS 记录类型A、AAAA、CNAME__TTL__生存时间秒300、600__LINE__解析线路default、unicom__TIMESTAMP__当前时间戳1634567890.123源码层面set_record 在每次更新时构造变量映射并调用 _replace_vars 完成替换extra.update({ __DOMAIN__: domain, __RECORDTYPE__: record_type, __TTL__: ttl, __IP__: value, __TIMESTAMP__: time(), __LINE__: line, }) url self._replace_vars(url, extra)其中domain、value、record_type来自主流程的每次同步ttl和line则透传自配置文件中的ttl、line参数__TIMESTAMP__取time.time()的浮点时间戳。替换逻辑是对映射中每个键做str.replace且 URL 与 POST 请求体都经过替换——但仅字符串类型的值会被替换测试 test_set_record_post_method_mixed_types 验证了token中的数字12345、整数30、布尔True均原样发送只有字符串值中的变量被替换。若 URL 或请求体中出现了映射之外的未知变量如__UNKNOWN__会保持原样不做替换见 test_replace_vars_partial_matches。仓库自带的 E2E 配置 tests/config/callback.json 展示了全部 6 个变量的真实用法id中用__DOMAIN__/__IP__/__RECORDTYPE__/__TIMESTAMP__构造查询串token的 JSON 字符串中同时携带__TTL__、__LINE__并附加自定义字段event、version等是一个可直接参考的完整样例。七、源码实现核对与关键细节对照 ddns/provider/callback.py 的实现有几点值得在使用时特别注意id必须是完整 URL。_validate 在初始化时执行校验只要id为空或不包含://就会抛出ValueError(endpoint or id must be configured with URL)。也就是说文档中endpoint与相对路径id合并的写法在当前源码的校验逻辑下会被拒绝——从源码结构看当前版本要求把完整回调 URL含协议头直接写在id中最为稳妥。这一点与 test_validate_failure_empty_id 的行为一致。token为空与 None 等价。判定逻辑是if token:真值判断callback.py 第 44–52 行空字符串走 GET 分支非空则解析为 POST 请求体token为 dict 时直接使用为字符串时先jsondecode反序列化。响应体原样返回。由于decode_response False基类 _http 不会把响应体当作 JSON 解析set_record拿到的是原始响应文本并记录到日志Callback result: %s便于在运行日志中直接看到回调服务的原始应答。失败语义统一。无论是网络异常、非 2xx 状态还是请求构造错误set_record一律记录错误日志并返回False由主流程决定本次run()的退出码ddns/main.py 中任一域名更新失败会以退出码 1 结束从而保证任务调度器能正确感知失败并在下一周期重试。八、典型使用场景场景 1自定义 Webhook 通知将 DDNS 更新事件推送到自定义 Webhooktoken中通过变量拼装完整事件负载{ endpoint: https://hooks.example.com, id: /webhook, token: { event: ddns_update, domain: __DOMAIN__, new_ip: __IP__, record_type: __RECORDTYPE__, timestamp: __TIMESTAMP__ }, dns: callback, index4: [default] }场景 2使用字符串格式的 token当需要动态构造复杂 JSON 字符串例如嵌套结构时token可以写成 JSON 字符串形式效果与对象形式等价{ id: https://api.example.com/ddns, token: {\auth\: \your_key\, \record\: {\name\: \__DOMAIN__\, \value\: \__IP__\, \type\: \__RECORDTYPE__\}}, dns: callback }九、故障排除调试方法启用调试在配置中设置debug: true日志级别相关配置见 配置文件格式查看日志检查 DDNS 运行日志Callback Provider 会记录每次请求的GET/POST URL、body、response以及最终结果Callback result: ...测试 API用 curl 或 Postman 独立测试回调 API 本身排除服务侧问题网络检查确保网络连通性和 DNS 解析正常代理配置proxy参数生效。使用 curl 测试回调接口# 测试 GET 请求 curl https://httpbin.org/get?domaintest.example.comip192.168.1.1 # 测试 POST 请求 curl -X POST https://httpbin.org/post \ -H Content-Type: application/json \ -d {domain: test.example.com, ip: 192.168.1.1}排查时若发现回调服务收到的是 2xx 但业务处理失败请记住第五节的规则回调接口必须用非 2xx 状态码反馈失败否则 DDNS 会将本次 IP 写入缓存、不再重试。十、延伸阅读配置文件格式index4、ipv4、proxy、log等公用参数的完整说明命令行使用以 CLI 方式运行 DDNS 与调试开发者指南编写自定义 Provider 的规范Callback Provider 即基于SimpleProvider接口核心实现ddns/provider/callback.py、ddns/provider/_base.py主流程与缓存写入ddns/main.py单元测试与响应判定验证tests/test_provider_callback.pyE2E 回调配置样例tests/config/callback.json赞分享网络CLI【免费下载链接】DDNS自动更新域名解析到本机IP,支持dnspod,阿里DNS,CloudFlare,华为云,DNSCOM...项目地址https://gitcode.com/gh_mirrors/dd/DDNS点击查看免费下载相关推荐GoReleaser HTTP Upload 实战指南把制品推送到任意 HTTP 服务器GoReleaser HTTP Upload 实战指南把制品推送到任意 HTTP 服务器 本文基于 GoReleaser 的 uploads 配置管道系统讲开发工具CI/CD构建工具GoReleaser WebHook 发布通知把每个 Release 推送到任意 HTTP 端点GoReleaser WebHook 发布通知把每个 Release 推送到任意 HTTP 端点 GoReleaser 的 announce.webhook开发工具CI/CD构建工具ddns-go 部署与配置完全指南系统服务、Docker、Webhook 与 Callback 实战ddns go 部署与配置完全指南系统服务、Docker、Webhook 与 Callback 实战 ddns go 是一款开箱即用的动态 DNSDDNS网络创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考