kilork/actix-web-static-files

actix-web static files as resources support

Use-case #1: Static resources folder

  • Legal
  • Features
  • Usage
    • Use-case #2: package.json - npm managed folder
    • Use-case #3: package.json - WebPack usage
    • Use-case #4: yarn package manager
    • Use-case #5: Angular-like applications

Legal

Dual-licensed under MIT or the UNLICENSE.

Features

  • Embed static resources in single self-contained executuble
  • Serve static resources in actix-web
  • Install dependencies with npm package manager
  • Run custom npm run commands (such as webpack)
  • Support for npm-like package managers (yarn)
  • Support for angular-like routers

Usage

Create folder with static resources in your project (for example static):

cd project_dir
mkdir static
echo "<p>Hello, world\!</p>" > static/index.html

Add to Cargo.toml dependencies related to actix-web-static-files:

[dependencies]
actix-web = "3"
actix-web-static-files = "3"
static-files = "0.2.1"

[build-dependencies]
static-files = "0.2.1"

Add build.rs with call to bundle resources:

use static_files::resource_dir;

fn main() -> std::io::Result<()> {
    resource_dir("./static").build()
}

Include generated code in src/main.rs:

use actix_web::{App, HttpServer};
use actix_web_static_files::ResourceFiles;

include!(concat!(env!("OUT_DIR"), "/generated.rs"));

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(move || {
        let generated = generate();
        App::new().service(ResourceFiles::new("/", generated))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

Run the server:

cargo run

Request the resource:

$ curl -v http://localhost:8080/
*   Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 8080 failed: Connection refused
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
>
< HTTP/1.1 200 OK
< content-length: 20
< content-type: text/html
< etag: "14:606a2226"
< date: Sun, 23 May 2021 19:46:42 GMT
<
* Connection #0 to host localhost left intact
<p>Hello, world!</p>* Closing connection 0

See also:

  • Static resources folder with index.html example
  • Another example with same resources but using own defined function

Use-case #2: package.json - npm managed folder

Create folder with static resources in your project (for example static):

cd project_dir
mkdir static_packages
cd static_packages
echo '{}' > package.json
# install your npm dependencies (here we use fontawesome as an example)
npm install --save-dev @fortawesome/fontawesome-free

Add generated folder to ignore file of your version control system (here: git):

cd project_dir
echo "static_packages/node_modules" >> .gitignore

Add dependencies and build-dependencies in Cargo.toml same way as in the first use-case.

Add build.rs with call to bundle resources:

use static_files::npm_resource_dir;

fn main() -> std::io::Result<()> {
    npm_resource_dir("./static_packages")?.build()
}

Include generated code in main.rs same way as in the first use-case.

Reference resources in your HTML (static/index.html):

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="/static/@fortawesome/fontawesome-free/css/all.css">
    <script defer src="/static/@fortawesome/fontawesome-free/js/all.js"></script>
    <title>Hi</title>
</head>
<body>
    <i class="fas fa-thumbs-up"></i>
</body>
</html>

Use-case #3: package.json - WebPack usage

Create folder with static resources in your project (for example web), install required packages and webpack:

cd project_dir
mkdir -p web/src
cd web
echo -e "node_modules\ndist" > .gitignore
echo '{}' > package.json


# install lodash for usage in example
npm install --save lodash

# install webpack npm dependencies
npm install webpack webpack-cli html-webpack-plugin clean-webpack-plugin --save-dev

Add web/webpack.config.js:

const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: 'actix-web-static-files WebPack',
    }),
  ],
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist', 'bundle'),
  },
};

Add web/src/index.js:

import _ from 'lodash';

function component() {
  const element = document.createElement('div');

  element.innerHTML = _.join(['Hello', 'webpack'], ' ');

  return element;
}

document.body.appendChild(component());

Modify web/package.json by adding "scripts" sections:

{
  "dependencies": {
    "lodash": "^4.17.21"
  },
  "devDependencies": {
    "clean-webpack-plugin": "^3.0.0",
    "html-webpack-plugin": "^5.2.0",
    "webpack": "^5.24.2",
    "webpack-cli": "^4.5.0"
  },
  "scripts": {
    "build": "webpack"
  }
}

Add to Cargo.toml dependency to actix-web-static-files as in the first use case.

Add build.rs with call to bundle resources:

use static_files::NpmBuild;

fn main() -> std::io::Result<()> {
    NpmBuild::new("web")
        .install()?
        .run("build")?
        .target("web/dist/bundle")
        .change_detection()
        .to_resource_dir()
        .build()
}

Include generated code in src/main.rs:

use actix_web::{App, HttpServer};
use actix_web_static_files;

include!(concat!(env!("OUT_DIR"), "/generated.rs"));

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(move || {
        let generated = generate();
        App::new().service(actix_web_static_files::ResourceFiles::new("/", generated))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

Run the server:

cargo run

Request the resource:

$ curl -v http://localhost:8080
*   Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 8080 failed: Connection refused
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
>
< HTTP/1.1 200 OK
< content-length: 199
< content-type: text/html
< etag: "c7:5e403845"
< date: Sun, 09 Feb 2020 16:51:45 GMT
<
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>actix-web-static-files WebPack</title>
  </head>
  <body>
  <script type="text/javascript" src="main.js"></script></body>

See also:

  • WebPack Example

Use-case #4: yarn package manager

We can use another package manager instead of npm. For example, to use yarn just add .executable("yarn") to NpmBuild call:

use static_files::NpmBuild;

fn main() -> std::io::Result<()> {
    NpmBuild::new("web")
        .executable("yarn")
        .install()?
        .run("build")?
        .target("web/dist/bundle")
        .change_detection()
        .to_resource_dir()
        .build()
}

See also:

  • Yarn WebPack Example

Use-case #5: Angular-like applications

If you are using Angular as frontend, you may want to resolve all not found calls via index.html of frontend app. To do this just call method resolve_not_found_to_root after resource creation.

use actix_web::{middleware::Logger, App, HttpServer};
#[cfg(feature = "ui")]
use actix_web_static_files;

#[cfg(feature = "ui")]
use angular_example_frontend::generate;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    env_logger::init();
    HttpServer::new(move || {
        let mut app = App::new().wrap(Logger::default());
        #[cfg(feature = "ui")]
        {
            let generated = generate();
            app = app.service(
                actix_web_static_files::ResourceFiles::new("/", generated)
                    .resolve_not_found_to_root(),
            );
        }
        app
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

Remember to place you static resource route after all other routes in this case.

You can check the complete example Angular Router Sample.

Issues

Collection of the latest Issues

kilork

kilork

Comment Icon0

Breaking changes for version v3.1.0.

kilork

kilork

enhancement
Comment Icon10

We are missing benchmarking suite in project. We need to have some numbers to provide this for comparision.

Related to #17 #10

kilork

kilork

enhancement
Comment Icon3

Actix starts worker for each processor. With current API it also makes a full copy of generated data for this. Should not be like this.

Versions

Find the latest versions by id

v3.0.5 - Dec 22, 2020

Changes:

v3.0.4 - Dec 19, 2020

Changes:

v3.0.3 - Dec 18, 2020

Changes:

v3.0.2 - Nov 21, 2020

Changes:

v3.0.1 - Oct 27, 2020

v3.0.0 - Oct 27, 2020

v2.0.2 - Aug 01, 2020

Fixes:

v2.0.1 - Jul 07, 2020

New functions:

Information - Updated Jul 13, 2022

Stars: 58
Forks: 16
Issues: 4

Rust bindings for libinjection

Add libinjection to dependencies of Cargo

Rust bindings for libinjection

Rust library for Self Organising Maps (SOM)

Add rusticsom as a dependency in Cargo

Rust library for Self Organising Maps (SOM)

Rust bindings for the C++ api of PyTorch

LIghtweight wrapper for pytorch eg libtorch in rust

Rust bindings for the C++ api of PyTorch

Rust leveldb bindings

Almost-complete bindings for leveldb for Rust

Rust leveldb bindings

rust-analyzer is a modular compiler frontend for the Rust language

It also contains some tips &amp; tricks to help you be more productive when using rust-analyzer

rust-analyzer is a modular compiler frontend for the Rust language

Rust-Lightning is a Bitcoin Lightning library written in Rust

lightning, does not handle networking, persistence, or any other I/O

Rust-Lightning is a Bitcoin Lightning library written in Rust

Rust FUSE - Filesystem in Userspace

Rust library crate for easy implementation of Crate documentation

Rust FUSE - Filesystem in Userspace

Rust crate to implement a counterpart to the PBRT book's (3rd edition) C++ code:

Some images of the test scenes are shown below, but you can find more

Rust crate to implement a counterpart to the PBRT book's (3rd edition) C++ code:

Rust Persian Calendar

1** provides functionality for conversion among Persian (Solar Hijri) and Gregorian calendars

Rust Persian Calendar

Rustorm is an SQL-centered ORM with focus on ease of use on conversion of database...

This project exists thanks to all the people who contribute

Rustorm is an SQL-centered ORM with focus on ease of use on conversion of database...

The Rust Programming Language for Espressif chips

This fork enables projects to be built for the Xtensa-based ESP32, ESP32-SXX and ESP8266 using esp-rs organization has been formed to develop runtime, pac and...

The Rust Programming Language for Espressif chips

A cross-platform, fast, and safe general purpose C library written in Rust

The library is organized as a series of modules

A cross-platform, fast, and safe general purpose C library written in Rust
Facebook Instagram Twitter GitHub Dribbble
Privacy