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:
sinavir 2024-09-22 21:28:39 +02:00
parent 240b6a8ba4
commit 3389c550b9
3 changed files with 30 additions and 19 deletions

View file

@ -46,7 +46,7 @@ pub enum DirectoryError {
DuplicateName(PathComponent),
/// Node failed validation
#[error("invalid node with name {}: {:?}", .0, .1.to_string())]
InvalidNode(PathComponent, ValidateNodeError),
InvalidNode(String, ValidateNodeError),
#[error("Total size exceeds u64::MAX")]
SizeOverflow,
/// Invalid name encountered

View file

@ -1,6 +1,9 @@
use prost::Message;
use std::cmp::Ordering;
use bstr::ByteSlice;
mod grpc_blobservice_wrapper;
mod grpc_directoryservice_wrapper;
@ -190,25 +193,40 @@ impl From<crate::Directory> for Directory {
}
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.
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)? {
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| DirectoryError::InvalidNode(name.clone(), e.into()))?;
let digest = B3Digest::try_from(n.digest).map_err(|e| {
DirectoryError::InvalidNode(n.name.as_bstr().to_string(), e.into())
})?;
let node = crate::Node::Directory {
digest,
size: n.size,
};
Ok((name, node))
Ok((n.name, node))
}
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| DirectoryError::InvalidNode(name.clone(), e.into()))?;
let digest = B3Digest::try_from(n.digest).map_err(|e| {
DirectoryError::InvalidNode(n.name.as_bstr().to_string(), e.into())
})?;
let node = crate::Node::File {
digest,
@ -216,22 +234,20 @@ impl Node {
executable: n.executable,
};
Ok((name, node))
Ok((n.name, node))
}
node::Node::Symlink(n) => {
let name: PathComponent = n.name.try_into().map_err(DirectoryError::InvalidName)?;
let node = crate::Node::Symlink {
target: n.target.try_into().map_err(|e| {
DirectoryError::InvalidNode(
name.clone(),
n.name.as_bstr().to_string(),
crate::ValidateNodeError::InvalidSymlinkTarget(e),
)
})?,
};
Ok((name, node))
Ok((n.name, node))
}
}
}

View file

@ -52,16 +52,11 @@ pub async fn get(
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");
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);
// spawn a task rendering the NAR to the client