Skip to content

Cosmos: Add Response Header traits #2589

@analogrelay

Description

@analogrelay

SDKs generated from TypeSpec include "Response Header traits", such as this one from azure_storage_blob:

pub trait AppendBlobClientAppendBlockResultHeaders: private::Sealed {
    fn content_md5(&self) -> Result<Option<String>>;
    fn date(&self) -> Result<Option<OffsetDateTime>>;
    fn last_modified(&self) -> Result<Option<OffsetDateTime>>;
    fn etag(&self) -> Result<Option<String>>;
    // ... snipped for brevity ...
}

impl AppendBlobClientAppendBlockResultHeaders for Response<AppendBlobClientAppendBlockResult> {
    /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the
    /// client can check for message content integrity.
    fn content_md5(&self) -> Result<Option<String>> {
        Headers::get_optional_as(self.headers(), &CONTENT_MD5)
    }

    /// UTC date/time value generated by the service that indicates the time at which the response was initiated
    fn date(&self) -> Result<Option<OffsetDateTime>> {
        Headers::get_optional_with(self.headers(), &DATE, |h| date::parse_rfc7231(h.as_str()))
    }

    /// The date/time that the container was last modified.
    fn last_modified(&self) -> Result<Option<OffsetDateTime>> {
        Headers::get_optional_with(self.headers(), &LAST_MODIFIED, |h| {
            date::parse_rfc7231(h.as_str())
        })
    }

    /// The ETag contains a value that you can use to perform operations conditionally.
    fn etag(&self) -> Result<Option<String>> {
        Headers::get_optional_as(self.headers(), &ETAG)
    }
    // ... snipped for brevity ...
}

These traits make it possible to call the methods they define on a Response to read the relevant response headers without needing to know the name or format of the header (note that headers like last_modified are parsed by these methods):

let resp = client.some_method();
println!("Last Modified: {:?}", resp.last_modified()?);

We should implement something similar for Cosmos, as we have several response headers that are relevant, such as the number of RUs expended by a request.

One thing that makes this a little tricky for Cosmos is that we have several methods that return "generic" Responses (either Response or Response<T> for some user-provided model type T, when reading items). That means we don't have a unique type to apply the trait to, in order to ensure the methods only appear for the correct responses. TypeSpec-generated clients seem to use zero-sized marker types (like pub struct AppendBlobClientAppendBlockResult) which might work for this.

Metadata

Metadata

Assignees

Labels

CosmosThe azure_cosmos crate

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions