A simple static file server as a Spin HTTP component, written in Rust.
This component is now fully componentized and
can be used with any runtime that supports wasi:http@0.2.0-rc-2023-10-18
, such as
Spin 2.0, wasmtime
and NGINX Unit.
Prerequisites:
- Rust at 1.72+ with the
wasm32-wasi
target configured - cargo-component
- Spin v2.0 to run the component/examples
Compiling the component:
$ cargo component build --release
See the examples directory for examples of using and composing spin-fileserver
with applications.
Prerequisites:
Running test cases:
$ make test
The easiest way to use this the Spin fileserver component in your application is to add it via its Spin template.
To create a new Spin app based on this component, run:
$ spin new -t static-fileserver
To add this component to your existing Spin app, run:
$ spin add -t static-fileserver
If you're looking to upgrade the version of this component in your application from one
of the releases, select the release
and corresponding checksum and update the component's source
in the application's spin.toml
, e.g.:
source = { url = "https://github.com/fermyon/spin-fileserver/releases/download/v0.1.0/spin_static_fs.wasm", digest = "sha256:96c76d9af86420b39eb6cd7be5550e3cb5d4cc4de572ce0fd1f6a29471536cb4" }
Next, we'll look at running the file server directly as well as using component composition to integrate this component in with your application logic.
Let's have a look at the component definition (from spin.toml):
[[trigger.http]]
route = "/..."
component = "fs"
# For more on configuring a component, see: https://developer.fermyon.com/spin/writing-apps
[component.fs]
source = "target/wasm32-wasi/release/spin_static_fs.wasm"
files = [{ source = "", destination = "/" }]
[component.fs.build]
command = "make"
This component will recursively mount all files from the current directory and
will serve them at the configured route. If an index.html
file is in the source root,
it will be served if no file is specified.
Running the static server:
$ spin up --listen 127.0.0.1:3000 --file spin.toml
At this point, the component is going to serve all files in the current
directory, and this can be tested using curl
:
$ curl localhost:3000/LICENSE
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
...
See also the rust-standalone example showing use of the file server alongside a simple Rust-based application.
The file server can also be composed with application logic to form one binary that can be run as a Spin application. See the following examples using the language and toolchains of your choice:
The Spin fileserver supports various configuration options.
Currently, this file server has a single cache header that it can set through
the CACHE_CONTROL
environment variable. If no value is set, the default
max-age=60
is used instead for all media types.
You can configure a FALLBACK_PATH
environment variable that points to a file that
will be returned instead of the default 404 Not Found response. If no environment
value is set, the default behavior is to return a 404 Not Found response. This behavior
is useful for Single Page Applications that use view routers on the front-end like React and Vue.
# For more on configuring a component, see: https://developer.fermyon.com/spin/writing-apps#adding-environment-variables-to-components
[component.fs]
source = "target/wasm32-wasi/release/spin_static_fs.wasm"
files = [{ source = "test", destination = "/" }]
environment = { FALLBACK_PATH = "index.html" }
You can configure a CUSTOM_404_PATH
environment variable and point to a file that will be served instead of returning a plain 404 Not Found response. Consider the following sample where the spin-fileserver
component is configured to serve all files from the test
folder. The desired page must exist in the test
folder to send a custom 404 HTML page (here, 404.html
) instead of a plain 404 Not Found response.
# For more on configuring a component, see: https://developer.fermyon.com/spin/writing-apps#adding-environment-variables-to-components
[component.fs]
source = "target/wasm32-wasi/release/spin_static_fs.wasm"
files = [{ source = "test", destination = "/" }]
environment = { CUSTOM_404_PATH = "404.html" }
If you haven't specified a favicon in your HTML document, spin-fileserver
will serve the Spin logo as the fallback favicon. The spin-fileserver
also serves the fallback favicon if the file (called favicon.ico
or favicon.png
) specified in your <link rel="shortcut icon" ...>
element does not exist.
Remember that there are situations where spin-fileserver
cannot serve the fallback favicon if no <link rel="shortcut icon" ...>
element is specified. Browsers try to find the favicon in the root directory of the origin (somedomain.com/favicon.ico
). If the application doesn't listen for requests targeting that route, it can't intercept requests to non-existing favicons.