fix(nar_bridge): Don't check if root node has a name in nar generation
Nar-bridge tried to parse the name of the protobuf node encoded in the URL into a PathComponent but this name was empty, leading to an error when the user tried to retrieve the nar file. This commit removes this useless step and fixes the errors caused by it Change-Id: I2996cdd2e0107133e502748947298f512f1cc521
This commit is contained in:
parent
240b6a8ba4
commit
3389c550b9
3 changed files with 30 additions and 19 deletions
|
@ -46,7 +46,7 @@ pub enum DirectoryError {
|
||||||
DuplicateName(PathComponent),
|
DuplicateName(PathComponent),
|
||||||
/// Node failed validation
|
/// Node failed validation
|
||||||
#[error("invalid node with name {}: {:?}", .0, .1.to_string())]
|
#[error("invalid node with name {}: {:?}", .0, .1.to_string())]
|
||||||
InvalidNode(PathComponent, ValidateNodeError),
|
InvalidNode(String, ValidateNodeError),
|
||||||
#[error("Total size exceeds u64::MAX")]
|
#[error("Total size exceeds u64::MAX")]
|
||||||
SizeOverflow,
|
SizeOverflow,
|
||||||
/// Invalid name encountered
|
/// Invalid name encountered
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use prost::Message;
|
use prost::Message;
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
use bstr::ByteSlice;
|
||||||
|
|
||||||
mod grpc_blobservice_wrapper;
|
mod grpc_blobservice_wrapper;
|
||||||
mod grpc_directoryservice_wrapper;
|
mod grpc_directoryservice_wrapper;
|
||||||
|
|
||||||
|
@ -190,25 +193,40 @@ impl From<crate::Directory> for Directory {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl Node {
|
||||||
|
/// Converts a proto [Node] to a [crate::Node], and splits off the name.
|
||||||
|
pub fn into_node(self) -> Result<crate::Node, DirectoryError> {
|
||||||
|
let (_, node) = self.into_unvalidated_name_and_node()?;
|
||||||
|
Ok(node)
|
||||||
|
}
|
||||||
/// Converts a proto [Node] to a [crate::Node], and splits off the name.
|
/// Converts a proto [Node] to a [crate::Node], and splits off the name.
|
||||||
pub fn into_name_and_node(self) -> Result<(PathComponent, crate::Node), DirectoryError> {
|
pub fn into_name_and_node(self) -> Result<(PathComponent, crate::Node), DirectoryError> {
|
||||||
|
let (unvalidated_name, node) = self.into_unvalidated_name_and_node()?;
|
||||||
|
Ok((
|
||||||
|
unvalidated_name
|
||||||
|
.try_into()
|
||||||
|
.map_err(DirectoryError::InvalidName)?,
|
||||||
|
node,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_unvalidated_name_and_node(self) -> Result<(bytes::Bytes, crate::Node), DirectoryError> {
|
||||||
match self.node.ok_or_else(|| DirectoryError::NoNodeSet)? {
|
match self.node.ok_or_else(|| DirectoryError::NoNodeSet)? {
|
||||||
node::Node::Directory(n) => {
|
node::Node::Directory(n) => {
|
||||||
let name: PathComponent = n.name.try_into().map_err(DirectoryError::InvalidName)?;
|
let digest = B3Digest::try_from(n.digest).map_err(|e| {
|
||||||
let digest = B3Digest::try_from(n.digest)
|
DirectoryError::InvalidNode(n.name.as_bstr().to_string(), e.into())
|
||||||
.map_err(|e| DirectoryError::InvalidNode(name.clone(), e.into()))?;
|
})?;
|
||||||
|
|
||||||
let node = crate::Node::Directory {
|
let node = crate::Node::Directory {
|
||||||
digest,
|
digest,
|
||||||
size: n.size,
|
size: n.size,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((name, node))
|
Ok((n.name, node))
|
||||||
}
|
}
|
||||||
node::Node::File(n) => {
|
node::Node::File(n) => {
|
||||||
let name: PathComponent = n.name.try_into().map_err(DirectoryError::InvalidName)?;
|
let digest = B3Digest::try_from(n.digest).map_err(|e| {
|
||||||
let digest = B3Digest::try_from(n.digest)
|
DirectoryError::InvalidNode(n.name.as_bstr().to_string(), e.into())
|
||||||
.map_err(|e| DirectoryError::InvalidNode(name.clone(), e.into()))?;
|
})?;
|
||||||
|
|
||||||
let node = crate::Node::File {
|
let node = crate::Node::File {
|
||||||
digest,
|
digest,
|
||||||
|
@ -216,22 +234,20 @@ impl Node {
|
||||||
executable: n.executable,
|
executable: n.executable,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((name, node))
|
Ok((n.name, node))
|
||||||
}
|
}
|
||||||
|
|
||||||
node::Node::Symlink(n) => {
|
node::Node::Symlink(n) => {
|
||||||
let name: PathComponent = n.name.try_into().map_err(DirectoryError::InvalidName)?;
|
|
||||||
|
|
||||||
let node = crate::Node::Symlink {
|
let node = crate::Node::Symlink {
|
||||||
target: n.target.try_into().map_err(|e| {
|
target: n.target.try_into().map_err(|e| {
|
||||||
DirectoryError::InvalidNode(
|
DirectoryError::InvalidNode(
|
||||||
name.clone(),
|
n.name.as_bstr().to_string(),
|
||||||
crate::ValidateNodeError::InvalidSymlinkTarget(e),
|
crate::ValidateNodeError::InvalidSymlinkTarget(e),
|
||||||
)
|
)
|
||||||
})?,
|
})?,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((name, node))
|
Ok((n.name, node))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,16 +52,11 @@ pub async fn get(
|
||||||
StatusCode::NOT_FOUND
|
StatusCode::NOT_FOUND
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let (root_name, root_node) = root_node.into_name_and_node().map_err(|e| {
|
let root_node = root_node.into_node().map_err(|e| {
|
||||||
warn!(err=%e, "root node validation failed");
|
warn!(err=%e, "root node validation failed");
|
||||||
StatusCode::BAD_REQUEST
|
StatusCode::BAD_REQUEST
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if !root_name.as_ref().is_empty() {
|
|
||||||
warn!("root node has name, which it shouldn't");
|
|
||||||
return Err(StatusCode::BAD_REQUEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
let (w, r) = tokio::io::duplex(1024 * 8);
|
let (w, r) = tokio::io::duplex(1024 * 8);
|
||||||
|
|
||||||
// spawn a task rendering the NAR to the client
|
// spawn a task rendering the NAR to the client
|
||||||
|
|
Loading…
Reference in a new issue