mirror of
https://git.asonix.dog/asonix/pict-rs
synced 2024-12-22 19:31:35 +00:00
Add HEAD endpoints for process, serve
This commit is contained in:
parent
6281d5bca4
commit
e0543b2c1c
1 changed files with 119 additions and 5 deletions
124
src/main.rs
124
src/main.rs
|
@ -486,6 +486,50 @@ async fn process<R: FullRepo, S: Store + 'static>(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(name = "Serving processed image headers", skip(repo))]
|
||||||
|
async fn process_head<R: FullRepo, S: Store + 'static>(
|
||||||
|
range: Option<web::Header<Range>>,
|
||||||
|
query: web::Query<ProcessQuery>,
|
||||||
|
ext: web::Path<String>,
|
||||||
|
repo: web::Data<R>,
|
||||||
|
store: web::Data<S>,
|
||||||
|
) -> Result<HttpResponse, Error> {
|
||||||
|
let (format, alias, thumbnail_path, _) = prepare_process(query, ext.as_str())?;
|
||||||
|
|
||||||
|
repo.check_cached(&alias).await?;
|
||||||
|
|
||||||
|
let path_string = thumbnail_path.to_string_lossy().to_string();
|
||||||
|
let hash = repo.hash(&alias).await?;
|
||||||
|
let identifier_opt = repo
|
||||||
|
.variant_identifier::<S::Identifier>(hash.clone(), path_string)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if let Some(identifier) = identifier_opt {
|
||||||
|
let details = repo.details(&identifier).await?;
|
||||||
|
|
||||||
|
let details = if let Some(details) = details {
|
||||||
|
debug!("details exist");
|
||||||
|
details
|
||||||
|
} else {
|
||||||
|
debug!("generating new details from {:?}", identifier);
|
||||||
|
let new_details = Details::from_store(
|
||||||
|
(**store).clone(),
|
||||||
|
identifier.clone(),
|
||||||
|
Some(ValidInputType::from_format(format)),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
debug!("storing details for {:?}", identifier);
|
||||||
|
repo.relate_details(&identifier, &new_details).await?;
|
||||||
|
debug!("stored");
|
||||||
|
new_details
|
||||||
|
};
|
||||||
|
|
||||||
|
return ranged_file_head_resp(&**store, identifier, range, details).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(HttpResponse::NotFound().finish())
|
||||||
|
}
|
||||||
|
|
||||||
/// Process files
|
/// Process files
|
||||||
#[instrument(name = "Spawning image process", skip(repo))]
|
#[instrument(name = "Spawning image process", skip(repo))]
|
||||||
async fn process_backgrounded<R: FullRepo, S: Store>(
|
async fn process_backgrounded<R: FullRepo, S: Store>(
|
||||||
|
@ -543,6 +587,59 @@ async fn serve<R: FullRepo, S: Store + 'static>(
|
||||||
ranged_file_resp(&**store, identifier, range, details).await
|
ranged_file_resp(&**store, identifier, range, details).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(name = "Serving file headers", skip(repo))]
|
||||||
|
async fn serve_head<R: FullRepo, S: Store + 'static>(
|
||||||
|
range: Option<web::Header<Range>>,
|
||||||
|
alias: web::Path<Serde<Alias>>,
|
||||||
|
repo: web::Data<R>,
|
||||||
|
store: web::Data<S>,
|
||||||
|
) -> Result<HttpResponse, Error> {
|
||||||
|
let alias = alias.into_inner();
|
||||||
|
|
||||||
|
repo.check_cached(&alias).await?;
|
||||||
|
|
||||||
|
let identifier = repo.identifier_from_alias::<S::Identifier>(&alias).await?;
|
||||||
|
|
||||||
|
let details = ensure_details(&**repo, &**store, &alias).await?;
|
||||||
|
|
||||||
|
ranged_file_head_resp(&**store, identifier, range, details).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn ranged_file_head_resp<S: Store + 'static>(
|
||||||
|
store: &S,
|
||||||
|
identifier: S::Identifier,
|
||||||
|
range: Option<web::Header<Range>>,
|
||||||
|
details: Details,
|
||||||
|
) -> Result<HttpResponse, Error> {
|
||||||
|
let builder = if let Some(web::Header(range_header)) = range {
|
||||||
|
//Range header exists - return as ranged
|
||||||
|
if let Some(range) = range::single_bytes_range(&range_header) {
|
||||||
|
let len = store.len(&identifier).await?;
|
||||||
|
|
||||||
|
if let Some(content_range) = range::to_content_range(range, len) {
|
||||||
|
let mut builder = HttpResponse::PartialContent();
|
||||||
|
builder.insert_header(content_range);
|
||||||
|
builder
|
||||||
|
} else {
|
||||||
|
HttpResponse::RangeNotSatisfiable()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(UploadError::Range.into());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// no range header
|
||||||
|
HttpResponse::Ok()
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(srv_head(
|
||||||
|
builder,
|
||||||
|
details.content_type(),
|
||||||
|
7 * DAYS,
|
||||||
|
details.system_time(),
|
||||||
|
)
|
||||||
|
.finish())
|
||||||
|
}
|
||||||
|
|
||||||
async fn ranged_file_resp<S: Store + 'static>(
|
async fn ranged_file_resp<S: Store + 'static>(
|
||||||
store: &S,
|
store: &S,
|
||||||
identifier: S::Identifier,
|
identifier: S::Identifier,
|
||||||
|
@ -594,7 +691,7 @@ async fn ranged_file_resp<S: Store + 'static>(
|
||||||
|
|
||||||
// A helper method to produce responses with proper cache headers
|
// A helper method to produce responses with proper cache headers
|
||||||
fn srv_response<S, E>(
|
fn srv_response<S, E>(
|
||||||
mut builder: HttpResponseBuilder,
|
builder: HttpResponseBuilder,
|
||||||
stream: S,
|
stream: S,
|
||||||
ext: mime::Mime,
|
ext: mime::Mime,
|
||||||
expires: u32,
|
expires: u32,
|
||||||
|
@ -611,6 +708,16 @@ where
|
||||||
Err(e) => Err(Error::from(e).into()),
|
Err(e) => Err(Error::from(e).into()),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
srv_head(builder, ext, expires, modified).streaming(stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A helper method to produce responses with proper cache headers
|
||||||
|
fn srv_head(
|
||||||
|
mut builder: HttpResponseBuilder,
|
||||||
|
ext: mime::Mime,
|
||||||
|
expires: u32,
|
||||||
|
modified: SystemTime,
|
||||||
|
) -> HttpResponseBuilder {
|
||||||
builder
|
builder
|
||||||
.insert_header(LastModified(modified.into()))
|
.insert_header(LastModified(modified.into()))
|
||||||
.insert_header(CacheControl(vec![
|
.insert_header(CacheControl(vec![
|
||||||
|
@ -619,8 +726,9 @@ where
|
||||||
CacheDirective::Extension("immutable".to_owned(), None),
|
CacheDirective::Extension("immutable".to_owned(), None),
|
||||||
]))
|
]))
|
||||||
.insert_header((ACCEPT_RANGES, "bytes"))
|
.insert_header((ACCEPT_RANGES, "bytes"))
|
||||||
.content_type(ext.to_string())
|
.content_type(ext.to_string());
|
||||||
.streaming(stream)
|
|
||||||
|
builder
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(name = "Spawning variant cleanup", skip(repo))]
|
#[instrument(name = "Spawning variant cleanup", skip(repo))]
|
||||||
|
@ -837,9 +945,15 @@ async fn launch<R: FullRepo + Clone + 'static, S: Store + Clone + 'static>(
|
||||||
.route(web::get().to(delete::<R>)),
|
.route(web::get().to(delete::<R>)),
|
||||||
)
|
)
|
||||||
.service(
|
.service(
|
||||||
web::resource("/original/{filename}").route(web::get().to(serve::<R, S>)),
|
web::resource("/original/{filename}")
|
||||||
|
.route(web::get().to(serve::<R, S>))
|
||||||
|
.route(web::head().to(serve_head::<R, S>)),
|
||||||
|
)
|
||||||
|
.service(
|
||||||
|
web::resource("/process.{ext}")
|
||||||
|
.route(web::get().to(process::<R, S>))
|
||||||
|
.route(web::head().to(process_head::<R, S>)),
|
||||||
)
|
)
|
||||||
.service(web::resource("/process.{ext}").route(web::get().to(process::<R, S>)))
|
|
||||||
.service(
|
.service(
|
||||||
web::resource("/process_backgrounded.{ext}")
|
web::resource("/process_backgrounded.{ext}")
|
||||||
.route(web::get().to(process_backgrounded::<R, S>)),
|
.route(web::get().to(process_backgrounded::<R, S>)),
|
||||||
|
|
Loading…
Reference in a new issue