Skip to main content

tower_embed/
lib.rs

1//! This crate provides a [`tower`] service designed to provide embedded static
2//! assets support for web application. This service includes the following HTTP features:
3//!
4//! - Support for GET and HEAD requests
5//! - `Content-Type` header generation based on file MIME type guessed from extension.
6//! - `ETag` header generation and validation.
7//! - `Last-Modified` header generation and validation.
8//!
9//! In `debug` mode, assets are served directly from the filesystem to facilitate rapid
10//! development. Both `ETag` and `Last-Modified` headers are not generated in this mode.
11//!
12//! # Usage
13//!
14//! Please see the [examples] directory for a working example.
15//!
16//! [`tower`]: https://crates.io/crates/tower
17//! [examples]: https://github.com/mattiapenati/tower-embed/tree/main/examples
18
19#[cfg(not(feature = "tokio"))]
20compile_error!("Only tokio runtime is supported, and it is required to use `tower-embed`.");
21
22use std::{
23    marker::PhantomData,
24    task::{Context, Poll},
25};
26
27#[doc(inline)]
28pub use tower_embed_impl::Embed;
29
30#[doc(inline)]
31pub use tower_embed_core as core;
32
33#[doc(inline)]
34pub use tower_embed_core::Embed;
35
36#[doc(inline)]
37pub use self::response::{ResponseBody, ResponseFuture};
38
39#[doc(hidden)]
40pub mod file;
41
42mod response;
43
44/// Service that serves files from embedded assets.
45pub struct ServeEmbed<E: Embed> {
46    _embed: PhantomData<E>,
47}
48
49impl<E: Embed> Clone for ServeEmbed<E> {
50    fn clone(&self) -> Self {
51        *self
52    }
53}
54
55impl<E: Embed> Copy for ServeEmbed<E> {}
56
57impl<E: Embed> ServeEmbed<E> {
58    /// Create a new [`ServeEmbed`] service.
59    pub fn new() -> Self {
60        Self {
61            _embed: PhantomData,
62        }
63    }
64}
65
66impl<E: Embed> Default for ServeEmbed<E> {
67    fn default() -> Self {
68        Self::new()
69    }
70}
71
72impl<E, ReqBody> tower_service::Service<http::Request<ReqBody>> for ServeEmbed<E>
73where
74    E: Embed,
75{
76    type Response = http::Response<ResponseBody>;
77    type Error = std::convert::Infallible;
78    type Future = ResponseFuture;
79
80    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
81        Poll::Ready(Ok(()))
82    }
83
84    fn call(&mut self, req: http::Request<ReqBody>) -> Self::Future {
85        ResponseFuture::new::<E, _>(&req)
86    }
87}