Crates.io | actix-web-rust-embed-responder |
lib.rs | actix-web-rust-embed-responder |
version | 2.2.3 |
source | src |
created_at | 2022-10-21 02:54:32.15869 |
updated_at | 2024-06-28 01:09:30.683723 |
description | An actix-web responder for rust-embed that implements cache revalidation and compressed responses. |
homepage | |
repository | |
max_upload_size | |
id | 693138 |
size | 6,240,397 |
An Actix Web responder for serving files embedded into the server. You can embed files into your server, and then use this responder to serve them out of your server. For example you can have a web app serve its own assets, html, css, javascript files, and more.
This crate implements responders for rust embed, as well as a more efficient fork rust-embed-for-web.
First, add this crate and rust-embed
or rust-embed-for-web
into your Cargo.toml
.
[dependencies]
actix-web = "4.2"
rust-embed = "6.4" # or rust-embed-for-web = "11.1"
actix-web-rust-embed-responder = "2.1.1"
Then, setup your embed and handler, and add your responder.
use actix_web::{route, web, App, HttpServer};
use actix_web_rust_embed_responder::{EmbedResponse, IntoResponse};
use rust_embed::{EmbeddedFile, RustEmbed};
#[derive(RustEmbed)]
#[folder = "path/to/assets/"]
struct Embed;
// This responder implements both GET and HEAD
#[route("/{path:.*}", method = "GET", method = "HEAD")]
// The return type is important, that is the type for this responder
async fn serve_assets(path: web::Path<String>) -> EmbedResponse<EmbeddedFile> {
// This is not required, but is likely what you want if you want this
// to serve `index.html` as the home page.
let path = if path.is_empty() {
"index.html"
} else {
path.as_str()
};
// There are implementations of `.into_response()` for both `EmbeddedFile` and `Option<EmbeddedFile>`.
// With `Option<EmbeddedFile>`, this responder will also handle sending a 404 response for `None`.
// If you want to customize the `404` response, you can handle the `None` case yourself: see the
// `custom-404.rs` test for an example.
Embed::get(path).into_response().
}
#[actix_web::main] // or #[tokio::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().service(serve_assets))
.bind(("127.0.0.1", 8080))?
.run()
.await
}
rust-embed-for-web
forkThe fork pre-computes certain things, like the header values that are used in responses.
It can also compressed the data ahead of time.
This can significantly increase the size of your compiled binary, but in exchange improves performance significantly.
You can disable the pre-compression which will minimize the increase (see rust-embed-for-web
readme for details).
In exchange for these limitations, you get improved performance. Based on some benchmarks, using the fork is 16% to 35% faster. For more detailed information check the benchmark reports.
With rust-embed-for-web
, this crate will serve compressed responses to clients
that support them if compression is enabled for the embed (you didn't add
#[gzip = false]
and #[br = false]
) and the file being served actually benefits from compression.
With rust-embed
, compressed responses are not served by default. However you
can set .use_compression(Compress::Always)
to turn it on. If you do, the files
will be compressed on the fly and cached. This will always compress files, even
for files like image files that are unlikely to benefit from compression.
Embed::get(path).into_response().use_compression(Compress::Always)
For rust-embed-for-web
, if you disabled pre-compression with #[gzip = false]
and #[br = false]
,
you can also enable on-the-fly compression with Compress::Always
.
Alternatively, you can use Compress::IfWellKnown
which will only compress files
known to be compressible such as html, css, and javascript.
You can also disable compression entirely with Compress::Never
.
Actix-web has a built-in response customization feature you can use.
#[route("/{path:.*}", method = "GET", method = "HEAD")]
async fn handler(
path: web::Path<String>,
) -> CustomizeResponder<EmbedResponse<EmbeddedFile>> {
EmbedRE::get(path)
.into_response()
.customize()
.insert_header(("X-My-Header", "My Header Value"))
}
There are examples for both rust-embed
and rust-embed-for-web
in the examples folder.
You can run these examples by using cargo run --example rust_embed --release
or cargo run --example rust_embed_for_web --release
, then visiting localhost:8080
in your browser.
By default, this crate enables support for both rust-embed
and
rust-embed-for-web
. You can disable support for the one you're not using:
# If you are using `rust-embed`:
actix-web-rust-embed-responder = { version = "2.1.1", default-features = false, features = ["support-rust-embed"] }
# If you are using `rust-embed-for-web`:
actix-web-rust-embed-responder = { version = "2.1.1", default-features = false, features = ["support-rust-embed-for-web"] }
There's also a feature flag always-embed
which is disabled by default. This is only useful for testing, you can ignore this feature.
actix-plus-static-files
Compared to actix-plus-static-files:
304 Not Modified
responses both with If-None-Match
and If-Unmodified-Since
headers, while actix-plus-static-files
only supports If-None-Match
.rust-embed-for-web
or during transmission with rust-embed
.rust-embed-for-web
and base64 with rust-embed
for the ETag
, which is more space efficient than the hex encoding used by actix-plus-static-files
.EmbeddedFile
type that you can add to your handlers, while actix-plus-static-files
implements a service you can directly add into your app.actix-plus-for-web
implements If-Any-Match
conditional requests, this crate does not. These are not usually used for GET
and HEAD
requests.Hengfei Yang 💻 |
Matt Palmer 💻 |