Skip to content

Commit f6199a7

Browse files
simorenohCopilot
andcommitted
Cosmos: RID-aware resource references and raw-path protocol (1/3)
Slice 1 of 3 (stacked, epic #4637) of the Cosmos RID-addressing work. This slice is driver-internal only and has no public API surface. Add RID-capable ContainerReference (new_by_rid, base_path, is_by_rid; database_name/name_based_path now return Option) and the raw-path / lowercased-RID signing protocol in CosmosResourceReference (compute_paths, rid_signing_override, is_rid_addressed, ResourcePaths::is_rid_based, encode_path_segments). build_transport_request sends RID-based paths raw and percent-encodes name-based paths; session_container indexes on base_path. validate_addressing and the CLIENT_MIXED_NAME_RID_ADDRESSING status are intentionally deferred to Slice 2; addressing_conflict/parent_chain_is_rid are debug-only here. A minimal compile shim in container_cache.rs adapts to the new Option-returning database_name. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 3bb48a5 commit f6199a7

7 files changed

Lines changed: 660 additions & 50 deletions

File tree

sdk/cosmos/azure_data_cosmos_driver/CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Release History
22

3+
## 0.6.0 (Unreleased)
4+
5+
### Features Added
6+
7+
### Breaking Changes
8+
9+
### Bugs Fixed
10+
11+
- RID-addressed requests are now signed and routed correctly. The driver signs them over the lowercased resource RID (the leaf for point reads, the parent for feeds), matching the service's `is_name_based = false` rule, and sends the RID raw in the request URL path; name-addressed paths continue to be percent-encoded. Previously the driver signed the full name-style resource link and percent-encoded the RID for every request, so RID-addressed reads were rejected with `401 Unauthorized`. ([#4640](https://github.com/Azure/azure-sdk-for-rust/pull/4640))
12+
13+
### Other Changes
14+
315
## 0.5.0 (2026-06-19)
416

517
### Features Added

sdk/cosmos/azure_data_cosmos_driver/src/driver/cache/container_cache.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ impl ContainerNameKey {
2828
fn from_container(c: &ContainerReference) -> Self {
2929
Self {
3030
account_endpoint: c.account().endpoint().as_str().to_owned(),
31-
db_name: c.database_name().to_owned(),
31+
db_name: c.database_name().unwrap_or_default().to_owned(),
3232
container_name: c.name().to_owned(),
3333
}
3434
}
@@ -378,8 +378,8 @@ mod tests {
378378
.await
379379
.unwrap();
380380

381-
assert_eq!(r1.database_name(), "db1");
382-
assert_eq!(r2.database_name(), "db2");
381+
assert_eq!(r1.database_name(), Some("db1"));
382+
assert_eq!(r2.database_name(), Some("db2"));
383383
}
384384

385385
// --- get returns none ---

sdk/cosmos/azure_data_cosmos_driver/src/driver/pipeline/operation_pipeline.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ use crate::{
2727
transport::CosmosTransport,
2828
},
2929
models::{
30-
cosmos_headers::QUERY_CONTENT_TYPE, request_header_names, AccountEndpoint, ActivityId,
31-
CosmosOperation, CosmosResponse, Credential, DefaultConsistencyLevel,
32-
EffectivePartitionKey, OperationType, SessionToken, SubStatusCode,
30+
cosmos_headers::QUERY_CONTENT_TYPE, encode_path_segments, request_header_names,
31+
AccountEndpoint, ActivityId, CosmosOperation, CosmosResponse, Credential,
32+
DefaultConsistencyLevel, EffectivePartitionKey, OperationType, SessionToken, SubStatusCode,
3333
},
3434
options::{
3535
HedgeThreshold, OperationOptionsView, ReadConsistencyStrategy, Region,
@@ -1269,7 +1269,17 @@ fn build_transport_request(
12691269
} else {
12701270
format!("/{}", request_path)
12711271
};
1272-
base.set_path(&normalized);
1272+
// Name-based paths are percent-encoded so the gateway reconstructs the
1273+
// same resource link we signed (names may contain reserved characters).
1274+
// RID-based paths must be sent raw: encoding the `=` padding of a base64
1275+
// RID makes the gateway treat the segment as a name and reject the
1276+
// RID-based signature. The authorization signature is derived from
1277+
// `paths` below (a lowercased RID for RID-addressed requests).
1278+
if paths.is_rid_based() {
1279+
base.set_path(&normalized);
1280+
} else {
1281+
base.set_path(&encode_path_segments(&normalized));
1282+
}
12731283
base
12741284
};
12751285

sdk/cosmos/azure_data_cosmos_driver/src/driver/routing/session_container.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,15 @@ struct SessionContainerInner {
3333
name_to_rid: HashMap<String, ResourceId>,
3434
}
3535

36-
/// Returns the `dbs/{db}/colls/{coll}` name path from a [`ContainerReference`],
37-
/// reusing the pre-computed `name_based_path` by skipping the leading `/`.
36+
/// Returns the container path used as the session-token index key, reusing the
37+
/// pre-computed path by skipping the leading `/`.
38+
///
39+
/// For name-addressed containers this is `dbs/{db}/colls/{coll}`; for RID-addressed
40+
/// containers it is the RID-based path. Either way it is stable per container and
41+
/// consistent between `set` and `resolve`, which is all the name→RID fallback needs.
3842
fn name_path(container: &ContainerReference) -> &str {
39-
// name_based_path() returns "/dbs/{db}/colls/{coll}"; skip the leading '/'.
40-
&container.name_based_path()[1..]
43+
// base_path() returns "/dbs/.../colls/..."; skip the leading '/'.
44+
&container.base_path()[1..]
4145
}
4246

4347
impl SessionContainer {

0 commit comments

Comments
 (0)