Skip to content

Conversation

@vincenttran-msft
Copy link
Member

@vincenttran-msft vincenttran-msft commented Nov 3, 2025

Generated code pointing to old policy name issue:

C:\azure-sdk-for-rust\sdk\storage\azure_storage_blob\tests>cargo test --test blob_container_client test_container_access -- -nocapture
Blocking waiting for file lock on build directory
Compiling azure_storage_blob v0.7.0 (C:\azure-sdk-for-rust\sdk\storage\azure_storage_blob)
error[E0432]: unresolved import azure_core::http::policies::BearerTokenCredentialPolicy
--> sdk\storage\azure_storage_blob\src\generated\clients\append_blob_client.rs:18:20
|
18 | policies::{BearerTokenCredentialPolicy, Policy},
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no BearerTokenCredentialPolicy in http::policies
..
..
For more information about this error, try rustc --explain E0432.
error: could not compile azure_storage_blob (lib) due to 6 previous errors

6x instances of this, seems like another issue with specifying the right version in emitter-package.json.

Change from PageIterator to Pager issue:

Error: Error { context: Custom(Custom { kind: DataConversion, error: Error("expected value", line: 1, column: 1) }) }

Relevant code excerpt:

let mut list_blobs_response = container_client.list_blobs(None)?;

// Old code against PageIterator
    // let page = list_blobs_response.try_next().await?;
    // let list_blob_segment_response = page.unwrap().into_body()?;
    // let blob_list = list_blob_segment_response.segment.blob_items;
    // for blob in blob_list {
    //     let blob_name = blob.name.unwrap().content.unwrap();
    //     let properties = blob.properties.unwrap();
    //     let blob_type = properties.blob_type.unwrap();
    //     let etag = properties.etag;
    //     assert!(blob_names.contains(&blob_name));
    //     assert_eq!(BlobType::BlockBlob, blob_type);
    //     assert!(etag.is_some());
    // }

// New code against Pager
    while let Some(blob_result) = list_blobs_response.next().await {
        let blob = blob_result?;
        let blob_name = blob.name.unwrap().content.unwrap();
        let properties = blob.properties.unwrap();
        let blob_type = properties.blob_type.unwrap();
        let etag = properties.etag;
        assert!(blob_names.contains(&blob_name));
        assert_eq!(BlobType::BlockBlob, blob_type);
        assert!(etag.is_some());
    }

@github-actions github-actions bot added the Storage Storage Service (Queues, Blobs, Files) label Nov 3, 2025
…ling list blobs test and work on simplest case first
Comment on lines 94 to 142
#[recorded::test]
async fn test_list_blobs(ctx: TestContext) -> Result<(), Box<dyn Error>> {
// Recording Setup
let recording = ctx.recording();
let container_client = get_container_client(recording, false).await?;
let blob_names = ["testblob1".to_string(), "testblob2".to_string()];

container_client.create_container(None).await?;
create_test_blob(
&container_client.blob_client(&blob_names[0].clone()),
None,
None,
)
.await?;
create_test_blob(
&container_client.blob_client(&blob_names[1].clone()),
None,
None,
)
.await?;

let mut list_blobs_response = container_client.list_blobs(None)?;

let page = list_blobs_response.try_next().await?;
let list_blob_segment_response = page.unwrap().into_body()?;
let blob_list = list_blob_segment_response.segment.blob_items;
for blob in blob_list {
// let page = list_blobs_response.try_next().await?;
// let list_blob_segment_response = page.unwrap().into_body()?;
// let blob_list = list_blob_segment_response.segment.blob_items;
// for blob in blob_list {
// let blob_name = blob.name.unwrap().content.unwrap();
// let properties = blob.properties.unwrap();
// let blob_type = properties.blob_type.unwrap();
// let etag = properties.etag;
// assert!(blob_names.contains(&blob_name));
// assert_eq!(BlobType::BlockBlob, blob_type);
// assert!(etag.is_some());
// }

while let Some(blob_result) = list_blobs_response.next().await {
let blob = blob_result?;
let blob_name = blob.name.unwrap().content.unwrap();
let properties = blob.properties.unwrap();
let blob_type = properties.blob_type.unwrap();
let etag = properties.etag;
assert!(blob_names.contains(&blob_name));
assert_eq!(BlobType::BlockBlob, blob_type);
assert!(etag.is_some());
}

container_client.delete_container(None).await?;
Ok(())
Copy link
Member Author

Choose a reason for hiding this comment

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

Relevant test case that I refactored to now work against the newly returned Pager, but this is hitting an error:

Error: Error { context: Custom(Custom { kind: DataConversion, error: Error("expected value", line: 1, column: 1) }) }

Comment on lines 800 to 886
pub fn list_blob_flat_segment(
&self,
options: Option<BlobContainerClientListBlobFlatSegmentOptions<'_>>,
) -> Result<PageIterator<Response<ListBlobsFlatSegmentResponse, XmlFormat>>> {
) -> Result<Pager<ListBlobsFlatSegmentResponse>> {
let options = options.unwrap_or_default().into_owned();
let pipeline = self.pipeline.clone();
let mut first_url = self.endpoint.clone();
first_url
.query_pairs_mut()
.append_pair("comp", "list")
.append_key_only("flat")
.append_pair("restype", "container");
if let Some(include) = options.include {
first_url.query_pairs_mut().append_pair(
"include",
&include
.iter()
.map(|i| i.to_string())
.collect::<Vec<String>>()
.join(","),
);
}
if let Some(marker) = options.marker {
first_url.query_pairs_mut().append_pair("marker", &marker);
}
if let Some(maxresults) = options.maxresults {
first_url
.query_pairs_mut()
.append_pair("maxresults", &maxresults.to_string());
}
if let Some(prefix) = options.prefix {
first_url.query_pairs_mut().append_pair("prefix", &prefix);
}
if let Some(timeout) = options.timeout {
first_url
.query_pairs_mut()
.append_pair("timeout", &timeout.to_string());
}
let version = self.version.clone();
Ok(PageIterator::from_callback(
move |marker: PagerState<String>| {
let mut url = first_url.clone();
if let PagerState::More(marker) = marker {
if url.query_pairs().any(|(name, _)| name.eq("marker")) {
let mut new_url = url.clone();
new_url
.query_pairs_mut()
.clear()
.extend_pairs(url.query_pairs().filter(|(name, _)| name.ne("marker")));
url = new_url;
}
url.query_pairs_mut().append_pair("marker", &marker);
Ok(Pager::from_callback(move |marker: PagerState<String>| {
let mut url = first_url.clone();
if let PagerState::More(marker) = marker {
if url.query_pairs().any(|(name, _)| name.eq("marker")) {
let mut new_url = url.clone();
new_url
.query_pairs_mut()
.clear()
.extend_pairs(url.query_pairs().filter(|(name, _)| name.ne("marker")));
url = new_url;
}
let mut request = Request::new(url, Method::Get);
request.insert_header("accept", "application/xml");
request.insert_header("content-type", "application/xml");
if let Some(client_request_id) = &options.client_request_id {
request.insert_header("x-ms-client-request-id", client_request_id);
}
request.insert_header("x-ms-version", &version);
let ctx = options.method_options.context.clone();
let pipeline = pipeline.clone();
async move {
let rsp = pipeline
.send(
&ctx,
&mut request,
Some(PipelineSendOptions {
check_success: CheckSuccessOptions {
success_codes: &[200],
},
..Default::default()
}),
)
.await?;
let (status, headers, body) = rsp.deconstruct();
let res: ListBlobsFlatSegmentResponse = xml::from_xml(&body)?;
let rsp = RawResponse::from_bytes(status, headers, body).into();
Ok(match res.next_marker {
Some(next_marker) if !next_marker.is_empty() => PagerResult::More {
response: rsp,
continuation: next_marker,
},
_ => PagerResult::Done { response: rsp },
})
}
},
))
url.query_pairs_mut().append_pair("marker", &marker);
}
let mut request = Request::new(url, Method::Get);
request.insert_header("accept", "application/xml");
request.insert_header("content-type", "application/xml");
if let Some(client_request_id) = &options.client_request_id {
request.insert_header("x-ms-client-request-id", client_request_id);
}
request.insert_header("x-ms-version", &version);
let ctx = options.method_options.context.clone();
let pipeline = pipeline.clone();
async move {
let rsp = pipeline
.send(
&ctx,
&mut request,
Some(PipelineSendOptions {
check_success: CheckSuccessOptions {
success_codes: &[200],
},
..Default::default()
}),
)
.await?;
let (status, headers, body) = rsp.deconstruct();
let res: ListBlobsFlatSegmentResponse = xml::from_xml(&body)?;
let rsp = RawResponse::from_bytes(status, headers, body).into();
Ok(match res.next_marker {
Some(next_marker) if !next_marker.is_empty() => PagerResult::More {
response: rsp,
continuation: next_marker,
},
_ => PagerResult::Done { response: rsp },
})
}
}))
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Example diff of what changed in generated functions for PageIterator -> Pager.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Storage Storage Service (Queues, Blobs, Files)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant