http-fs 2.0.1

HTTP File Service library
Documentation
use http_fs::{ServeEntry, StaticFiles};

use std::path::Path;

#[test]
fn serve_files() {
    let static_files = StaticFiles::default();

    let path = Path::new("Cargo.tml");
    let result = static_files.serve(&path);

    match result {
        ServeEntry::NotFound => (),
        _ => panic!("Unexpected result for serve. Should ServeEntry::NotFound")
    }

    //Serve file with no headers for GET.
    let path = Path::new("Cargo.toml");

    match static_files.serve(&path) {
        ServeEntry::File(file, meta, _) => {
            let file_len = format!("{}", meta.len());
            let file_etag = format!("{}", etag::EntityTag::from_file_meta(&meta));
            let file_last_modified = httpdate::fmt_http_date(meta.modified().expect("Get Last-Modified"));

            let headers = http::header::HeaderMap::new();
            let mut out_headers = http::header::HeaderMap::new();
            let (code, body) = static_files.serve_file(&path, file, meta, http::Method::GET, &headers, &mut out_headers);
            assert_eq!(code, http::StatusCode::OK);

            let etag = out_headers.get(http::header::ETAG).expect("To have ETag in out_headers");
            let last_modified = out_headers.get(http::header::LAST_MODIFIED).expect("To have Last-Modified in out_headers");
            let content_type = out_headers.get(http::header::CONTENT_TYPE).expect("To have Content-Type in out_headers");
            let content_disposition = out_headers.get(http::header::CONTENT_DISPOSITION).expect("To have Content-Disposition in out_headers");
            let content_len = out_headers.get(http::header::CONTENT_LENGTH).expect("To have Content-Length in out_headers");

            assert_eq!(etag.to_str().unwrap(), file_etag);
            assert_eq!(last_modified.to_str().unwrap(), file_last_modified);
            assert_eq!(content_len.to_str().unwrap(), file_len);
            assert_eq!(content_type.to_str().unwrap(), "text/x-toml");
            assert_eq!(content_disposition.to_str().unwrap(), "inline");
            assert!(!body.is_finished());
        },
        _ => panic!("Unexpected result for serve. Should ServeEntry::File")
    }

    //Serve file with no headers for HEAD.
    match static_files.serve(&path) {
        ServeEntry::File(file, meta, _) => {
            let file_len = format!("{}", meta.len());
            let file_etag = format!("{}", etag::EntityTag::from_file_meta(&meta));
            let file_last_modified = httpdate::fmt_http_date(meta.modified().expect("Get Last-Modified"));

            let headers = http::header::HeaderMap::new();
            let mut out_headers = http::header::HeaderMap::new();
            let (code, body) = static_files.serve_file(&path, file, meta, http::Method::HEAD, &headers, &mut out_headers);

            assert_eq!(code, http::StatusCode::OK);

            let etag = out_headers.get(http::header::ETAG).expect("To have ETag in out_headers");
            let last_modified = out_headers.get(http::header::LAST_MODIFIED).expect("To have Last-Modified in out_headers");
            let content_type = out_headers.get(http::header::CONTENT_TYPE).expect("To have Content-Type in out_headers");
            let content_disposition = out_headers.get(http::header::CONTENT_DISPOSITION).expect("To have Content-Disposition in out_headers");
            let content_len = out_headers.get(http::header::CONTENT_LENGTH).expect("To have Content-Length in out_headers");

            assert_eq!(etag.to_str().unwrap(), file_etag);
            assert_eq!(last_modified.to_str().unwrap(), file_last_modified);
            assert_eq!(content_len.to_str().unwrap(), file_len);
            assert_eq!(content_type.to_str().unwrap(), "text/x-toml");
            assert_eq!(content_disposition.to_str().unwrap(), "inline");
            assert!(body.is_finished());
        },
        _ => panic!("Unexpected result for serve. Should ServeEntry::File")
    }

    //Serve cached file by ETAG
    match static_files.serve(&path) {
        ServeEntry::File(file, meta, _) => {
            let file_etag = etag::EntityTag::from_file_meta(&meta);

            let mut headers = http::header::HeaderMap::new();
            headers.insert(http::header::IF_NONE_MATCH, http_fs::utils::display_to_header(&file_etag));

            let mut out_headers = http::header::HeaderMap::new();
            let (code, body) = static_files.serve_file(&path, file, meta, http::Method::GET, &headers, &mut out_headers);

            assert_eq!(code, http::StatusCode::NOT_MODIFIED);
            assert!(body.is_finished());

            let etag = out_headers.get(http::header::ETAG).expect("To have ETag in out_headers");

            assert_eq!(etag.to_str().unwrap(), format!("{}", file_etag));
        },
        _ => panic!("Unexpected result for serve. Should ServeEntry::File")
    }

    match static_files.serve(&path) {
        ServeEntry::File(file, meta, _) => {
            let mut headers = http::header::HeaderMap::new();
            headers.insert(http::header::IF_MATCH, http_fs::utils::display_to_header(&"wrong etag"));

            let mut out_headers = http::header::HeaderMap::new();
            let (code, body) = static_files.serve_file(&path, file, meta, http::Method::GET, &headers, &mut out_headers);

            assert_eq!(code, http::StatusCode::PRECONDITION_FAILED);
            assert!(body.is_finished());
        },
        _ => panic!("Unexpected result for serve. Should ServeEntry::File")
    }

    //Serve cached file by Last-Modified
    match static_files.serve(&path) {
        ServeEntry::File(file, meta, _) => {
            let file_last_modified = httpdate::fmt_http_date(meta.modified().expect("Get Last-Modified"));

            let mut headers = http::header::HeaderMap::new();
            headers.insert(http::header::IF_MODIFIED_SINCE, http_fs::utils::display_to_header(&file_last_modified));

            let mut out_headers = http::header::HeaderMap::new();
            let (code, body) = static_files.serve_file(&path, file, meta, http::Method::GET, &headers, &mut out_headers);

            assert_eq!(code, http::StatusCode::NOT_MODIFIED);
            assert!(body.is_finished());

            let etag = out_headers.get(http::header::LAST_MODIFIED).expect("To have Last-Modified in out_headers");

            assert_eq!(etag.to_str().unwrap(), format!("{}", file_last_modified));
        },
        _ => panic!("Unexpected result for serve. Should ServeEntry::File")
    }

    match static_files.serve(&path) {
        ServeEntry::File(file, meta, _) => {
            let file_last_modified = httpdate::fmt_http_date(meta.modified().expect("Get Last-Modified"));

            let mut headers = http::header::HeaderMap::new();
            headers.insert(http::header::IF_MODIFIED_SINCE, http_fs::utils::display_to_header(&file_last_modified));
            //We ignore IF_MODIFIED_SINCE when IF_NONE_MATCH is present
            headers.insert(http::header::IF_NONE_MATCH, http::header::HeaderValue::from_static("dummy"));

            let mut out_headers = http::header::HeaderMap::new();
            let (code, body) = static_files.serve_file(&path, file, meta, http::Method::GET, &headers, &mut out_headers);

            assert_eq!(code, http::StatusCode::OK);
            assert!(!body.is_finished());
        },
        _ => panic!("Unexpected result for serve. Should ServeEntry::File")
    }

    match static_files.serve(&path) {
        ServeEntry::File(file, meta, _) => {
            let file_last_modified = httpdate::fmt_http_date(meta.modified().expect("Get Last-Modified"));
            let unmodified_since = meta.modified().expect("Get Last-Modified") - std::time::Duration::from_secs(60);

            let mut headers = http::header::HeaderMap::new();
            headers.insert(http::header::IF_UNMODIFIED_SINCE, http_fs::utils::display_to_header(&httpdate::fmt_http_date(unmodified_since)));

            let mut out_headers = http::header::HeaderMap::new();
            let (code, body) = static_files.serve_file(&path, file, meta, http::Method::GET, &headers, &mut out_headers);

            assert_eq!(code, http::StatusCode::PRECONDITION_FAILED);
            assert!(body.is_finished());

            let etag = out_headers.get(http::header::LAST_MODIFIED).expect("To have Last-Modified in out_headers");

            assert_eq!(etag.to_str().unwrap(), format!("{}", file_last_modified));
        },
        _ => panic!("Unexpected result for serve. Should ServeEntry::File")
    }
}