}
async fn stdout(
State(config): State<Config>,
Path(job): Path<uuid::Uuid>,
range: Option<TypedHeader<Range>>,
) -> Response {
debug!("stdout {:?} {:?}", job, range);
let Ok(mut file) =
tokio::fs::File::open(&config.config.ci_path.join(&format!("{}.stdout", job))).await
else {
return StatusCode::NOT_FOUND.into_response();
};
if let Some(TypedHeader(range)) = range {
use tokio::io::AsyncSeekExt;
match range.satisfiable_ranges(0).next() {
Some((std::ops::Bound::Included(a), std::ops::Bound::Unbounded)) => {
use tokio::io::AsyncReadExt;
let mut v = Vec::new();
file.seek(std::io::SeekFrom::Start(a)).await.unwrap();
file.read_to_end(&mut v).await.unwrap();
v.into_response()
}
None => {
use tokio::io::AsyncReadExt;
let mut v = Vec::new();
file.read_to_end(&mut v).await.unwrap();
v.into_response()
}
r => {
panic!("range = {:?}", r)
}
}
} else {
use tokio::io::AsyncReadExt;
let mut v = Vec::new();
file.read_to_end(&mut v).await.unwrap();
v.into_response()
}
}
async fn stderr(
State(config): State<Config>,
Path(job): Path<uuid::Uuid>,
range: Option<TypedHeader<Range>>,
) -> Response {
debug!("stderr {:?} {:?}", job, range);
let Ok(mut file) =
tokio::fs::File::open(&config.config.ci_path.join(&format!("{}.stderr", job))).await
else {
return StatusCode::NOT_FOUND.into_response();
};
if let Some(TypedHeader(range)) = range {
use tokio::io::AsyncSeekExt;
match range.satisfiable_ranges(0).next() {
Some((std::ops::Bound::Included(a), std::ops::Bound::Unbounded)) => {
use tokio::io::AsyncReadExt;
let mut v = Vec::new();
file.seek(std::io::SeekFrom::Start(a)).await.unwrap();
file.read_to_end(&mut v).await.unwrap();
v.into_response()
}
None => {
use tokio::io::AsyncReadExt;
let mut v = Vec::new();
file.read_to_end(&mut v).await.unwrap();
v.into_response()
}
r => {
panic!("r {:?}", r);
}
}
} else {
use tokio::io::AsyncReadExt;
let mut v = Vec::new();
file.read_to_end(&mut v).await.unwrap();
v.into_response()
}