diff --git a/src/blob.rs b/src/blob.rs index 07042fa..7ddd5c5 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -11,6 +11,10 @@ use crate::errors::DigestError; pub struct SizedStream { /// The length of the stream if the upstream registry sent a `Content-Length` header pub content_length: Option, + /// The digest header value if the upstream registry sent a `Digest` header. This should be used + /// (in addition to the layer digest) for validation when using partial requests as the library + /// can't validate against the full response. + pub digest_header_value: Option, /// The stream of bytes pub stream: BoxStream<'static, Result>, } diff --git a/src/client.rs b/src/client.rs index 211411d..5c79d5f 100644 --- a/src/client.rs +++ b/src/client.rs @@ -323,7 +323,7 @@ impl TryFrom for Client { let no_proxy = config .no_proxy .as_ref() - .and_then(|no_proxy| NoProxy::from_string(&no_proxy)); + .and_then(|no_proxy| NoProxy::from_string(no_proxy)); let proxy = Proxy::https(proxy_addr)?.no_proxy(no_proxy); client_builder = client_builder.proxy(proxy); } @@ -1137,10 +1137,15 @@ impl Client { ) } - /// Stream a single layer from an OCI registry starting with a byte offset. - /// This can be used to continue downloading a layer after a network error. + /// Stream a single layer from an OCI registry starting with a byte offset. This can be used to + /// continue downloading a layer after a network error. Please note that when doing a partial + /// download (meaning it returns the [`BlobResponse::Partial`] variant), the layer digest is not + /// verified as all the bytes are not available. The returned blob response will contain the + /// header from the request digest, if it was set, that can be used (in addition to the digest + /// from the layer) to verify the blob once all the bytes have been downloaded. Failure to do + /// this means your content will not be verified. /// - /// Returns [`Stream`](futures_util::Stream). + /// Returns [`BlobResponse`] which indicates if the response was a full or partial response. pub async fn pull_blob_stream_partial( &self, image: &Reference, @@ -1640,6 +1645,9 @@ fn stream_from_response( Some(digest) => Some((Digester::new(&digest)?, digest)), None => None, }; + let header_digest = header_digester_and_digest + .as_ref() + .map(|(_, digest)| digest.to_owned()); let stream: BoxStream<'static, std::result::Result> = if verify { Box::pin(VerifyingStream::new( Box::pin(stream), @@ -1652,6 +1660,7 @@ fn stream_from_response( }; Ok(SizedStream { content_length, + digest_header_value: header_digest, stream, }) } diff --git a/src/manifest.rs b/src/manifest.rs index f4cb00e..b6d2550 100644 --- a/src/manifest.rs +++ b/src/manifest.rs @@ -421,6 +421,7 @@ pub struct Platform { /// This OPTIONAL property specifies an array of strings, each specifying a mandatory OS feature. /// When `os` is `windows`, image indexes SHOULD use, and implementations SHOULD understand the following values: /// - `win32k`: image requires `win32k.sys` on the host (Note: `win32k.sys` is missing on Nano Server) + /// /// When `os` is not `windows`, values are implementation-defined and SHOULD be submitted to this specification for standardization. #[serde(rename = "os.features")] #[serde(skip_serializing_if = "Option::is_none")]