diff --git a/registry/Cargo.toml b/registry/Cargo.toml index 64b9f0c..00d90d6 100644 --- a/registry/Cargo.toml +++ b/registry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pesde-registry" -version = "0.2.0" +version = "0.3.0" edition = "2021" [dependencies] diff --git a/registry/src/endpoints/packages.rs b/registry/src/endpoints/packages.rs index 1a49e91..8fe6061 100644 --- a/registry/src/endpoints/packages.rs +++ b/registry/src/endpoints/packages.rs @@ -1,6 +1,7 @@ use actix_multipart::form::{bytes::Bytes, MultipartForm}; use actix_web::{web, HttpResponse, Responder}; use flate2::read::GzDecoder; +use log::error; use reqwest::StatusCode; use rusty_s3::S3Action; use tantivy::{doc, Term}; @@ -159,15 +160,28 @@ pub async fn get_package_version( app_state: web::Data, path: web::Path<(String, String, String)>, ) -> Result { - let (scope, name, version) = path.into_inner(); + let (scope, name, mut version) = path.into_inner(); let package_name = PackageName::new(&scope, &name)?; { let index = app_state.index.lock().unwrap(); - if !index.package(&package_name)?.is_some() { - return Ok(HttpResponse::NotFound().finish()); + match index.package(&package_name)? { + Some(package) => { + if version == "latest" { + version = package + .iter() + .max_by(|a, b| a.version.cmp(&b.version)) + .map(|v| v.version.to_string()) + .unwrap(); + } else { + if !package.iter().any(|v| v.version.to_string() == version) { + return Ok(HttpResponse::NotFound().finish()); + } + } + } + None => return Ok(HttpResponse::NotFound().finish()), } } @@ -190,7 +204,11 @@ pub async fn get_package_version( Err(e) => { if let Some(status) = e.status() { if status == StatusCode::NOT_FOUND { - return Ok(HttpResponse::NotFound().finish()); + error!( + "package {}@{} not found in S3, but found in index", + package_name, version + ); + return Ok(HttpResponse::InternalServerError().finish()); } } @@ -200,3 +218,28 @@ pub async fn get_package_version( Ok(HttpResponse::Ok().body(response.bytes().await?)) } + +pub async fn get_package_versions( + app_state: web::Data, + path: web::Path<(String, String)>, +) -> Result { + let (scope, name) = path.into_inner(); + + let package_name = PackageName::new(&scope, &name)?; + + { + let index = app_state.index.lock().unwrap(); + + match index.package(&package_name)? { + Some(package) => { + let versions = package + .iter() + .map(|v| v.version.to_string()) + .collect::>(); + + Ok(HttpResponse::Ok().json(versions)) + } + None => Ok(HttpResponse::NotFound().finish()), + } + } +} diff --git a/registry/src/main.rs b/registry/src/main.rs index 5c2f4af..0c5f0a8 100644 --- a/registry/src/main.rs +++ b/registry/src/main.rs @@ -292,6 +292,12 @@ fn main() -> std::io::Result<()> { .to(endpoints::search::search_packages) .wrap(Governor::new(&generic_governor_config)), ) + .route( + "/packages/{scope}/{name}/versions", + web::get() + .to(endpoints::packages::get_package_versions) + .wrap(Governor::new(&generic_governor_config)), + ) .route( "/packages/{scope}/{name}/{version}", web::get()