pub struct IncomingRequest {Show 13 fields
pub transport: RequestTransport,
pub session_generation: u64,
pub conn_id: u64,
pub proto_id: u32,
pub serial_no: u32,
pub proto_fmt_type: ProtoFmtType,
pub body: Bytes,
pub idempotency_key: Option<String>,
pub caller_key_id: Option<String>,
pub caller_allowed_acc_ids: Option<Arc<HashSet<u64>>>,
pub caller_has_auth_setup_scope: bool,
pub caller_is_loopback: bool,
pub caller_legacy_local_mode: bool,
/* private fields */
}Expand description
从连接接收到的请求
Fields§
§transport: RequestTransport§session_generation: u64Physical socket generation copied from ClientConn by the listener
immediately before dispatch. Non-raw adapters retain zero.
conn_id: u64发送请求的连接 ID(用于响应路由 + SubscriptionManager / cache 记账)
跨 surface 命名空间分配(v1.4.106 codex 0517 ζ25-redo F2 沉淀):
- raw TCP listener:
ClientConn::generate_conn_id()派生(u32 范围) - REST:
crates/futu-rest/src/routes/qot.rs::REST_SHARED_CONN=0xFFFF_FFFE(u32 上限附近, 单值共享) - gRPC:
crates/futu-grpc/src/auth.rs::GRPC_STABLE_CONN_NAMESPACE=0x4000_0000_0000_0000(bit 62 namespace, 按 caller 派生) - WS / MCP: 通常派生自所属物理 TCP 连接的 conn_id
各 surface 不重叠. 加新 surface 时分配一个 namespace base, 不要与 上述 4 个段重合.
proto_id: u32协议 ID(对齐 C++ NN_ProtoCmd_*)
serial_no: u32序列号(和 Response 配对,供 client 端请求-响应匹配)
proto_fmt_type: ProtoFmtType请求体 proto 格式(Protobuf / JSON)
body: Bytes请求 body(已解密后的明文)
idempotency_key: Option<String>v1.4.38 Phase 4: 订单幂等 key(由 REST Idempotency-Key header / gRPC
metadata / WS envelope / MCP tool args 填入)。None 表示客户端未传,
handler 走无幂等直通 path(backward-compat)。
caller_key_id: Option<String>v1.4.106 codex 0920 F1 (P1): caller key id 副本 (per-call snapshot, 由 surface adapter 层从 KeyRecord 读取后填入).
目标: idempotency cache key namespace 必须含 caller key id, 否则 不同 caller 用同 Idempotency-Key 会跨 caller 命中老 response —— 严重 跨账户数据泄漏 + 重复下单 silent fail.
None = 无 caller 标识 (legacy TCP / 未 auth) → namespace 用 <no_key>
占位符. Some("alice") = WS / MCP / REST 已 auth 的 caller —— namespace
用 <caller_key_id="alice">, 不与其他 caller 串.
caller_allowed_acc_ids: Option<Arc<HashSet<u64>>>v1.4.105 D2 contract-hardening 补丁: caller key 的 allowed_acc_ids 硬限额
副本 (per-call snapshot, 在 surface adapter 层从 KeyRecord 读取后填入).
目标: 让 dispatch-time handlers (e.g. SubAccPushHandler 注册 acc_id
到 SubscriptionManager) 也能 enforce per-acc whitelist — 即使上游 pipeline
body-aware step 已 enforce, 让 handler 自己 defense-in-depth 防 future
regression (新 surface 加进来漏调 pipeline body-aware).
None / Some(empty) = caller 无 acc_id 限制 (legacy mode 或 unrestricted
key) → handler 不 filter; Some(non-empty set) → handler 应 reject 不在
set 中的 acc_id. Deny-all 使用 sentinel {0},不使用空集合。
caller_has_auth_setup_scope: boolCentral pre-login Verification admission facts supplied by adapters.
caller_is_loopback: bool§caller_legacy_local_mode: boolImplementations§
Source§impl IncomingRequest
impl IncomingRequest
pub fn response_commit_waiter(&self) -> ResponseCommitWaiter
Sourcepub fn builder(
conn_id: u64,
proto_id: u32,
serial_no: u32,
proto_fmt_type: ProtoFmtType,
body: Bytes,
) -> IncomingRequestBuilder
pub fn builder( conn_id: u64, proto_id: u32, serial_no: u32, proto_fmt_type: ProtoFmtType, body: Bytes, ) -> IncomingRequestBuilder
codex 0522 F4 v1.4.106: cross-surface 单测 hook. 构 IncomingRequest
并填 caller scope (caller_key_id + caller_allowed_acc_ids) — 让
REST / gRPC / WS / MCP 等 surface 的 adapter 都用同一构造路径, 防
“某个 surface 漏填字段” silent regression.
之前 4 surface 各写一份 struct literal, 加新字段需逐个改, 漏一个就 出现 silent None — 与坑 #54 schema-only fix 同模式 (实装符号 vs 真 行为差距). 本 helper 是 single point, 加新字段 schema 自动 propagate.
注意: 本 helper 不 take ownership of body — caller 已 own bytes. idempotency_key / caller_key_id 接 String 而非 &str 让 caller 决定 是 clone 还是 move.
Trait Implementations§
Source§impl Debug for IncomingRequest
impl Debug for IncomingRequest
Source§impl From<IncomingRequestBuilder> for IncomingRequest
impl From<IncomingRequestBuilder> for IncomingRequest
Source§fn from(builder: IncomingRequestBuilder) -> Self
fn from(builder: IncomingRequestBuilder) -> Self
Auto Trait Implementations§
impl !Freeze for IncomingRequest
impl RefUnwindSafe for IncomingRequest
impl Send for IncomingRequest
impl Sync for IncomingRequest
impl Unpin for IncomingRequest
impl UnsafeUnpin for IncomingRequest
impl UnwindSafe for IncomingRequest
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more