kellnr-docs 6.2.0

Kellnr is a self-hosted registry for Rust crates with support for rustdocs and crates.io caching.
Documentation
use std::io::Cursor;
use std::path::Path;

use axum::body::{Body, Bytes};
use axum::extract::FromRequest;
use axum::http::Request;
use kellnr_appstate::AppStateData;
use kellnr_error::api_error::{ApiError, ApiResult};
use kellnr_registry::registry_error::RegistryError;
use zip::ZipArchive;

type Zip = ZipArchive<Cursor<Vec<u8>>>;

pub struct DocArchive(Zip);

impl DocArchive {
    pub fn extract(&mut self, path: &Path) -> ApiResult<()> {
        Ok(self.0.extract(path)?)
    }
}

impl FromRequest<AppStateData, Body> for DocArchive {
    type Rejection = ApiError;

    async fn from_request(
        req: Request<Body>,
        state: &AppStateData,
    ) -> Result<Self, Self::Rejection> {
        let data_bytes: Vec<u8> = Bytes::from_request(req, state)
            .await
            .map_err(RegistryError::ExtractBytesFailed)?
            .to_vec();

        let max_docs_size = state.settings.docs.max_size * 1_000_000;
        if data_bytes.len() > max_docs_size {
            return Err(RegistryError::InvalidMinLength(data_bytes.len(), max_docs_size).into());
        }

        let reader = Cursor::new(data_bytes);

        match ZipArchive::new(reader) {
            Ok(zip) => Ok(DocArchive(zip)),
            Err(e) => Err(ApiError::from(e)),
        }
    }
}