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), 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

View file

@ -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))
} }
} }
} }

View file

@ -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