pub fn response(s3: &Arc<dyn S3 + Send + Sync>, req: &Request<Body>, response_body: &[u8]) -> Result<Response<Body>, (StatusCode, &'static str)> {
    let mut res: UpstreamResponse = serde_json::from_slice(response_body).map_err(|e| {
        log::error!("Invalid upstream response JSON: {}", e);
        (StatusCode::INTERNAL_SERVER_ERROR, "Failed to parse upstream request")
    })?;

    res.entries.sort();

    let etag = {
        //TODO: use a hash function that is stable across releases and architectures
        let mut hasher = std::collections::hash_map::DefaultHasher::new();
        res.hash(&mut hasher);
        format!("{:x}", hasher.finish())
    };
    
    let entries: Vec<ZipEntry> = res.entries.into_iter().map(|file| {
        ZipEntry {
            archive_path: file.archive_name,
            crc: file.crc,
            data: Box::new(S3Object { 
                s3: s3.clone(),
                bucket: file.source.bucket,
                key: file.source.key,
                len: file.length
            }),
            last_modified: file.last_modified,
        }
    }).collect();

    let num_entries = entries.len();

    let stream = zip_stream(entries, ZipOptions::default());

    log::info!("Streaming zip file {}: {} entries, {} bytes", res.filename, num_entries, stream.len());

    Ok(hyper_response(&req, "application/zip", &etag, &res.filename, &stream))
}
/// Parse an upstream JSON response and produce a streaming zip file response
Parse an upstream JSON response and produce a streaming zip file response
Parse an upstream JSON response and produce a streaming zip file response
pub fn response(s3: &Arc<dyn S3 + Send + Sync>, req: &Request<Body>, response_body: &[u8]) -> Result<Response<Body>, (StatusCode, &'static str)> {
    let mut res: UpstreamResponse = serde_json::from_slice(response_body).map_err(|e| {
        log::error!("Invalid upstream response JSON: {}", e);
        (StatusCode::INTERNAL_SERVER_ERROR, "Failed to parse upstream request")
    })?;
    res.entries.sort();
    let etag = {
        //TODO: use a hash function that is stable across releases and architectures
        let mut hasher = std::collections::hash_map::DefaultHasher::new();
        res.hash(&mut hasher);
        format!("{:x}", hasher.finish())
    };
    let entries: Vec<ZipEntry> = res.entries.into_iter().map(|file| {
        ZipEntry {
            archive_path: file.archive_name,
            crc: file.crc,
            data: Box::new(S3Object { 
                s3: s3.clone(),
                bucket: file.source.bucket,
                key: file.source.key,
                len: file.length
            }),
            last_modified: file.last_modified,
        }
    }).collect();
    let num_entries = entries.len();
    let stream = zip_stream(entries, ZipOptions::default());
    log::info!("Streaming zip file {}: {} entries, {} bytes", res.filename, num_entries, stream.len());
    Ok(hyper_response(&req, "application/zip", &etag, &res.filename, &stream))
}
pub fn response ( s3 : & Arc < dyn S3 + Send + Sync > , req : & Request < Body > , response_body : & [ u8 ] ) -> Result < Response < Body > , ( StatusCode , & ' static str ) > { let mut res : UpstreamResponse = serde_json :: from_slice ( response_body ) . map_err ( | e | { log :: error ! ( " " e ) ; ( StatusCode :: INTERNAL_SERVER_ERROR , " " ) } ) ? ; res . entries . sort ( ) ; let etag = { //TODO: use a hash function that is stable across releases and architectures let mut hasher = std :: collections :: hash_map :: DefaultHasher :: new ( ) ; res . hash ( & mut hasher ) ; format ! ( " " hasher finish ( ) ) } ; let entries : Vec < ZipEntry > = res . entries . into_iter ( ) . map ( | file | { ZipEntry { archive_path : file . archive_name , crc : file . crc , data : Box :: new ( S3Object { s3 : s3 . clone ( ) , bucket : file . source . bucket , key : file . source . key , len : file . length } ) , last_modified : file . last_modified , } } ) . collect ( ) ; let num_entries = entries . len ( ) ; let stream = zip_stream ( entries , ZipOptions :: default ( ) ) ; log :: info ! ( " " res filename num_entries stream len ( ) ) ; Ok ( hyper_response ( & req , " " , & etag , & res . filename , & stream ) ) }
Parse an upstream JSON response and produce a streaming zip file response
Parse an upstream JSON response and produce a streaming zip file response
s3
&Arc<dyn S3 + Send + Sync>
req
&Request<Body>
response_body
&[u8]
s3
&Arc<dyn S3 + Send + Sync>
req
&Request<Body>
response_body
&[u8]