feat(registry): package versions endpoint

This commit is contained in:
daimond113 2024-03-10 19:02:33 +01:00
parent d20fb4aee3
commit f2758c6351
No known key found for this signature in database
GPG key ID: 3A8ECE51328B513C
3 changed files with 54 additions and 5 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "pesde-registry" name = "pesde-registry"
version = "0.2.0" version = "0.3.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]

View file

@ -1,6 +1,7 @@
use actix_multipart::form::{bytes::Bytes, MultipartForm}; use actix_multipart::form::{bytes::Bytes, MultipartForm};
use actix_web::{web, HttpResponse, Responder}; use actix_web::{web, HttpResponse, Responder};
use flate2::read::GzDecoder; use flate2::read::GzDecoder;
use log::error;
use reqwest::StatusCode; use reqwest::StatusCode;
use rusty_s3::S3Action; use rusty_s3::S3Action;
use tantivy::{doc, Term}; use tantivy::{doc, Term};
@ -159,15 +160,28 @@ pub async fn get_package_version(
app_state: web::Data<AppState>, app_state: web::Data<AppState>,
path: web::Path<(String, String, String)>, path: web::Path<(String, String, String)>,
) -> Result<impl Responder, errors::Errors> { ) -> Result<impl Responder, errors::Errors> {
let (scope, name, version) = path.into_inner(); let (scope, name, mut version) = path.into_inner();
let package_name = PackageName::new(&scope, &name)?; let package_name = PackageName::new(&scope, &name)?;
{ {
let index = app_state.index.lock().unwrap(); let index = app_state.index.lock().unwrap();
if !index.package(&package_name)?.is_some() { match index.package(&package_name)? {
return Ok(HttpResponse::NotFound().finish()); 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) => { Err(e) => {
if let Some(status) = e.status() { if let Some(status) = e.status() {
if status == StatusCode::NOT_FOUND { 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?)) Ok(HttpResponse::Ok().body(response.bytes().await?))
} }
pub async fn get_package_versions(
app_state: web::Data<AppState>,
path: web::Path<(String, String)>,
) -> Result<impl Responder, errors::Errors> {
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::<Vec<String>>();
Ok(HttpResponse::Ok().json(versions))
}
None => Ok(HttpResponse::NotFound().finish()),
}
}
}

View file

@ -292,6 +292,12 @@ fn main() -> std::io::Result<()> {
.to(endpoints::search::search_packages) .to(endpoints::search::search_packages)
.wrap(Governor::new(&generic_governor_config)), .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( .route(
"/packages/{scope}/{name}/{version}", "/packages/{scope}/{name}/{version}",
web::get() web::get()