Skip to content

为 API v4 接入 FastIP 预热与直连优化 - #177

Merged
tsosunchia merged 3 commits into
mainfrom
codex/api-v4-fastip
May 22, 2026
Merged

为 API v4 接入 FastIP 预热与直连优化#177
tsosunchia merged 3 commits into
mainfrom
codex/api-v4-fastip

Conversation

@tsosunchia

@tsosunchia tsosunchia commented May 22, 2026

Copy link
Copy Markdown
Member

Summary

  • LeoMoeAPI 的 NextTrace API v4 HTTP 路径补上 FastIP 预热与复用逻辑。
  • 让默认 api.nxtrace.org/v4/ipGeo 请求在无代理场景下优先拨到已探测的 FastIP,同时保留原有 URL、Host、SNI 和 token 行为。
  • 当配置了 API v4 token 时,CLI 和 service runtime 不再初始化 v3 WebSocket 连接,而是改为预热 v4 FastIP。

Motivation

v3 WebSocket 已经复用 FastIP 优化连接,但 v4 HTTP GeoIP 路径没有走同样的建连逻辑,导致两条 API 路径的连接优化不一致。

Changes

  • ipgeo 中新增 v4 FastIP 预热入口,并为默认 API endpoint 构建 FastIP-aware HTTP client。
  • 将 v4 client cache 与 dial 逻辑调整为:默认 endpoint 走 FastIP,非默认 endpoint 继续走现有 Geo DNS 行为,代理场景不强制绕过代理。
  • cmdinternal/service 的 runtime 选择中,v4 token 模式下改为预热 FastIP,并补充对应单测。
  • 增加 v4 FastIP、custom endpoint、proxy、CLI/runtime 分支的测试覆盖。

Testing

  • go test ./ipgeo ./cmd ./internal/service
  • go test ./...
  • git diff --check

Notes for Reviewers

  • 需要重点确认 v4 默认 endpoint 的连接目标是否与预期一致,尤其是 proxy 场景和自定义 endpoint 的行为边界。
  • 本次未改变 v4 response/schema,也未改动 v3 WebSocket 协议。'
    pull request create failed: GraphQL: Head sha can't be blank, Base sha can't be blank, No commits between main and codex/api-v4-fastip, Head ref must be a branch (createPullRequest)
    无法创建拉取请求

Summary by CodeRabbit

发布说明

  • 新功能

    • 添加 NextTrace API v4 的 FastIP 预热与快速查询支持,检测到 v4 配置时优先使用该路径。
  • 改进

    • 初始化流程自动选择更快的查询方案以减少连接与查询延迟,增强稳定性与性能回退逻辑。
  • 测试

    • 新增多组针对 v4 快速查询、代理行为、超时边界与回退拨号的测试用例以覆盖关键场景。

Review Change Stack

Copilot AI review requested due to automatic review settings May 22, 2026 09:34
@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 6cae5119-3edb-4f84-b348-ea934cf38262

📥 Commits

Reviewing files that changed from the base of the PR and between 1b2b0c7 and 8dd2db9.

📒 Files selected for processing (2)
  • ipgeo/nexttrace_api_v4.go
  • ipgeo/nexttrace_api_v4_test.go

Walkthrough

在 ipgeo 中新增 NextTrace API v4 FastIP 预热与按端点 HTTP 客户端工厂,并在 cmd 和 service 初始化路径按 NextTrace APIV4 token 配置触发预热;新增/调整大量单元测试覆盖代理、超时与回退场景。

Changes

NextTrace API v4 FastIP 预热与集成

Layer / File(s) Summary
NextTrace API v4 FastIP 核心实现
ipgeo/nexttrace_api_v4.go
新增 v4 API 常量、按 endpoint+timeout 的 HTTP 客户端工厂、导出入口 PrepareNextTraceAPIV4FastIP、以及自定义 Transport 与拨号逻辑(fast IP 缓存优先,失败回退到 geo DNS)。
ipgeo 测试与工厂签名适配
ipgeo/nexttrace_api_v4_test.go
新增代理隔离辅助、将 nextTraceAPIV4HTTPClientFactory 签名扩展为接收 endpoint 参数;新增/扩展多组测试覆盖 FastIP 预热、超时共享、缓存回退、代理场景与端点端口规则。
service 运行时初始化的条件路由
internal/service/service.go, internal/service/service_test.go
新增包级 prepareNextTraceAPIV4FastIPFnwithServiceRuntime 在 v4 token 配置时调用 prepareNextTraceAPIV4FastIPFn(ctx,false) 否则调用 ensureLeoMoeConnectionFn(ctx);新增测试验证 GeoLookup 在有 token 时使用 FastIP 并跳过 Leo WS,更新测试桩保存/恢复逻辑。
cmd WebSocket 初始化中的 FastIP 触发
cmd/cmd.go, cmd/cmd_test.go
新增包级 prepareNextTraceAPIV4FastIPFn,在 initLeoWebsocket 的 v4 token 分支调用 prepareNextTraceAPIV4FastIPFn(ctx, true)(返回值忽略);测试替换全局函数并断言被调用一次且参数有效。

Sequence Diagram

sequenceDiagram
  participant Init as initLeoWebsocket / withServiceRuntime
  participant Token as NextTraceAPIV4TokenConfigured
  participant Prepare as PrepareNextTraceAPIV4FastIP
  participant ClientFactory as nextTraceAPIV4HTTPClientFactory
  participant Transport as newNextTraceAPIV4HTTPClient
  participant Dial as dialNextTraceAPIV4
  participant Geo as util.LookupHostForGeo
  Init->>Token: 检查 v4 token
  Token-->>Init: true
  Init->>Prepare: 调用(ctx, enableOutput)
  Prepare->>ClientFactory: 请求按 endpoint 创建客户端
  ClientFactory->>Transport: 返回带自定义 Dial 的 Transport
  Transport->>Dial: DialContext 发起拨号
  Dial->>Prepare: 查询 FastIP 缓存并尝试直连
  Dial->>Geo: 回退到 Geo DNS 并逐个拨号
Loading

估计审阅工作量

🎯 4 (复杂) | ⏱️ ~45 分钟

可能相关的 PR

  • nxtrace/NTrace-dev#174: 与本 PR 在 cmd/cmd.go 的 initLeoWebsocket v4 token 分支相关,存在代码级交叉变更点。
  • nxtrace/NTrace-dev#176: 修改与 v4 客户端创建/缓存复用相关的流,与本次按 endpoint 绑定客户端工厂的改动有直接关联。

诗歌

🐰 我在代码地里轻轻跑,预热 FastIP 嗅新草,
端点铺路连通道,超时与代理都记牢,
从 cmd 到 service 串起桥,测试花开遍野笑,
小兔吱喳:连接来啦,快链路报到!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确反映了PR的核心变更:为NextTrace API v4集成FastIP预热与直连优化功能,清晰且具体。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/api-v4-fastip

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@tsosunchia

Copy link
Copy Markdown
Member Author

@codex review

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ipgeo/nexttrace_api_v4.go`:
- Around line 246-251: When a cached FastIP exists (util.GetFastIPCache) the
code currently returns the DialContext error directly; change this so you
attempt dialer.DialContext(ctx, network, net.JoinHostPort(fastIP, port)) but if
that call returns a non-nil error fall back to calling dialGeoResolved(ctx,
dialer, network, host, port) instead of returning the error immediately; update
the branch that checks strings.EqualFold(host, apiHost) && port == apiPort to
perform the fallback logic using the same fastIP, dialer.DialContext, and
dialGeoResolved symbols.
- Around line 205-208: The port defaulting logic currently sets an implicit port
to nextTraceAPIV4DefaultPort regardless of scheme; change it so when port :=
u.Port() is empty you pick "80" for u.Scheme == "http" and
nextTraceAPIV4DefaultPort (likely "443") for other schemes (i.e., check u.Scheme
and assign port = "80" when scheme == "http", else port =
nextTraceAPIV4DefaultPort) in the same block where port and u are used.
- Around line 177-190: PrepareNextTraceAPIV4FastIP currently passes the caller's
ctx through, which can block forever; modify prepareNextTraceAPIV4FastIP to
create a bounded child context (e.g., context.WithTimeout(ctx, shortDuration))
before calling nextTraceAPIV4FastIPFn, defer the cancel(), and pass that timed
ctx into nextTraceAPIV4FastIPFn so the FastIP prewarm is bounded; keep the
existing host/port checks and return behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 84fd279f-cefb-4bd9-a442-7968bbc10555

📥 Commits

Reviewing files that changed from the base of the PR and between ea5c1e9 and 8b81f03.

📒 Files selected for processing (6)
  • cmd/cmd.go
  • cmd/cmd_test.go
  • internal/service/service.go
  • internal/service/service_test.go
  • ipgeo/nexttrace_api_v4.go
  • ipgeo/nexttrace_api_v4_test.go

Comment thread ipgeo/nexttrace_api_v4.go
Comment thread ipgeo/nexttrace_api_v4.go
Comment thread ipgeo/nexttrace_api_v4.go

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

为 NextTrace API v4 的 ipGeo HTTP 路径补齐 FastIP 预热与“直连已探测 FastIP”的拨号逻辑,并在 v4 token 模式下让 CLI / service runtime 不再初始化 v3 WebSocket,而是改为预热 v4 FastIP;同时补充对应测试覆盖,以统一 v3/v4 的连接优化行为边界(默认 endpoint / 自定义 endpoint / proxy)。

Changes:

  • 为 v4 默认 endpoint 构建 FastIP-aware 的 HTTP client,并新增 v4 FastIP 预热入口(含 proxy / custom endpoint 分支)。
  • CLI 与 service runtime 在检测到 v4 token 时改为预热 v4 FastIP,跳过 v3 WebSocket 初始化路径。
  • 增加 v4 FastIP、custom endpoint、proxy、CLI/runtime 分支相关的单测覆盖。

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
ipgeo/nexttrace_api_v4.go 引入 v4 FastIP 预热与基于 FastIP cache 的 DialContext 逻辑,并调整 client factory 签名以支持 endpoint-aware client 创建。
ipgeo/nexttrace_api_v4_test.go 新增/更新测试覆盖:默认 endpoint 使用 FastIP、自定义 endpoint 跳过 FastIP、proxy 场景走代理等。
internal/service/service.go service runtime:v4 token 模式下预热 FastIP,避免初始化 v3 WebSocket。
internal/service/service_test.go 增加 v4 token 模式下应调用 FastIP 预热且不触发 LeoWS 初始化的测试,并加强测试环境隔离。
cmd/cmd.go CLI 初始化:v4 token 模式下调用 FastIP 预热后直接返回,跳过 v3 WebSocket 初始化。
cmd/cmd_test.go 增加 CLI 分支测试,断言 v4 token 模式下会调用 FastIP 预热。

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ipgeo/nexttrace_api_v4.go
Comment on lines +193 to +209
func nextTraceAPIV4APIEndpointHostPort(endpoint string) (string, string, bool) {
u, err := url.Parse(normalizeNextTraceAPIV4Endpoint(endpoint))
if err != nil {
return "", "", false
}
scheme := strings.ToLower(u.Scheme)
if scheme != "https" && scheme != "http" {
return "", "", false
}
if !strings.EqualFold(u.Hostname(), nextTraceAPIV4APIHost) || u.EscapedPath() != nextTraceAPIV4GeoPath {
return "", "", false
}
port := u.Port()
if port == "" {
port = nextTraceAPIV4DefaultPort
}
return nextTraceAPIV4APIHost, port, true
Comment thread ipgeo/nexttrace_api_v4.go Outdated
Comment on lines 96 to 101
fastIPCtx, cancelFastIP := context.WithTimeout(context.Background(), timeout)
_ = prepareNextTraceAPIV4FastIP(fastIPCtx, nextTraceAPIV4GeoEndpoint, true)
cancelFastIP()

ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
Comment thread ipgeo/nexttrace_api_v4.go Outdated
timeout = normalizeNextTraceAPIV4Timeout(timeout)
client := cachedNextTraceAPIV4Client(nextTraceAPIV4GeoEndpoint, util.GetNextTraceAPIV4Token(), timeout)
fastIPCtx, cancelFastIP := context.WithTimeout(context.Background(), timeout)
_ = prepareNextTraceAPIV4FastIP(fastIPCtx, nextTraceAPIV4GeoEndpoint, true)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8b81f0365f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ipgeo/nexttrace_api_v4.go Outdated
Comment on lines 96 to 100
fastIPCtx, cancelFastIP := context.WithTimeout(context.Background(), timeout)
_ = prepareNextTraceAPIV4FastIP(fastIPCtx, nextTraceAPIV4GeoEndpoint, true)
cancelFastIP()

ctx, cancel := context.WithTimeout(context.Background(), timeout)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep v4 lookup within a single timeout budget

This now spends one full timeout warming FastIP and then starts a second full-timeout lookup, so a single LeoIPNextTraceAPIV4HTTP call can block for roughly 2× the caller’s budget on cache misses or slow FastIP probes. Before this change the timeout bounded the whole call path, so callers that rely on timeout as an end-to-end SLA will see unexpected latency inflation.

Useful? React with 👍 / 👎.

Comment thread ipgeo/nexttrace_api_v4.go Outdated
Comment on lines +183 to +184
if !ok || util.GetProxy() != nil {
return nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Detect all proxy modes before FastIP prewarm

The prewarm skip condition only checks NEXTTRACE_PROXY via util.GetProxy(), but the HTTP transport is cloned from http.DefaultTransport, which still honors HTTP_PROXY/HTTPS_PROXY (ProxyFromEnvironment). In environments using standard proxy env vars, this path still runs FastIP probing even though the actual API request is proxied, adding avoidable delay and direct outbound probe traffic that bypasses the configured proxy policy.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ipgeo/nexttrace_api_v4.go (1)

43-45: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

默认工厂别绕过 util.NewGeoHTTPClient(...)

这里把默认路径统一切到 newNextTraceAPIV4HTTPClient 了,但该工厂最终是手工组装 http.Client/Transport。这样会把 Geo HTTP 客户端已有的默认行为分叉出去。建议先从 util.NewGeoHTTPClient(timeout) 派生,再只覆写这次需要的 Proxy/DialContext

As per coding guidelines "Geo HTTP requests must use util.NewGeoHTTPClient(...) with Transport cloned from default Transport to preserve proxy/HTTP2/connection pool behavior."

Also applies to: 74-75, 131-131

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ipgeo/nexttrace_api_v4.go` around lines 43 - 45, The default factory
nextTraceAPIV4HTTPClientFactory currently returns a bespoke http.Client
assembled by newNextTraceAPIV4HTTPClient, which bypasses
util.NewGeoHTTPClient(...) and loses shared proxy/HTTP2/connection-pool
behavior; change newNextTraceAPIV4HTTPClient to call
util.NewGeoHTTPClient(timeout) (or clone its Transport from
http.DefaultTransport) and then only override the specific Transport fields you
need (Proxy and DialContext) before returning the client, and update any other
factory usages that create clients (the other factory assignments referenced) to
follow the same pattern so all Geo HTTP clients preserve the default transport
behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ipgeo/nexttrace_api_v4_test.go`:
- Around line 410-414: In TestDialNextTraceAPIV4FallsBackWhenCachedFastIPFails
replace net.Listen("tcp", "127.0.0.1:0") with net.ListenConfig{}.Listen to
create the listener so context-aware listen is used, and change the defer to
capture and handle listener.Close()’s error (e.g., defer func() { if err :=
listener.Close(); err != nil { t.Fatalf("listener.Close() error = %v", err) }
}()) to satisfy errcheck/noctx; ensure you update the variable name `listener`
and any surrounding error handling in that test accordingly.

---

Outside diff comments:
In `@ipgeo/nexttrace_api_v4.go`:
- Around line 43-45: The default factory nextTraceAPIV4HTTPClientFactory
currently returns a bespoke http.Client assembled by
newNextTraceAPIV4HTTPClient, which bypasses util.NewGeoHTTPClient(...) and loses
shared proxy/HTTP2/connection-pool behavior; change newNextTraceAPIV4HTTPClient
to call util.NewGeoHTTPClient(timeout) (or clone its Transport from
http.DefaultTransport) and then only override the specific Transport fields you
need (Proxy and DialContext) before returning the client, and update any other
factory usages that create clients (the other factory assignments referenced) to
follow the same pattern so all Geo HTTP clients preserve the default transport
behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5c895ba3-983a-4cd5-84e9-89eb8727d427

📥 Commits

Reviewing files that changed from the base of the PR and between 8b81f03 and 1b2b0c7.

📒 Files selected for processing (2)
  • ipgeo/nexttrace_api_v4.go
  • ipgeo/nexttrace_api_v4_test.go

Comment thread ipgeo/nexttrace_api_v4_test.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

@tsosunchia
tsosunchia merged commit 33e7ee1 into main May 22, 2026
49 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants