qrock 0.2.2

Helpers for Rocket HTTP server applications.
Documentation
use std::path::Path;

use rocket::{
  http::{hyper::header::CACHE_CONTROL, ContentType, Header},
  response::{self, Responder},
  Request, Response
};


#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NoCache<R>(pub R);

/// Reponse wrapper that sets the `Cache-Control` header to `no-store`.
///
/// ```
/// use qrock::response::NoCache;
/// use rocket::{response::{self, content::RawHtml, Responder}, get};
///
/// #[get("/")]
/// pub fn root_unauth() -> NoCache<RawHtml<String>> {
///   let buf = String::from("<p>hello</p>");
///   NoCache(RawHtml(buf))
/// }
/// ```
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for NoCache<R> {
  fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {
    let mut build = Response::build();
    build.merge(self.0.respond_to(req)?);

    let hdr = Header::new(CACHE_CONTROL.as_str(), "no-store");
    build.header(hdr);

    build.ok()
  }
}


/// Given a file name return its assumed content type.
///
/// Attempts to parse the file name's extension and makes the content type
/// guess based on it.  If the extension either can not be determined or is
/// unrecognized, then return `application/octet-stream`.
pub fn guess_mime_type(fname: impl AsRef<str>) -> ContentType {
  fn inner(fname: &str) -> ContentType {
    // The `unwrap()` in the `and_then` is safe because the original input
    // must be a valid utf-8 string.  The `unwrap()` in the `unwrap_or` is safe
    // because `application/octet-stream` will always exist.
    Path::new(fname)
      .extension()
      .and_then(|ext| ContentType::from_extension(ext.to_str().unwrap()))
      .unwrap_or_else(|| {
        ContentType::parse_flexible("application/octet-stream").unwrap()
      })
  }
  inner(fname.as_ref())
}

// vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :