aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/error.rs3
-rw-r--r--src/get_routes.rs59
-rw-r--r--src/main.rs7
3 files changed, 41 insertions, 28 deletions
diff --git a/src/error.rs b/src/error.rs
index 8460376..0a36476 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -2,6 +2,7 @@ use sputnik::hyper_body::FormError;
use sputnik::request::QueryError;
use std::str::Utf8Error;
+/// For convenience this enum also contains nonerroneous variants.
pub enum Error {
/// A 400 bad request error.
BadRequest(String),
@@ -13,6 +14,8 @@ pub enum Error {
NotFound(String),
/// A 500 internal server error.
Internal(String),
+ /// A 304 response.
+ NotModified,
/// A 302 redirect to the given path.
Redirect(String),
diff --git a/src/get_routes.rs b/src/get_routes.rs
index 57d7e56..cde88c3 100644
--- a/src/get_routes.rs
+++ b/src/get_routes.rs
@@ -8,8 +8,6 @@ use git2::Tree;
use git2::TreeEntry;
use hyper::header;
use hyper::http::request::Parts;
-use hyper::http::response::Builder;
-use hyper::StatusCode;
use serde::Deserialize;
use sputnik::html_escape;
use sputnik::request::SputnikParts;
@@ -310,11 +308,9 @@ fn diff_blob<C: Controller>(
Ok(page.into())
}
-fn raw_blob<C: Controller>(
+fn build_raw_response(
entr: TreeEntry,
- _params: ActionParam,
- _controller: &C,
- ctx: Context,
+ ctx: &Context,
parts: &Parts,
) -> Result<HyperResponse, Error> {
if let Some(etag) = parts
@@ -323,11 +319,7 @@ fn raw_blob<C: Controller>(
.and_then(|v| v.to_str().ok())
{
if etag.trim_matches('"') == entr.id().to_string() {
- return Ok(Builder::new()
- .status(StatusCode::NOT_MODIFIED)
- .body("".into())
- .unwrap()
- .into());
+ return Err(Error::NotModified);
}
}
@@ -338,25 +330,36 @@ fn raw_blob<C: Controller>(
.insert(header::ETAG, format!("\"{}\"", entr.id()).parse().unwrap());
resp.headers_mut()
.insert(header::CACHE_CONTROL, "no-cache".parse().unwrap());
+ Ok(resp)
+}
- if let Some(mime) = mime_guess::from_path(&ctx.path).first() {
- if mime.type_() == "text" {
- // workaround for Firefox, which downloads non-plain text subtypes
- // instead of displaying them (https://bugzilla.mozilla.org/1319262)
- resp.headers_mut()
- .insert(header::CONTENT_TYPE, "text/plain".parse().unwrap());
- } else {
- resp.headers_mut()
- .insert(header::CONTENT_TYPE, mime.to_string().parse().unwrap());
+fn raw_blob<C: Controller>(
+ entr: TreeEntry,
+ _params: ActionParam,
+ _controller: &C,
+ ctx: Context,
+ parts: &Parts,
+) -> Result<HyperResponse, Error> {
+ build_raw_response(entr, &ctx, parts).map(|mut resp| {
+ if let Some(mime) = mime_guess::from_path(&ctx.path).first() {
+ if mime.type_() == "text" {
+ // workaround for Firefox, which downloads non-plain text subtypes
+ // instead of displaying them (https://bugzilla.mozilla.org/1319262)
+ resp.headers_mut()
+ .insert(header::CONTENT_TYPE, "text/plain".parse().unwrap());
+ } else {
+ resp.headers_mut()
+ .insert(header::CONTENT_TYPE, mime.to_string().parse().unwrap());
+ }
}
- }
- Ok(resp)
+ resp
+ })
}
fn run_blob<C: Controller>(
entr: TreeEntry,
- params: ActionParam,
- controller: &C,
+ _params: ActionParam,
+ _controller: &C,
ctx: Context,
parts: &Parts,
) -> Result<HyperResponse, Error> {
@@ -365,18 +368,18 @@ fn run_blob<C: Controller>(
"run action only available for .html files".into(),
));
}
- raw_blob(entr, params, controller, ctx, parts).map(|mut r| {
- r.headers_mut()
+ build_raw_response(entr, &ctx, parts).map(|mut resp| {
+ resp.headers_mut()
.insert(header::CONTENT_TYPE, "text/html".parse().unwrap());
// We want users to be able to view .html applications of other users
// without having to worry about the application accessing their private
// files. So we set the CSP: sandbox header which makes browsers treat
// the page as a unique origin as per the same-origin policy.
- r.headers_mut().insert(
+ resp.headers_mut().insert(
header::CONTENT_SECURITY_POLICY,
"sandbox allow-scripts;".parse().unwrap(),
);
- r
+ resp
})
}
diff --git a/src/main.rs b/src/main.rs
index 58431a2..d3c88f6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -21,6 +21,7 @@ use serde::Deserialize;
use sputnik::html_escape;
use sputnik::mime;
use sputnik::request::SputnikParts;
+use sputnik::response::EmptyBuilder;
use sputnik::response::SputnikBuilder;
use std::convert::Infallible;
use std::env;
@@ -241,6 +242,12 @@ async fn service<C: Controller>(
Error::Forbidden(msg) => (403, msg),
Error::NotFound(msg) => (404, msg),
Error::Internal(msg) => (500, msg),
+ Error::NotModified => {
+ return Builder::new()
+ .status(StatusCode::NOT_MODIFIED)
+ .empty()
+ .unwrap();
+ }
Error::MissingTrailingSlash(path) => {
return Builder::new()
.status(StatusCode::FOUND)