From b7965493e15b35b2ff319207049186ef2e3f9886 Mon Sep 17 00:00:00 2001
From: Eduardo Trujillo <ed@chromabits.com>
Date: Tue, 8 Sep 2020 00:34:31 -0700
Subject: [PATCH] Initial commit for Rust rewrite

---
 .editorconfig                  |    5 +
 .gitignore                     |    5 +-
 .gitlab-ci.yml                 |   16 -
 Cargo.lock                     | 2963 ++++++++++++++++++++++++++++++++
 Cargo.toml                     |   40 +
 Dockerfile                     |   22 -
 LICENSE                        |    4 +-
 README.md                      |   52 +-
 Setup.hs                       |    2 -
 config.sample.toml             |   14 +
 config.sample.yaml             |  145 --
 espresso.cabal                 |   50 -
 package.yaml                   |   39 -
 rustfmt.toml                   |    1 +
 src/Espresso/Config.hs         |   68 -
 src/Main.hs                    |  294 ----
 src/bundle/mod.rs              |  215 +++
 src/bundle/poller/local_dir.rs |   41 +
 src/bundle/poller/mod.rs       |   39 +
 src/bundle/poller/s3.rs        |  159 ++
 src/bundle/rundir.rs           |  270 +++
 src/config.rs                  |  113 ++
 src/files/LICENSE              |   25 +
 src/files/README.md            |    4 +
 src/files/chunked.rs           |   98 ++
 src/files/error.rs             |   27 +
 src/files/mime_ext.rs          |   26 +
 src/files/mod.rs               | 1214 +++++++++++++
 src/files/named.rs             |  437 +++++
 src/files/pathbuf.rs           |  113 ++
 src/lib.rs                     |    9 +
 src/main.rs                    |  157 ++
 src/monitor.rs                 |  140 ++
 src/server.rs                  |   69 +
 src/stats.rs                   |   76 +
 src/thread.rs                  |  165 ++
 stack.yaml                     |   70 -
 stack.yaml.lock                |   12 -
 tests/test space.binary        |    1 +
 tests/test.binary              |    1 +
 tests/test.png                 |  Bin 0 -> 67390 bytes
 41 files changed, 6448 insertions(+), 753 deletions(-)
 create mode 100644 .editorconfig
 delete mode 100644 .gitlab-ci.yml
 create mode 100644 Cargo.lock
 create mode 100644 Cargo.toml
 delete mode 100644 Dockerfile
 delete mode 100644 Setup.hs
 create mode 100644 config.sample.toml
 delete mode 100644 config.sample.yaml
 delete mode 100644 espresso.cabal
 delete mode 100644 package.yaml
 create mode 100644 rustfmt.toml
 delete mode 100644 src/Espresso/Config.hs
 delete mode 100644 src/Main.hs
 create mode 100644 src/bundle/mod.rs
 create mode 100644 src/bundle/poller/local_dir.rs
 create mode 100644 src/bundle/poller/mod.rs
 create mode 100644 src/bundle/poller/s3.rs
 create mode 100644 src/bundle/rundir.rs
 create mode 100644 src/config.rs
 create mode 100644 src/files/LICENSE
 create mode 100644 src/files/README.md
 create mode 100644 src/files/chunked.rs
 create mode 100644 src/files/error.rs
 create mode 100644 src/files/mime_ext.rs
 create mode 100644 src/files/mod.rs
 create mode 100644 src/files/named.rs
 create mode 100644 src/files/pathbuf.rs
 create mode 100644 src/lib.rs
 create mode 100644 src/main.rs
 create mode 100644 src/monitor.rs
 create mode 100644 src/server.rs
 create mode 100644 src/stats.rs
 create mode 100644 src/thread.rs
 delete mode 100644 stack.yaml
 delete mode 100644 stack.yaml.lock
 create mode 100644 tests/test space.binary
 create mode 100644 tests/test.binary
 create mode 100644 tests/test.png

diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..f11c0f7
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,5 @@
+root = true
+
+[*.rs]
+indent_style = space
+indent_size = 4
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 9006621..db38427 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,2 @@
-.stack-work
-config.yaml
-run
+/target
+config.toml
\ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
deleted file mode 100644
index af0ffab..0000000
--- a/.gitlab-ci.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-image: fpco/stack-build-small:lts-14.17
-
-stages:
-  - build
-
-variables:
-  STACK_ROOT: "${CI_PROJECT_DIR}/.stack-root"
-
-build:
-  cache:
-    key: "$CI_JOB_NAME"
-    paths:
-      - .stack-work/
-      - .stack-root/
-  script:
-    - stack --no-terminal build
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..d9f8f39
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,2963 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "actix"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4af87564ff659dee8f9981540cac9418c45e910c8072fdedd643a262a38fcaf"
+dependencies = [
+ "actix-http",
+ "actix-rt",
+ "actix_derive",
+ "bitflags",
+ "bytes",
+ "crossbeam-channel",
+ "derive_more",
+ "futures",
+ "lazy_static",
+ "log",
+ "parking_lot 0.10.2",
+ "pin-project",
+ "smallvec",
+ "tokio",
+ "tokio-util 0.2.0",
+ "trust-dns-proto",
+ "trust-dns-resolver",
+]
+
+[[package]]
+name = "actix-codec"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09e55f0a5c2ca15795035d90c46bd0e73a5123b72f68f12596d6ba5282051380"
+dependencies = [
+ "bitflags",
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "tokio",
+ "tokio-util 0.2.0",
+]
+
+[[package]]
+name = "actix-connect"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c95cc9569221e9802bf4c377f6c18b90ef10227d787611decf79fd47d2a8e76c"
+dependencies = [
+ "actix-codec",
+ "actix-rt",
+ "actix-service",
+ "actix-utils",
+ "derive_more",
+ "either",
+ "futures",
+ "http",
+ "log",
+ "trust-dns-proto",
+ "trust-dns-resolver",
+]
+
+[[package]]
+name = "actix-files"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "193b22cb1f7b4ff12a4eb2415d6d19e47e44ea93e05930b30d05375ea29d3529"
+dependencies = [
+ "actix-http",
+ "actix-service",
+ "actix-web",
+ "bitflags",
+ "bytes",
+ "derive_more",
+ "futures-core",
+ "futures-util",
+ "log",
+ "mime",
+ "mime_guess",
+ "percent-encoding",
+ "v_htmlescape 0.4.5",
+]
+
+[[package]]
+name = "actix-http"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c16664cc4fdea8030837ad5a845eb231fb93fc3c5c171edfefb52fad92ce9019"
+dependencies = [
+ "actix-codec",
+ "actix-connect",
+ "actix-rt",
+ "actix-service",
+ "actix-threadpool",
+ "actix-utils",
+ "base64 0.11.0",
+ "bitflags",
+ "brotli2",
+ "bytes",
+ "chrono",
+ "copyless",
+ "derive_more",
+ "either",
+ "encoding_rs",
+ "failure",
+ "flate2",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "fxhash",
+ "h2",
+ "http",
+ "httparse",
+ "indexmap",
+ "language-tags",
+ "lazy_static",
+ "log",
+ "mime",
+ "percent-encoding",
+ "pin-project",
+ "rand",
+ "regex",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "sha1",
+ "slab",
+ "time 0.1.43",
+]
+
+[[package]]
+name = "actix-macros"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a60f9ba7c4e6df97f3aacb14bb5c0cd7d98a49dcbaed0d7f292912ad9a6a3ed2"
+dependencies = [
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "actix-router"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d7a10ca4d94e8c8e7a87c5173aba1b97ba9a6563ca02b0e1cd23531093d3ec8"
+dependencies = [
+ "bytestring",
+ "http",
+ "log",
+ "regex",
+ "serde",
+]
+
+[[package]]
+name = "actix-rt"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "143fcc2912e0d1de2bcf4e2f720d2a60c28652ab4179685a1ee159e0fb3db227"
+dependencies = [
+ "actix-macros",
+ "actix-threadpool",
+ "copyless",
+ "futures-channel",
+ "futures-util",
+ "smallvec",
+ "tokio",
+]
+
+[[package]]
+name = "actix-server"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6d74b464215a473c973a2d7d03a69cc10f4ce1f4b38a7659c5193dc5c675630"
+dependencies = [
+ "actix-codec",
+ "actix-rt",
+ "actix-service",
+ "actix-utils",
+ "futures-channel",
+ "futures-util",
+ "log",
+ "mio",
+ "mio-uds",
+ "num_cpus",
+ "slab",
+ "socket2",
+]
+
+[[package]]
+name = "actix-service"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0052435d581b5be835d11f4eb3bce417c8af18d87ddf8ace99f8e67e595882bb"
+dependencies = [
+ "futures-util",
+ "pin-project",
+]
+
+[[package]]
+name = "actix-testing"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47239ca38799ab74ee6a8a94d1ce857014b2ac36f242f70f3f75a66f691e791c"
+dependencies = [
+ "actix-macros",
+ "actix-rt",
+ "actix-server",
+ "actix-service",
+ "log",
+ "socket2",
+]
+
+[[package]]
+name = "actix-threadpool"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d209f04d002854b9afd3743032a27b066158817965bf5d036824d19ac2cc0e30"
+dependencies = [
+ "derive_more",
+ "futures-channel",
+ "lazy_static",
+ "log",
+ "num_cpus",
+ "parking_lot 0.11.0",
+ "threadpool",
+]
+
+[[package]]
+name = "actix-tls"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4e5b4faaf105e9a6d389c606c298dcdb033061b00d532af9df56ff3a54995a8"
+dependencies = [
+ "actix-codec",
+ "actix-rt",
+ "actix-service",
+ "actix-utils",
+ "derive_more",
+ "either",
+ "futures",
+ "log",
+]
+
+[[package]]
+name = "actix-utils"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcf8f5631bf01adec2267808f00e228b761c60c0584cc9fa0b5364f41d147f4e"
+dependencies = [
+ "actix-codec",
+ "actix-rt",
+ "actix-service",
+ "bitflags",
+ "bytes",
+ "either",
+ "futures",
+ "log",
+ "pin-project",
+ "slab",
+]
+
+[[package]]
+name = "actix-web"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3158e822461040822f0dbf1735b9c2ce1f95f93b651d7a7aded00b1efbb1f635"
+dependencies = [
+ "actix-codec",
+ "actix-http",
+ "actix-macros",
+ "actix-router",
+ "actix-rt",
+ "actix-server",
+ "actix-service",
+ "actix-testing",
+ "actix-threadpool",
+ "actix-tls",
+ "actix-utils",
+ "actix-web-codegen",
+ "awc",
+ "bytes",
+ "derive_more",
+ "encoding_rs",
+ "futures",
+ "fxhash",
+ "log",
+ "mime",
+ "net2",
+ "pin-project",
+ "regex",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "time 0.1.43",
+ "url",
+]
+
+[[package]]
+name = "actix-web-codegen"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a71bf475cbe07281d0b3696abb48212db118e7e23219f13596ce865235ff5766"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "actix_derive"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b95aceadaf327f18f0df5962fedc1bde2f870566a0b9f65c89508a3b1f79334c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "addr2line"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "arc-swap"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034"
+
+[[package]]
+name = "arrayref"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
+
+[[package]]
+name = "arrayvec"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
+
+[[package]]
+name = "async-channel"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21279cfaa4f47df10b1816007e738ca3747ef2ee53ffc51cdbf57a8bb266fee3"
+dependencies = [
+ "concurrent-queue",
+ "event-listener",
+ "futures-core",
+]
+
+[[package]]
+name = "async-compat"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4316ce79a7185ddb5cbb692bc5e992e3bbdb68a00382fa0b0ee248f05c16ecd7"
+dependencies = [
+ "futures-core",
+ "futures-io",
+ "once_cell",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "async-executor"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90f47c78ea98277cb1f5e6f60ba4fc762f5eafe9f6511bc2f7dfd8b75c225650"
+dependencies = [
+ "async-io",
+ "futures-lite",
+ "multitask",
+ "parking 1.0.6",
+ "scoped-tls",
+ "waker-fn",
+]
+
+[[package]]
+name = "async-io"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ae22a338d28c75b53702b66f77979062cb29675db376d99e451af4fa79dedb3"
+dependencies = [
+ "cfg-if",
+ "concurrent-queue",
+ "futures-lite",
+ "libc",
+ "once_cell",
+ "parking 2.0.0",
+ "polling",
+ "socket2",
+ "vec-arena",
+ "wepoll-sys-stjepang",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "async-mutex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66941c2577c4fa351e4ce5fdde8f86c69b88d623f3b955be1bc7362a23434632"
+dependencies = [
+ "event-listener",
+]
+
+[[package]]
+name = "async-std"
+version = "1.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46c8da367da62b8ff2313c406c9ac091c1b31d67a165becdd2de380d846260f7"
+dependencies = [
+ "async-executor",
+ "async-io",
+ "async-mutex",
+ "async-task",
+ "blocking",
+ "crossbeam-utils",
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-lite",
+ "futures-timer",
+ "kv-log-macro",
+ "log",
+ "memchr",
+ "num_cpus",
+ "once_cell",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+ "wasm-bindgen-futures",
+]
+
+[[package]]
+name = "async-tar"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb619eae01ab289095debb1ff7c02710d5124c20edde1b2eca926572a34c3998"
+dependencies = [
+ "async-std",
+ "filetime",
+ "libc",
+ "pin-project",
+ "redox_syscall",
+ "xattr",
+]
+
+[[package]]
+name = "async-task"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c17772156ef2829aadc587461c7753af20b7e8db1529bc66855add962a3b35d3"
+
+[[package]]
+name = "async-trait"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "687c230d85c0a52504709705fc8a53e4a692b83a2184f03dae73e38e1e93a783"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "atomic-waker"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
+
+[[package]]
+name = "awc"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7601d4d1d7ef2335d6597a41b5fe069f6ab799b85f53565ab390e7b7065aac5"
+dependencies = [
+ "actix-codec",
+ "actix-http",
+ "actix-rt",
+ "actix-service",
+ "base64 0.11.0",
+ "bytes",
+ "derive_more",
+ "futures-core",
+ "log",
+ "mime",
+ "percent-encoding",
+ "rand",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+]
+
+[[package]]
+name = "backtrace"
+version = "0.3.50"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293"
+dependencies = [
+ "addr2line",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "base-x"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1"
+
+[[package]]
+name = "base64"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
+
+[[package]]
+name = "base64"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
+
+[[package]]
+name = "bitflags"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+
+[[package]]
+name = "blake2b_simd"
+version = "0.5.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a"
+dependencies = [
+ "arrayref",
+ "arrayvec",
+ "constant_time_eq",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "blocking"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea5800d29218fea137b0880387e5948694a23c93fcdde157006966693a865c7c"
+dependencies = [
+ "async-channel",
+ "atomic-waker",
+ "futures-lite",
+ "once_cell",
+ "waker-fn",
+]
+
+[[package]]
+name = "brotli-sys"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "brotli2"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e"
+dependencies = [
+ "brotli-sys",
+ "libc",
+]
+
+[[package]]
+name = "buf-min"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6ae7069aad07c7cdefe6a22a671f00650728bd2331a4cc62e1e5d0becdf9ca4"
+dependencies = [
+ "bytes",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
+
+[[package]]
+name = "byteorder"
+version = "1.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
+
+[[package]]
+name = "bytes"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
+
+[[package]]
+name = "bytestring"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc7c05fa5172da78a62d9949d662d2ac89d4cc7355d7b49adee5163f1fb3f363"
+dependencies = [
+ "bytes",
+]
+
+[[package]]
+name = "cache-padded"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
+
+[[package]]
+name = "cc"
+version = "1.0.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+
+[[package]]
+name = "chrono"
+version = "0.4.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "942f72db697d8767c22d46a598e01f2d3b475501ea43d0db4f16d90259182d0b"
+dependencies = [
+ "num-integer",
+ "num-traits",
+ "serde",
+ "time 0.1.43",
+]
+
+[[package]]
+name = "cloudabi"
+version = "0.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "cloudabi"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "concurrent-queue"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
+dependencies = [
+ "cache-padded",
+]
+
+[[package]]
+name = "constant_time_eq"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
+
+[[package]]
+name = "copyless"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536"
+
+[[package]]
+name = "core-foundation"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac"
+
+[[package]]
+name = "cpuid-bool"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
+
+[[package]]
+name = "crc32fast"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ee0cc8804d5393478d743b035099520087a5186f3b93fa58cec08fa62407b6"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "lazy_static",
+]
+
+[[package]]
+name = "crypto-mac"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab"
+dependencies = [
+ "generic-array",
+ "subtle",
+]
+
+[[package]]
+name = "derive_more"
+version = "0.99.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "298998b1cf6b5b2c8a7b023dfd45821825ce3ba8a8af55c921a0e734e4653f76"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "digest"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "dirs"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
+dependencies = [
+ "cfg-if",
+ "dirs-sys",
+]
+
+[[package]]
+name = "dirs-sys"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a"
+dependencies = [
+ "libc",
+ "redox_users",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "discard"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
+
+[[package]]
+name = "doc-comment"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
+
+[[package]]
+name = "dtoa"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
+
+[[package]]
+name = "either"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f"
+
+[[package]]
+name = "encoding_rs"
+version = "0.8.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8ac63f94732332f44fe654443c46f6375d1939684c17b0afb6cb56b0456e171"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "enum-as-inner"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
+dependencies = [
+ "atty",
+ "humantime",
+ "log",
+ "regex",
+ "termcolor",
+]
+
+[[package]]
+name = "espresso"
+version = "0.1.0"
+dependencies = [
+ "actix",
+ "actix-files",
+ "actix-http",
+ "actix-rt",
+ "actix-service",
+ "actix-web",
+ "async-compat",
+ "async-tar",
+ "async-trait",
+ "bitflags",
+ "bytes",
+ "futures-core",
+ "futures-util",
+ "lazy_static",
+ "log",
+ "mime",
+ "mime_guess",
+ "percent-encoding",
+ "pretty_env_logger",
+ "rusoto_core",
+ "rusoto_credential",
+ "rusoto_s3",
+ "serde",
+ "serde_derive",
+ "snafu",
+ "tokio",
+ "toml",
+ "v_htmlescape 0.10.0",
+]
+
+[[package]]
+name = "event-listener"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1cd41440ae7e4734bbd42302f63eaba892afc93a3912dad84006247f0dedb0e"
+
+[[package]]
+name = "failure"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
+dependencies = [
+ "backtrace",
+ "failure_derive",
+]
+
+[[package]]
+name = "failure_derive"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "fastrand"
+version = "1.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c85295147490b8fcf2ea3d104080a105a8b2c63f9c319e82c02d8e952388919"
+
+[[package]]
+name = "filetime"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ed85775dcc68644b5c950ac06a2b23768d3bc9390464151aaf27136998dcf9e"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "flate2"
+version = "1.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68c90b0fc46cf89d227cc78b40e494ff81287a92dd07631e5af0d06fe3cf885e"
+dependencies = [
+ "cfg-if",
+ "crc32fast",
+ "libc",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
+[[package]]
+name = "fuchsia-zircon"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
+dependencies = [
+ "bitflags",
+ "fuchsia-zircon-sys",
+]
+
+[[package]]
+name = "fuchsia-zircon-sys"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
+
+[[package]]
+name = "futures"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399"
+
+[[package]]
+name = "futures-executor"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789"
+
+[[package]]
+name = "futures-lite"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97999970129b808f0ccba93211201d431fcc12d7e1ffae03a61b5cedd1a7ced2"
+dependencies = [
+ "fastrand",
+ "futures-core",
+ "futures-io",
+ "memchr",
+ "parking 2.0.0",
+ "pin-project-lite",
+ "waker-fn",
+]
+
+[[package]]
+name = "futures-macro"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39"
+dependencies = [
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc"
+
+[[package]]
+name = "futures-task"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "futures-timer"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c"
+dependencies = [
+ "gloo-timers",
+ "send_wrapper",
+]
+
+[[package]]
+name = "futures-util"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project",
+ "pin-utils",
+ "proc-macro-hack",
+ "proc-macro-nested",
+ "slab",
+]
+
+[[package]]
+name = "fxhash"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
+dependencies = [
+ "byteorder",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
+dependencies = [
+ "typenum",
+ "version_check 0.9.2",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "gimli"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
+
+[[package]]
+name = "gloo-timers"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "h2"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util 0.3.1",
+ "tracing",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "heck"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hex"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
+
+[[package]]
+name = "hmac"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840"
+dependencies = [
+ "crypto-mac",
+ "digest",
+]
+
+[[package]]
+name = "hostname"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
+dependencies = [
+ "libc",
+ "match_cfg",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "http"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b"
+dependencies = [
+ "bytes",
+ "http",
+]
+
+[[package]]
+name = "httparse"
+version = "1.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
+
+[[package]]
+name = "humantime"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
+dependencies = [
+ "quick-error",
+]
+
+[[package]]
+name = "hyper"
+version = "0.13.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e68a8dd9716185d9e64ea473ea6ef63529252e3e27623295a0378a19665d5eb"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "httparse",
+ "itoa",
+ "pin-project",
+ "socket2",
+ "time 0.1.43",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper-tls"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d979acc56dcb5b8dddba3917601745e877576475aa046df3226eabdecef78eed"
+dependencies = [
+ "bytes",
+ "hyper",
+ "native-tls",
+ "tokio",
+ "tokio-tls",
+]
+
+[[package]]
+name = "idna"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
+dependencies = [
+ "matches",
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "indexmap"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485"
+
+[[package]]
+name = "iovec"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "ipconfig"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7"
+dependencies = [
+ "socket2",
+ "widestring",
+ "winapi 0.3.9",
+ "winreg",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
+
+[[package]]
+name = "js-sys"
+version = "0.3.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85a7e2c92a4804dd459b86c339278d0fe87cf93757fae222c3fa3ae75458bc73"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+dependencies = [
+ "winapi 0.2.8",
+ "winapi-build",
+]
+
+[[package]]
+name = "kv-log-macro"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
+dependencies = [
+ "log",
+]
+
+[[package]]
+name = "language-tags"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.74"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10"
+
+[[package]]
+name = "linked-hash-map"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
+
+[[package]]
+name = "lock_api"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "lock_api"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "lru-cache"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
+dependencies = [
+ "linked-hash-map",
+]
+
+[[package]]
+name = "match_cfg"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
+
+[[package]]
+name = "matches"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
+
+[[package]]
+name = "md5"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
+
+[[package]]
+name = "memchr"
+version = "2.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
+
+[[package]]
+name = "mime"
+version = "0.3.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
+
+[[package]]
+name = "mime_guess"
+version = "2.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212"
+dependencies = [
+ "mime",
+ "unicase",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be0f75932c1f6cfae3c04000e40114adf955636e19040f9c0a2c380702aa1c7f"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "mio"
+version = "0.6.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430"
+dependencies = [
+ "cfg-if",
+ "fuchsia-zircon",
+ "fuchsia-zircon-sys",
+ "iovec",
+ "kernel32-sys",
+ "libc",
+ "log",
+ "miow 0.2.1",
+ "net2",
+ "slab",
+ "winapi 0.2.8",
+]
+
+[[package]]
+name = "mio-named-pipes"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656"
+dependencies = [
+ "log",
+ "mio",
+ "miow 0.3.5",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "mio-uds"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
+dependencies = [
+ "iovec",
+ "libc",
+ "mio",
+]
+
+[[package]]
+name = "miow"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
+dependencies = [
+ "kernel32-sys",
+ "net2",
+ "winapi 0.2.8",
+ "ws2_32-sys",
+]
+
+[[package]]
+name = "miow"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e"
+dependencies = [
+ "socket2",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "multitask"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c09c35271e7dcdb5f709779111f2c8e8ab8e06c1b587c1c6a9e179d865aaa5b4"
+dependencies = [
+ "async-task",
+ "concurrent-queue",
+ "fastrand",
+]
+
+[[package]]
+name = "native-tls"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d"
+dependencies = [
+ "lazy_static",
+ "libc",
+ "log",
+ "openssl",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "security-framework",
+ "security-framework-sys",
+ "tempfile",
+]
+
+[[package]]
+name = "net2"
+version = "0.2.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "nom"
+version = "4.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
+dependencies = [
+ "memchr",
+ "version_check 0.1.5",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "object"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
+
+[[package]]
+name = "once_cell"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
+
+[[package]]
+name = "opaque-debug"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+
+[[package]]
+name = "openssl"
+version = "0.10.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d575eff3665419f9b83678ff2815858ad9d11567e082f5ac1814baba4e2bcb4"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "foreign-types",
+ "lazy_static",
+ "libc",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de"
+dependencies = [
+ "autocfg",
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "parking"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6cb300f271742d4a2a66c01b6b2fa0c83dfebd2e0bf11addb879a3547b4ed87c"
+
+[[package]]
+name = "parking"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
+
+[[package]]
+name = "parking_lot"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e"
+dependencies = [
+ "lock_api 0.3.4",
+ "parking_lot_core 0.7.2",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733"
+dependencies = [
+ "instant",
+ "lock_api 0.4.1",
+ "parking_lot_core 0.8.0",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3"
+dependencies = [
+ "cfg-if",
+ "cloudabi 0.0.3",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
+dependencies = [
+ "cfg-if",
+ "cloudabi 0.1.0",
+ "instant",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+
+[[package]]
+name = "pin-project"
+version = "0.4.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca4433fff2ae79342e497d9f8ee990d174071408f28f726d6d83af93e58e48aa"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "0.4.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c0e815c3ee9a031fdf5af21c10aa17c573c9c6a566328d99e3936c34e36461f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282adbf10f2698a7a77f8e983a74b2d18176c19a7fd32a45446139ae7b02b715"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33"
+
+[[package]]
+name = "polling"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fffa183f6bd5f1a8a3e1f60ce2f8d5621e350eed84a62d6daaa5b9d1aaf6fbd"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "log",
+ "wepoll-sys-stjepang",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
+
+[[package]]
+name = "pretty_env_logger"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
+dependencies = [
+ "env_logger",
+ "log",
+]
+
+[[package]]
+name = "proc-macro-hack"
+version = "0.5.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598"
+
+[[package]]
+name = "proc-macro-nested"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quick-error"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+
+[[package]]
+name = "quote"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+dependencies = [
+ "getrandom",
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.1.57"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
+
+[[package]]
+name = "redox_users"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
+dependencies = [
+ "getrandom",
+ "redox_syscall",
+ "rust-argon2",
+]
+
+[[package]]
+name = "regex"
+version = "1.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+ "thread_local",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "resolv-conf"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11834e137f3b14e309437a8276714eed3a80d1ef894869e510f2c0c0b98b9f4a"
+dependencies = [
+ "hostname",
+ "quick-error",
+]
+
+[[package]]
+name = "rusoto_core"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e977941ee0658df96fca7291ecc6fc9a754600b21ad84b959eb1dbbc9d5abcc7"
+dependencies = [
+ "async-trait",
+ "base64 0.12.3",
+ "bytes",
+ "crc32fast",
+ "futures",
+ "http",
+ "hyper",
+ "hyper-tls",
+ "lazy_static",
+ "log",
+ "md5",
+ "percent-encoding",
+ "pin-project",
+ "rusoto_credential",
+ "rusoto_signature",
+ "rustc_version",
+ "serde",
+ "serde_json",
+ "tokio",
+ "xml-rs",
+]
+
+[[package]]
+name = "rusoto_credential"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ac05563f83489b19b4d413607a30821ab08bbd9007d14fa05618da3ef09d8b"
+dependencies = [
+ "async-trait",
+ "chrono",
+ "dirs",
+ "futures",
+ "hyper",
+ "pin-project",
+ "regex",
+ "serde",
+ "serde_json",
+ "shlex",
+ "tokio",
+ "zeroize",
+]
+
+[[package]]
+name = "rusoto_s3"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1146e37a7c1df56471ea67825fe09bbbd37984b5f6e201d8b2e0be4ee15643d8"
+dependencies = [
+ "async-trait",
+ "bytes",
+ "futures",
+ "rusoto_core",
+ "xml-rs",
+]
+
+[[package]]
+name = "rusoto_signature"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97a740a88dde8ded81b6f2cff9cd5e054a5a2e38a38397260f7acdd2c85d17dd"
+dependencies = [
+ "base64 0.12.3",
+ "bytes",
+ "futures",
+ "hex",
+ "hmac",
+ "http",
+ "hyper",
+ "log",
+ "md5",
+ "percent-encoding",
+ "pin-project",
+ "rusoto_credential",
+ "rustc_version",
+ "serde",
+ "sha2",
+ "time 0.2.16",
+ "tokio",
+]
+
+[[package]]
+name = "rust-argon2"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dab61250775933275e84053ac235621dfb739556d5c54a2f2e9313b7cf43a19"
+dependencies = [
+ "base64 0.12.3",
+ "blake2b_simd",
+ "constant_time_eq",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
+
+[[package]]
+name = "rustc_version"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
+
+[[package]]
+name = "schannel"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
+dependencies = [
+ "lazy_static",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "scoped-tls"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "security-framework"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535"
+dependencies = [
+ "bitflags",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+dependencies = [
+ "semver-parser",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+
+[[package]]
+name = "send_wrapper"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0"
+
+[[package]]
+name = "serde"
+version = "1.0.115"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.115"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.57"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_urlencoded"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
+dependencies = [
+ "dtoa",
+ "itoa",
+ "serde",
+ "url",
+]
+
+[[package]]
+name = "sha1"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
+
+[[package]]
+name = "sha2"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1"
+dependencies = [
+ "block-buffer",
+ "cfg-if",
+ "cpuid-bool",
+ "digest",
+ "opaque-debug",
+]
+
+[[package]]
+name = "shlex"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3e12110bc539e657a646068aaf5eb5b63af9d0c1f7b29c97113fad80e15f035"
+dependencies = [
+ "arc-swap",
+ "libc",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
+
+[[package]]
+name = "smallvec"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252"
+
+[[package]]
+name = "snafu"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7f5aed652511f5c9123cf2afbe9c244c29db6effa2abb05c866e965c82405ce"
+dependencies = [
+ "doc-comment",
+ "snafu-derive",
+]
+
+[[package]]
+name = "snafu-derive"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebf8f7d5720104a9df0f7076a8682024e958bba0fe9848767bb44f251f3648e9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "socket2"
+version = "0.3.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "standback"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33a71ea1ea5f8747d1af1979bfb7e65c3a025a70609f04ceb78425bc5adad8e6"
+dependencies = [
+ "version_check 0.9.2",
+]
+
+[[package]]
+name = "stdweb"
+version = "0.4.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
+dependencies = [
+ "discard",
+ "rustc_version",
+ "stdweb-derive",
+ "stdweb-internal-macros",
+ "stdweb-internal-runtime",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "stdweb-derive"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_derive",
+ "syn",
+]
+
+[[package]]
+name = "stdweb-internal-macros"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
+dependencies = [
+ "base-x",
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "sha1",
+ "syn",
+]
+
+[[package]]
+name = "stdweb-internal-runtime"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
+
+[[package]]
+name = "subtle"
+version = "2.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "502d53007c02d7605a05df1c1a73ee436952781653da5d0bf57ad608f66932c1"
+
+[[package]]
+name = "syn"
+version = "1.0.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "synstructure"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unicode-xid",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "rand",
+ "redox_syscall",
+ "remove_dir_all",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "threadpool"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
+dependencies = [
+ "num_cpus",
+]
+
+[[package]]
+name = "time"
+version = "0.1.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
+dependencies = [
+ "libc",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "time"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a51cadc5b1eec673a685ff7c33192ff7b7603d0b75446fb354939ee615acb15"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "standback",
+ "stdweb",
+ "time-macros",
+ "version_check 0.9.2",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "time-macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ae9b6e9f095bc105e183e3cd493d72579be3181ad4004fceb01adbe9eecab2d"
+dependencies = [
+ "proc-macro-hack",
+ "time-macros-impl",
+]
+
+[[package]]
+name = "time-macros-impl"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
+dependencies = [
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote",
+ "standback",
+ "syn",
+]
+
+[[package]]
+name = "tinyvec"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53953d2d3a5ad81d9f844a32f14ebb121f50b650cd59d0ee2a07cf13c617efed"
+
+[[package]]
+name = "tokio"
+version = "0.2.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "iovec",
+ "lazy_static",
+ "libc",
+ "memchr",
+ "mio",
+ "mio-named-pipes",
+ "mio-uds",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "slab",
+ "tokio-macros",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tokio-tls"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343"
+dependencies = [
+ "native-tls",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "toml"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "tower-service"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860"
+
+[[package]]
+name = "tracing"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c"
+dependencies = [
+ "cfg-if",
+ "log",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db63662723c316b43ca36d833707cc93dff82a02ba3d7e354f342682cc8b3545"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "trust-dns-proto"
+version = "0.18.0-alpha.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a7f3a2ab8a919f5eca52a468866a67ed7d3efa265d48a652a9a3452272b413f"
+dependencies = [
+ "async-trait",
+ "enum-as-inner",
+ "failure",
+ "futures",
+ "idna",
+ "lazy_static",
+ "log",
+ "rand",
+ "smallvec",
+ "socket2",
+ "tokio",
+ "url",
+]
+
+[[package]]
+name = "trust-dns-resolver"
+version = "0.18.0-alpha.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f"
+dependencies = [
+ "cfg-if",
+ "failure",
+ "futures",
+ "ipconfig",
+ "lazy_static",
+ "log",
+ "lru-cache",
+ "resolv-conf",
+ "smallvec",
+ "tokio",
+ "trust-dns-proto",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
+
+[[package]]
+name = "typenum"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
+
+[[package]]
+name = "unicase"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
+dependencies = [
+ "version_check 0.9.2",
+]
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
+dependencies = [
+ "matches",
+]
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
+
+[[package]]
+name = "url"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
+dependencies = [
+ "idna",
+ "matches",
+ "percent-encoding",
+]
+
+[[package]]
+name = "v_escape"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "660b101c07b5d0863deb9e7fb3138777e858d6d2a79f9e6049a27d1cc77c6da6"
+dependencies = [
+ "v_escape_derive 0.5.6",
+]
+
+[[package]]
+name = "v_escape"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b2d5ca56f0412d5ad5e642202e5c8fb61b61ad39435a53ed501fbd45380e8d3"
+dependencies = [
+ "buf-min",
+ "v_escape_derive 0.8.1",
+]
+
+[[package]]
+name = "v_escape_derive"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae"
+dependencies = [
+ "nom",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "v_escape_derive"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cae7cffca0b1f9af9b20610f6fdeee9ffcce61417b5ad186a5d482dc904e24cd"
+dependencies = [
+ "nom",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "v_htmlescape"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e33e939c0d8cf047514fb6ba7d5aac78bc56677a6938b2ee67000b91f2e97e41"
+dependencies = [
+ "cfg-if",
+ "v_escape 0.7.4",
+]
+
+[[package]]
+name = "v_htmlescape"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f5fd25529cb2f78527b5ee507bcfb357b26d057b5e480853c26d49a4ead5c629"
+dependencies = [
+ "cfg-if",
+ "v_escape 0.12.1",
+]
+
+[[package]]
+name = "vcpkg"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c"
+
+[[package]]
+name = "vec-arena"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8cb18268690309760d59ee1a9b21132c126ba384f374c59a94db4bc03adeb561"
+
+[[package]]
+name = "version_check"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
+
+[[package]]
+name = "version_check"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
+
+[[package]]
+name = "waker-fn"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
+
+[[package]]
+name = "want"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+dependencies = [
+ "log",
+ "try-lock",
+]
+
+[[package]]
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.67"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0563a9a4b071746dd5aedbc3a28c6fe9be4586fb3fbadb67c400d4f53c6b16c"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.67"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc71e4c5efa60fb9e74160e89b93353bc24059999c0ae0fb03affc39770310b0"
+dependencies = [
+ "bumpalo",
+ "lazy_static",
+ "log",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-futures"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95f8d235a77f880bcef268d379810ea6c0af2eacfa90b1ad5af731776e0c4699"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.67"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97c57cefa5fa80e2ba15641578b44d36e7a64279bc5ed43c6dbaf329457a2ed2"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.67"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "841a6d1c35c6f596ccea1f82504a192a60378f64b3bb0261904ad8f2f5657556"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.67"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93b162580e34310e5931c4b792560108b10fd14d64915d7fff8ff00180e70092"
+
+[[package]]
+name = "web-sys"
+version = "0.3.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dda38f4e5ca63eda02c059d243aa25b5f35ab98451e518c51612cd0f1bd19a47"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "wepoll-sys-stjepang"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fd319e971980166b53e17b1026812ad66c6b54063be879eb182342b55284694"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "widestring"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a763e303c0e0f23b0da40888724762e802a8ffefbc22de4127ef42493c2ea68c"
+
+[[package]]
+name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "winreg"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
+dependencies = [
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "ws2_32-sys"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
+dependencies = [
+ "winapi 0.2.8",
+ "winapi-build",
+]
+
+[[package]]
+name = "xattr"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "xml-rs"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a"
+
+[[package]]
+name = "zeroize"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3cbac2ed2ba24cc90f5e06485ac8c7c1e5449fe8911aef4d8877218af021a5b8"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..abd4dc2
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,40 @@
+[package]
+name = "espresso"
+version = "0.1.0"
+authors = ["Eduardo Trujillo <ed@chromabits.com>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+actix = "0.9.0"
+actix-web = "2.0.0"
+actix-rt = "1.0"
+actix-files = "0.2.2"
+bitflags = "1.2.1"
+actix-http = "1.0.1"
+mime_guess = "2.0.3"
+mime = "0.3.16"
+futures-util = "0.3.5"
+actix-service = "1.0.6"
+percent-encoding = "2.1.0"
+futures-core = "0.3.5"
+v_htmlescape = "0.10.0"
+bytes = "0.5.6"
+log = "0.4"
+snafu = "0.6.8"
+serde = "1.0.115"
+serde_derive = "1.0.115"
+toml = "0.5"
+pretty_env_logger = "0.4.0"
+rusoto_core = "0.45.0"
+rusoto_s3 = "0.45.0"
+rusoto_credential = "0.45.0"
+async-trait = "0.1.40"
+async-tar = "0.3"
+async-compat = "0.1.3"
+lazy_static = "1.4.0"
+
+[dependencies.tokio]
+version = "0.2"
+features = ["stream", "signal", "macros"]
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 88da1d6..0000000
--- a/Dockerfile
+++ /dev/null
@@ -1,22 +0,0 @@
-# Build
-FROM fpco/stack-build:lts-14.17 as build
-
-RUN mkdir /opt/build
-COPY . /opt/build
-
-RUN cd /opt/build && stack install --system-ghc
-
-# Runtime
-FROM ubuntu:20.04
-
-RUN mkdir -p /opt/espresso
-ARG BINARY_PATH
-WORKDIR /opt/espresso
-
-RUN apt-get update && apt-get install -y \
-  ca-certificates \
-  libgmp-dev
-
-COPY --from=build /root/.local/bin/espresso .
-
-CMD ["/opt/espresso/espresso"]
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index db83523..22642af 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright Eduardo Trujillo (c) 2019
+Copyright Eduardo Trujillo (c) 2019-2020
 
 All rights reserved.
 
@@ -27,4 +27,4 @@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
index 47e9bc5..e198e01 100644
--- a/README.md
+++ b/README.md
@@ -21,41 +21,33 @@ named `bundle.tar.gz` at the root of the bucket.
 
 ## Configuration
 
-Espresso supports the following environment variables:
-
-- **`SITE_STAGE` (Optional):** One of `production`, `staging`, or `development`
-  (Defaults to `development`). This specifies which set of configurations to
-  use as part of the `kawaii` package.
-- **`SITE_DOMAIN`**: Domain the site will be served from. This will be used to
-  redirect the user if a different domain is used (Defaults to
-  `chromabits.com`).
-- **`SITE_404_ROUTE`:** Route to redirect a user to if the path requested is
-  not found (Defaults to `/404`).
-- **`MINIO_ACCESS_KEY`:** Access key for the S3-compatible storage backend.
-- **`MINIO_SECRET_KEY`:** Secret key for the S3-compatible storage backend.
-- **`OBJECT_STORAGE_ENDPOINT`**: Endpoint to the S3-compatible storage backend.
-- **`BUCKET_NAME`:** The name of the bucket where the site bundle will be
-  stored in.
-
-### Stages
-
-- **Development:** Listens on port 9090 and has a minimal set of configurations
-  and middleware enabled.
-- **Staging:** Listens on port 8080 and has a set of configuration closer to
-  the production stage. Enables security middlewares (CSP, Force HTTPS),
-  as well as, GZIP compression and index-less URLs.
-- **Production:** Listens on port 80. Same configuration as the staging stage,
-  but with the addition of HSTS.
+Espresso can be configured via a TOML configuration file. Simply create a
+`config.toml` file and place it on the working directory.
+
+```toml
+[server]
+address = "127.0.0.1:8088"
+run_dir = "run"
+auto_cleanup = true
+
+[stats]
+address = "127.0.0.1:8089"
+
+[bundle]
+type = "LocalBundle"
+dir = "/tmp/"
+
+[unbundler]
+poll_seconds = 10
+```
 
 ## Customization
 
 While Espresso was built specifically for chromabits.com, it is able to serve
 other static sites as long as their requirements are simple.
 
-One of the main limitations you may encounter is the default set of CSP
-policies. These are not configurable over environment variables and require the
-server to be recompiled.
-
 ## Development
 
-`stack build --copy-bins` to build the server.
+`RUST_LOG=info cargo run` to build and run the server.
+
+`RUST_LOG=info cargo test` to run all tests.
diff --git a/Setup.hs b/Setup.hs
deleted file mode 100644
index 9a994af..0000000
--- a/Setup.hs
+++ /dev/null
@@ -1,2 +0,0 @@
-import Distribution.Simple
-main = defaultMain
diff --git a/config.sample.toml b/config.sample.toml
new file mode 100644
index 0000000..0c762d6
--- /dev/null
+++ b/config.sample.toml
@@ -0,0 +1,14 @@
+[server]
+address = "127.0.0.1:8088"
+run_dir = "run"
+# auto_cleanup = true
+
+[stats]
+address = "127.0.0.1:8089"
+
+[bundle]
+type = "LocalBundle"
+dir = "/tmp/"
+
+[unbundler]
+poll_seconds = 10
\ No newline at end of file
diff --git a/config.sample.yaml b/config.sample.yaml
deleted file mode 100644
index deca5fa..0000000
--- a/config.sample.yaml
+++ /dev/null
@@ -1,145 +0,0 @@
-server:
-  stage: Development
-  dev:
-    middleware:
-      - tag: LoggerMiddleware
-      - tag: SecurityHeadersMiddleware
-      - tag: DeindexifyMiddleware
-      - tag: GzipMiddleware
-    tlsConfiguration: null
-    port: 9090
-    notFoundHandler:
-      tag: NotFoundPath
-      contents: "/404"
-  staging:
-    middleware:
-      - tag: LoggerMiddleware
-      - tag: ContentSecurityPolicyMiddleware
-        contents: &csp
-          - tag: DefaultSrc
-            contents:
-              - tag: KeywordSource
-                contents: Self
-          # Allowed scripts sources
-          - tag: ScriptSrc
-            contents:
-              - tag: KeywordSource
-                contents: Self
-              - tag: KeywordSource
-                contents: UnsafeInline
-              - tag: HostSource
-                scheme: "https"
-                host:
-                  tag: DomainHostPart
-                  wildcard: false
-                  domain: "use.typekit.net"
-              - tag: HostSource
-                scheme: "https"
-                host:
-                  tag: DomainHostPart
-                  wildcard: false
-                  domain: "gist.github.com"
-          # Allowed image sources
-          - tag: ImgSrc
-            contents:
-              - tag: KeywordSource
-                contents: Self
-              - tag: SchemeSource
-                contents: "https"
-              - tag: SchemeSource
-                contents: "data"
-          # Allowed font sources
-          - tag: FontSrc
-            contents:
-              - tag: KeywordSource
-                contents: Self
-              - tag: SchemeSource
-                contents: "data"
-              - tag: HostSource
-                scheme: "https"
-                host:
-                  tag: DomainHostPart
-                  wildcard: false
-                  domain: "use.typekit.net"
-              - tag: HostSource
-                scheme: "https"
-                host:
-                  tag: DomainHostPart
-                  wildcard: false
-                  domain: "fonts.typekit.net"
-          # Allowed style sources
-          - tag: StyleSrc
-            contents:
-              - tag: KeywordSource
-                contents: Self
-              - tag: KeywordSource
-                contents: UnsafeInline
-              - tag: HostSource
-                scheme: "https"
-                host:
-                  tag: DomainHostPart
-                  wildcard: false
-                  domain: "use.typekit.net"
-              - tag: HostSource
-                scheme: "https"
-                host:
-                  tag: DomainHostPart
-                  wildcard: false
-                  domain: "assets-cdn.github.com"
-          # Allowed frame sources
-          - tag: FrameSrc
-            contents:
-              - tag: HostSource
-                scheme: "https"
-                host:
-                  tag: DomainHostPart
-                  wildcard: false
-                  domain: "www.youtube.com"
-      - tag: SecurityHeadersMiddleware
-      - tag: DomainMiddleware
-        contents: "chromabits.com"
-      - tag: ForceSSLMiddleware
-      - tag: DeindexifyMiddleware
-      - tag: GzipMiddleware
-    tlsConfiguration: null
-    port: 8080
-    notFoundHandler:
-      tag: NotFoundPath
-      contents: "/404"
-  prod:
-    middleware:
-      - tag: LoggerMiddleware
-      - tag: ContentSecurityPolicyMiddleware
-        contents: *csp
-      - tag: SecurityHeadersMiddleware
-      - tag: DomainMiddleware
-        contents: "chromabits.com"
-      - tag: ForceSSLMiddleware
-      - tag: DeindexifyMiddleware
-      - tag: GzipMiddleware
-      - tag: StrictTransportSecurityMiddleware
-        contents:
-          maxAge: 31536000
-          includeSubdomains: true
-          preload: false
-    tlsConfiguration: null
-    port: 80
-    notFoundHandler:
-      tag: NotFoundPath
-      contents: "/404"
-    cacheControl:
-      tag: CacheSeconds
-      contents: 604801
-# bundle:
-#   tag: S3Bundle
-#   contents:
-#     accessKey: EXAMPLE
-#     secretKey: EXAMPLE
-#     endpoint: https://minio
-#     bucket: example
-#     pollSeconds: 30
-#     objectName: bundle.tar.gz
-bundle:
-  tag: LocalBundle
-  contents:
-    path: run/serve
diff --git a/espresso.cabal b/espresso.cabal
deleted file mode 100644
index 2803992..0000000
--- a/espresso.cabal
+++ /dev/null
@@ -1,50 +0,0 @@
-cabal-version: 1.12
-
--- This file has been generated from package.yaml by hpack version 0.31.2.
---
--- see: https://github.com/sol/hpack
---
--- hash: 88f6a790ccefae14d57575e829a82a2df917f04afacc2c41ad729913f1e467f1
-
-name:           espresso
-version:        0.1.0.0
-description:    A web server for chromabits.com
-category:       Web
-homepage:       https://github.com/etcinit/espresso#readme
-author:         Eduardo Trujillo
-maintainer:     ed@chromabits.com
-copyright:      Copyright 2019 Eduardo Trujillo
-license:        BSD3
-license-file:   LICENSE
-build-type:     Simple
-extra-source-files:
-    README.md
-
-executable espresso
-  main-is: Main.hs
-  other-modules:
-      Espresso.Config
-      Paths_espresso
-  hs-source-dirs:
-      src
-  build-depends:
-      aeson
-    , base >=4.7 && <5
-    , conduit
-    , conduit-extra
-    , data-default >=0.7.1.1
-    , directory
-    , filepath
-    , generic-lens
-    , kawaii >=0.0.3.0
-    , lens >=4.0.0
-    , lifted-async
-    , lifted-base
-    , minio-hs
-    , monad-control
-    , monad-logger
-    , tar
-    , text
-    , transformers-base
-    , yaml
-  default-language: Haskell2010
diff --git a/package.yaml b/package.yaml
deleted file mode 100644
index 442209d..0000000
--- a/package.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
-name: espresso
-version: 0.1.0.0
-#synopsis:
-description: A web server for chromabits.com
-homepage: https://github.com/etcinit/espresso#readme
-license: BSD3
-author: Eduardo Trujillo
-maintainer: ed@chromabits.com
-copyright: Copyright 2019 Eduardo Trujillo
-category: Web
-extra-source-files:
-  - README.md
-
-dependencies:
-  - base >= 4.7 && < 5
-  - kawaii >= 0.0.3.0
-  - lens >= 4.0.0
-  - data-default >= 0.7.1.1
-  - minio-hs
-  - conduit
-  - conduit-extra
-  - directory
-  - filepath
-  - tar
-  - monad-logger
-  - text
-  - lifted-base
-  - lifted-async
-  - monad-control
-  - transformers-base
-  - aeson
-  - directory
-  - generic-lens
-  - yaml
-
-executables:
-  espresso:
-    source-dirs: src
-    main: Main.hs
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..47874a2
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1 @@
+tab_spaces=2
\ No newline at end of file
diff --git a/src/Espresso/Config.hs b/src/Espresso/Config.hs
deleted file mode 100644
index 3067fa9..0000000
--- a/src/Espresso/Config.hs
+++ /dev/null
@@ -1,68 +0,0 @@
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE DuplicateRecordFields #-}
-
-module Espresso.Config where
-
-import           Control.Monad.IO.Class         ( MonadIO
-                                                , liftIO
-                                                )
-import           GHC.Generics                   ( Generic )
-
-import           Control.Exception.Lifted       ( Exception
-                                                , throwIO
-                                                )
-import           Control.Monad.Base             ( MonadBase )
-import           System.Directory               ( getCurrentDirectory )
-import           Data.Aeson                     ( FromJSON )
-import           Data.Yaml                      ( decodeFileEither
-                                                , prettyPrintParseException
-                                                )
-import           Network.Wai.Serve.Types        ( StageConfiguration )
-import           Data.Text                      ( Text )
-import qualified Data.Text                     as T
-
-data ConfigException = ConfigParseException Text deriving (Show)
-
-instance Exception ConfigException
-
-data Config = Config
-  { server :: StageConfiguration
-  , bundle :: BundleConfig
-  } deriving (Generic)
-
-instance FromJSON Config
-
-data BundleConfig
-  = S3Bundle S3BundleConfig
-  | LocalBundle LocalBundleConfig
-  deriving (Generic, Show)
-
-instance FromJSON BundleConfig
-
-data S3BundleConfig = S3BundleConfig
-  { accessKey :: Text
-  , secretKey :: Text
-  , endpoint :: Text
-  , bucket :: Text
-  , objectName :: Text
-  , pollSeconds :: Int
-  } deriving (Generic, Show)
-
-instance FromJSON S3BundleConfig
-
-data LocalBundleConfig = LocalBundleConfig
-  { path :: Text
-  } deriving (Generic, Show)
-
-instance FromJSON LocalBundleConfig
-
-loadConfig :: (MonadIO m, MonadBase IO m) => m Config
-loadConfig = do
-  configFile <- (<> "/config.yaml") <$> liftIO getCurrentDirectory
-  parseResult <- liftIO $ decodeFileEither configFile
-
-  case parseResult of
-    Left parserError -> throwIO
-      $ ConfigParseException (T.pack $ prettyPrintParseException parserError)
-    Right decodedConfig -> pure decodedConfig
diff --git a/src/Main.hs b/src/Main.hs
deleted file mode 100644
index d00f6c3..0000000
--- a/src/Main.hs
+++ /dev/null
@@ -1,294 +0,0 @@
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE OverloadedLabels #-}
-{-# LANGUAGE TemplateHaskell #-}
-
-import qualified Codec.Archive.Tar             as Tar
-
-import           Control.Concurrent             ( forkIO )
-import           Control.Concurrent.Async.Lifted
-                                                ( async
-                                                , cancel
-                                                )
-import           Control.Concurrent.Chan.Lifted ( Chan
-                                                , newChan
-                                                , readChan
-                                                , writeChan
-                                                )
-import           Control.Concurrent.Lifted      ( threadDelay )
-import           Control.Concurrent.MVar.Lifted ( MVar
-                                                , newEmptyMVar
-                                                , putMVar
-                                                , readMVar
-                                                , takeMVar
-                                                )
-import           Control.Lens
-import           Control.Monad                  ( forever )
-import           Control.Monad.Base             ( MonadBase )
-import           Control.Monad.IO.Class         ( MonadIO
-                                                , liftIO
-                                                )
-import           Control.Monad.Logger           ( MonadLogger
-                                                , logError
-                                                , logInfo
-                                                , runChanLoggingT
-                                                , runStdoutLoggingT
-                                                , unChanLoggingT
-                                                )
-import           Control.Monad.Trans.Control    ( MonadBaseControl )
-import           Data.List.NonEmpty             ( NonEmpty((:|)) )
-
-import qualified Data.Conduit                  as C
-import qualified Data.Conduit.Binary           as CB
-import           Data.Default                   ( def )
-import           Data.Generics.Labels           ( )
-import           Data.Maybe                     ( fromMaybe )
-import           Data.Monoid                    ( (<>) )
-import           Data.Text                      ( Text )
-import qualified Data.Text                     as T
-import           Data.String                    ( fromString )
-
-import           Network.Minio                  ( Bucket
-                                                , Credentials(..)
-                                                , ConnectInfo
-                                                , GetObjectResponse
-                                                , MinioErr
-                                                , ObjectInfo(oiETag)
-                                                , defaultGetObjectOptions
-                                                , fromAWSEnv
-                                                , fromMinioEnv
-                                                , getObject
-                                                , gorObjectInfo
-                                                , gorObjectStream
-                                                , runMinio
-                                                , setCreds
-                                                , statObject
-                                                )
-import           Network.Minio.S3API            ( ETag )
-import           Network.Http.Csp               ( DirectiveList
-                                                , Keyword(..)
-                                                , SourceExpression(..)
-                                                , Directive(..)
-                                                , SchemePart(..)
-                                                , HostPart(..)
-                                                )
-import           Network.Wai.Serve.Applications ( redirect )
-import           Network.Wai.Serve.Main         ( serve' )
-import           Network.Wai.Serve.Middleware   ( (<#>)
-                                                , cspHeadersMiddleware
-                                                , deindexifyMiddleware
-                                                , domainMiddleware
-                                                , forceSSLMiddleware
-                                                , gzipMiddleware
-                                                , loggerMiddleware
-                                                , securityHeadersMiddleware
-                                                , stsHeadersMiddleware
-                                                )
-import           Network.Wai.Serve.Types        ( Stage(..)
-                                                , TLSConfiguration(..)
-                                                , NotFoundHandlerConfig(..)
-                                                , MiddlewareConfig(..)
-                                                )
-
-import           System.Directory               ( createDirectoryIfMissing
-                                                , doesDirectoryExist
-                                                , getCurrentDirectory
-                                                , removeDirectoryRecursive
-                                                , makeAbsolute
-                                                )
-import           System.Environment             ( lookupEnv )
-import           System.FilePath.Posix          ( (</>) )
-
-import           Espresso.Config                ( loadConfig
-                                                , BundleConfig(..)
-                                                , Config
-                                                )
-
-lookupEnvOrDefault :: (Read a, MonadIO m) => String -> a -> m a
-lookupEnvOrDefault name def = do
-  lookup <- liftIO $ lookupEnv name
-
-  pure $ maybe def read lookup
-
--- | The entry point of the server application.
-main :: IO ()
-main = do
-  config <- loadConfig
-
-  loggerChan <- newChan
-  restartChan <- newChan
-  etagMVar <- newEmptyMVar
-
-  -- Start a logger thread
-  forkIO $ runStdoutLoggingT $ unChanLoggingT loggerChan
-
-  runChanLoggingT loggerChan $ case (config ^. #bundle) of
-    LocalBundle bundleConfig -> do
-      path_ <- liftIO $ makeAbsolute (T.unpack $ bundleConfig ^. #path)
-
-      $(logInfo)
-        $ "Bundle: Using local path backend ("
-        <> (T.pack path_)
-        <> ")."
-
-      liftIO $ runServer config path_
-    S3Bundle bundleConfig -> do
-      $(logInfo) "Bundle: Using object storage backend."
-
-      cwd <- liftIO getCurrentDirectory
-
-      let runDir = cwd </> "run/"
-      let serveDir = runDir </> "serve/"
-      let bundlePath = runDir </> (T.unpack bundleObjectName)
-
-      liftIO $ createDirectoryIfMissing True runDir
-
-      $(logInfo) ("Bucket: " <> bucket)
-
-      minioResult <- downloadBundle cb3CI bucket bundlePath bundleObjectName
-
-      case minioResult of
-        Left e -> $(logError) $ "getObject failed." <> T.pack (show e)
-        Right response -> do
-          $(logInfo) "Sucessfully downloaded bundle."
-
-          let bundleInfo = gorObjectInfo response
-          $(logInfo) $ "ETag: " <> oiETag bundleInfo
-
-          putMVar etagMVar (oiETag bundleInfo)
-
-          async $ foreverServer restartChan config serveDir bundlePath
-
-          forever $ updater cb3CI
-                            bucket
-                            etagMVar
-                            restartChan
-                            bundlePath
-                            bundleObjectName
-                            (bundleConfig ^. #pollSeconds)
-
-     where
-      bucket = bundleConfig ^. #bucket
-      bundleObjectName = bundleConfig ^. #objectName
-      endpointUrl = T.unpack $ bundleConfig ^. #endpoint
-      cb3CI = setCreds
-        (Credentials (bundleConfig ^. #accessKey) (bundleConfig ^. #secretKey))
-        (fromString endpointUrl)
-
-downloadBundle
-  :: (MonadIO a, MonadLogger a)
-  => ConnectInfo
-  -> Bucket
-  -> FilePath
-  -> Text
-  -> a (Either MinioErr GetObjectResponse)
-downloadBundle connectInfo bucket bundlePath bundleObjectName = do
-  $(logInfo) "Downloading latest bundle..."
-
-  liftIO $ runMinio connectInfo $ do
-    response <- getObject bucket bundleObjectName defaultGetObjectOptions
-
-    C.connect (gorObjectStream response) $ CB.sinkFileCautious bundlePath
-
-    pure response
-
-updater
-  :: (MonadIO m, MonadLogger m, MonadBase IO m)
-  => ConnectInfo
-  -> Bucket
-  -> MVar ETag
-  -> Chan Bool
-  -> FilePath
-  -> Text
-  -> Int
-  -> m ()
-updater connectInfo bucket etagMVar restartChan bundlePath bundleObjectName pollSeconds
-  = do
-    threadDelay (1000000 * pollSeconds)
-
-    $(logInfo) "Checking for bundle updates..."
-
-    minioResult <- liftIO $ runMinio connectInfo $ statObject
-      bucket
-      bundleObjectName
-      defaultGetObjectOptions
-
-    case minioResult of
-      Left e -> $(logError) $ "statObject failed." <> T.pack (show e)
-      Right response -> do
-        currentETag <- readMVar etagMVar
-        let newETag = oiETag response
-
-        if newETag == currentETag
-          then $(logInfo) "No changes"
-          else do
-            $(logInfo) $ "Got new ETag: " <> oiETag response
-
-            minioResult_ <- downloadBundle connectInfo
-                                           bucket
-                                           bundlePath
-                                           bundleObjectName
-
-            case minioResult_ of
-              Left e -> $(logError) $ "getObject failed." <> T.pack (show e)
-              Right response -> do
-                $(logInfo) "Sucessfully downloaded new bundle."
-
-                -- Update eTag.
-                _ <- takeMVar etagMVar
-                putMVar etagMVar newETag
-
-                -- Schedule restart of web server.
-                writeChan restartChan True
-
-foreverServer
-  :: (MonadIO m, MonadLogger m, MonadBaseControl IO m)
-  => Chan Bool
-  -> Config
-  -> FilePath
-  -> FilePath
-  -> m ()
-foreverServer restartChan config serveDir bundlePath = forever $ do
-  serverId <- async $ prepareAndRunServer config serveDir bundlePath
-
-  _ <- readChan restartChan
-
-  $(logInfo) "Stopping server thread..."
-  cancel serverId
-
-prepareAndRunServer
-  :: (MonadIO a, MonadLogger a) => Config -> FilePath -> FilePath -> a ()
-prepareAndRunServer config serveDir bundlePath = do
-  prepareServeDir serveDir
-
-  $(logInfo) "Extracting bundle..."
-  liftIO $ Tar.extract serveDir bundlePath
-
-  liftIO $ runServer config serveDir
-
-prepareServeDir :: (MonadIO a, MonadLogger a) => FilePath -> a ()
-prepareServeDir serveDir = do
-  serveDirExists <- liftIO $ doesDirectoryExist serveDir
-
-  if serveDirExists
-    then do
-      $(logInfo) "Removing existing serve directory..."
-
-      liftIO $ removeDirectoryRecursive serveDir
-    else pure ()
-
-  $(logInfo) "Recreating serve directory..."
-  liftIO $ createDirectoryIfMissing True serveDir
-
-runServer :: Config -> FilePath -> IO ()
-runServer config serveDir = do
-  let serverConfig = config ^. #server
-
-  stage_ <- lookupEnvOrDefault "SITE_STAGE" (serverConfig ^. #stage)
-
-  let serverEnvironmentConfig = case stage_ of
-        Development -> serverConfig ^. #dev
-        Staging -> serverConfig ^. #staging
-        Production -> serverConfig ^. #prod
-
-  serve' $ (serverEnvironmentConfig & #path .~ (Just serveDir))
diff --git a/src/bundle/mod.rs b/src/bundle/mod.rs
new file mode 100644
index 0000000..dd36427
--- /dev/null
+++ b/src/bundle/mod.rs
@@ -0,0 +1,215 @@
+use crate::config::Config;
+use rundir::RunDir;
+use snafu::{ResultExt, Snafu};
+use std::{
+  path::PathBuf,
+  sync::{Arc, RwLock},
+};
+use tokio::time::{interval, Duration};
+
+mod poller;
+pub mod rundir;
+
+#[derive(Snafu, Debug)]
+pub enum Error {
+  InitRunDir { source: rundir::Error },
+  DeinitRunDir { source: rundir::Error },
+  LockRead,
+  LockWrite,
+  AttachSignalHook { source: std::io::Error },
+  MissingETag,
+  PollError { source: poller::Error },
+  SubDirError { source: rundir::Error },
+}
+
+type Result<T, E = Error> = std::result::Result<T, E>;
+
+#[derive(Copy, Clone, Debug)]
+pub enum UnbundlerStatus {
+  INIT = 0,
+  IDLE = 1,
+}
+
+#[derive(Clone)]
+pub struct Bundle {
+  etag: Option<String>,
+}
+
+struct UnbundlerState {
+  rundir: RunDir,
+  status: UnbundlerStatus,
+  active_bundle: Option<Bundle>,
+  staging_bundle: Option<Bundle>,
+  temp_dir: Option<PathBuf>,
+}
+
+pub struct Unbundler {
+  config: Arc<Config>,
+  serve_dir: Arc<RwLock<Option<PathBuf>>>,
+  state: RwLock<UnbundlerState>,
+  poller: Box<dyn poller::BundlePoller + Sync + Send>,
+}
+
+impl Unbundler {
+  pub fn new(config: Arc<Config>, serve_dir: Arc<RwLock<Option<PathBuf>>>) -> Unbundler {
+    let mut rundir = RunDir::new(config.server.run_dir.clone());
+
+    if let Some(allow_cleaning) = config.server.auto_cleanup {
+      rundir = rundir.allow_cleaning(allow_cleaning);
+    }
+
+    let poller: Box<dyn poller::BundlePoller + Sync + Send> = match &config.bundle {
+      crate::config::BundleConfig::S3Bundle {
+        access_key,
+        secret_key,
+        endpoint,
+        bucket,
+        region,
+        object_name,
+      } => Box::new(poller::S3BundlePoller::new(
+        access_key.clone(),
+        secret_key.clone(),
+        endpoint.clone(),
+        bucket.clone(),
+        region.clone(),
+        object_name.clone(),
+      )),
+      crate::config::BundleConfig::LocalBundle { dir } => {
+        Box::new(poller::LocalBundlePoller::new(dir.clone()))
+      }
+    };
+
+    Unbundler {
+      config: config.clone(),
+      state: RwLock::new(UnbundlerState {
+        rundir,
+        status: UnbundlerStatus::INIT,
+        active_bundle: None,
+        staging_bundle: None,
+        temp_dir: None,
+      }),
+      poller,
+      serve_dir,
+    }
+  }
+
+  pub fn get_status(&self) -> Result<UnbundlerStatus> {
+    let state = self.state.read().map_err(|_| Error::LockRead)?;
+
+    Ok(state.status.clone())
+  }
+
+  pub fn get_serve_dir(&self) -> Result<Option<PathBuf>> {
+    let serve_dir = self.serve_dir.read().map_err(|_| Error::LockRead)?;
+
+    Ok(serve_dir.clone())
+  }
+
+  pub async fn enter(&self) -> Result<()> {
+    self.init()?;
+
+    let mut interval = interval(Duration::from_secs(self.config.unbundler.poll_seconds));
+
+    loop {
+      let me = self;
+
+      tokio::select! {
+          _ = tokio::signal::ctrl_c() => {
+            break;
+          }
+          _ = interval.tick() => {
+            me.poll().await?;
+          }
+      }
+    }
+
+    self.deinit()
+  }
+
+  fn init(&self) -> Result<()> {
+    info!("Unbundler: Initializing...");
+
+    let mut state = self.state.write().map_err(|_| Error::LockWrite)?;
+
+    state.rundir.initialize().context(InitRunDir)?;
+    state.temp_dir = Some(state.rundir.create_subdir("temp").context(InitRunDir)?);
+
+    state.status = UnbundlerStatus::IDLE;
+
+    Ok(())
+  }
+
+  async fn poll(&self) -> Result<()> {
+    info!("Unbundler: Checking for updates...");
+
+    let mut state = self.state.write().map_err(|_| Error::LockWrite)?;
+
+    let result = self
+      .poller
+      .poll(&state.active_bundle)
+      .await
+      .context(PollError)?;
+
+    match result {
+      poller::PollResult::Skip => {
+        info!("Unbundler: No updates from poller.");
+
+        Ok(())
+      }
+      poller::PollResult::StaticUpdateReady { etag, path } => {
+        // Replacing active bundle.
+        state.active_bundle = Some(Bundle { etag });
+        state.staging_bundle = None;
+
+        let mut serve_dir = self.serve_dir.write().map_err(|_| Error::LockWrite)?;
+
+        serve_dir.replace(path);
+        // TODO: Update path.
+
+        Ok(())
+      }
+      poller::PollResult::UpdateReady { etag } => {
+        if state.rundir.subdir_exists(&etag).context(SubDirError)? {
+          warn!("Unbundler: Skipping update. Subdir already exists.");
+
+          return Ok(());
+        }
+
+        state.staging_bundle = Some(Bundle {
+          etag: Some(etag.clone()),
+        });
+
+        let newdir = state.rundir.create_subdir(&etag).context(SubDirError)?;
+
+        let result = self.poller.retrieve(&etag, newdir.clone()).await;
+
+        if result.is_err() {
+          warn!("Unbundler: Poller failed to retrieve new bundle. Rolling back.");
+
+          state.staging_bundle = None;
+
+          state.rundir.remove_subdir_all(&etag).context(SubDirError)?;
+        }
+
+        // Replacing active bundle.
+        state.active_bundle = state.staging_bundle.clone();
+        state.staging_bundle = None;
+
+        let mut serve_dir = self.serve_dir.write().map_err(|_| Error::LockWrite)?;
+
+        serve_dir.replace(newdir);
+        // TODO: Update path.
+
+        Ok(())
+      }
+    }
+  }
+
+  fn deinit(&self) -> Result<()> {
+    let state = self.state.write().map_err(|_| Error::LockWrite)?;
+
+    state.rundir.cleanup().context(DeinitRunDir)?;
+
+    Ok(())
+  }
+}
diff --git a/src/bundle/poller/local_dir.rs b/src/bundle/poller/local_dir.rs
new file mode 100644
index 0000000..6d22051
--- /dev/null
+++ b/src/bundle/poller/local_dir.rs
@@ -0,0 +1,41 @@
+use super::{BundlePoller, PollResult, Result};
+use crate::bundle::Bundle;
+use async_trait::async_trait;
+use std::path::PathBuf;
+
+pub struct LocalBundlePoller {
+  dir: PathBuf,
+}
+
+impl LocalBundlePoller {
+  pub fn new(dir: PathBuf) -> LocalBundlePoller {
+    LocalBundlePoller { dir }
+  }
+}
+
+#[async_trait]
+impl BundlePoller for LocalBundlePoller {
+  async fn poll(&self, active_bundle: &Option<Bundle>) -> Result<PollResult> {
+    if let None = active_bundle {
+      info!(
+        "LocalBundlePoller: Updating bundle (Local dir: {}).",
+        self.dir.display()
+      );
+
+      return Ok(PollResult::StaticUpdateReady {
+        etag: None,
+        path: self.dir.clone(),
+      });
+    }
+
+    info!("LocalBundlePoller: Local dir. No update needed.");
+
+    Ok(PollResult::Skip)
+  }
+
+  async fn retrieve(&self, _bundle_id: &str, _path: PathBuf) -> Result<()> {
+    warn!("LocalBundlePoller: retrieve is not supported. Ignoring.");
+
+    Ok(())
+  }
+}
diff --git a/src/bundle/poller/mod.rs b/src/bundle/poller/mod.rs
new file mode 100644
index 0000000..58eaf72
--- /dev/null
+++ b/src/bundle/poller/mod.rs
@@ -0,0 +1,39 @@
+use super::Bundle;
+use async_trait::async_trait;
+pub use local_dir::LocalBundlePoller;
+pub use s3::S3BundlePoller;
+use snafu::Snafu;
+use std::path::PathBuf;
+
+mod local_dir;
+mod s3;
+
+#[derive(Snafu, Debug)]
+pub enum Error {
+  MissingBundleID,
+  InternalPollerError {
+    source: Box<dyn std::error::Error>,
+  },
+  MismatchedBundleID {
+    original_id: String,
+    current_id: String,
+  },
+  UnpackError {
+    source: std::io::Error,
+  },
+}
+
+pub type Result<T, E = Error> = std::result::Result<T, E>;
+
+pub enum PollResult {
+  Skip,
+  UpdateReady { etag: String },
+  StaticUpdateReady { etag: Option<String>, path: PathBuf },
+}
+
+#[async_trait]
+pub trait BundlePoller {
+  async fn poll(&self, active_bundle: &Option<Bundle>) -> Result<PollResult>;
+
+  async fn retrieve(&self, bundle_id: &str, path: PathBuf) -> Result<()>;
+}
diff --git a/src/bundle/poller/s3.rs b/src/bundle/poller/s3.rs
new file mode 100644
index 0000000..76823f1
--- /dev/null
+++ b/src/bundle/poller/s3.rs
@@ -0,0 +1,159 @@
+use super::{BundlePoller, Error, PollResult, Result};
+use crate::bundle::Bundle;
+use async_compat::CompatExt;
+use async_tar::Archive;
+use async_trait::async_trait;
+use rusoto_core::RusotoError;
+use rusoto_s3::{
+  GetObjectError, GetObjectRequest, HeadObjectError, HeadObjectRequest, S3Client, S3,
+};
+use snafu::{ResultExt, Snafu};
+use std::path::PathBuf;
+
+#[derive(Snafu, Debug)]
+pub enum InternalError {
+  S3HeadObjectError {
+    source: RusotoError<HeadObjectError>,
+  },
+  S3GetObjectError {
+    source: RusotoError<GetObjectError>,
+  },
+  S3MissingBody,
+  S3MissingETag,
+}
+
+impl From<InternalError> for Error {
+  fn from(err: InternalError) -> Self {
+    Error::InternalPollerError {
+      source: Box::new(err),
+    }
+  }
+}
+
+pub struct S3BundlePoller {
+  client: S3Client,
+  bucket: String,
+  object_name: String,
+}
+
+impl S3BundlePoller {
+  pub fn new(
+    access_key: String,
+    secret_key: String,
+    endpoint: String,
+    bucket: String,
+    region: String,
+    object_name: String,
+  ) -> S3BundlePoller {
+    let region = rusoto_core::Region::Custom {
+      name: region.clone(),
+      endpoint: endpoint.clone(),
+    };
+    let credentials =
+      rusoto_credential::StaticProvider::new_minimal(access_key.clone(), secret_key.clone());
+    let dispatcher = rusoto_core::HttpClient::new().unwrap();
+    let client = S3Client::new_with(dispatcher, credentials, region);
+
+    S3BundlePoller {
+      client,
+      bucket,
+      object_name,
+    }
+  }
+}
+
+#[async_trait]
+impl BundlePoller for S3BundlePoller {
+  async fn poll(&self, active_bundle: &Option<Bundle>) -> Result<PollResult> {
+    if let Some(active_bundle) = active_bundle {
+      if let Some(_) = &active_bundle.etag {
+        let mut head_request: HeadObjectRequest = Default::default();
+
+        head_request.bucket = self.bucket.clone();
+        head_request.key = self.object_name.clone();
+
+        let head_response = self
+          .client
+          .head_object(head_request)
+          .await
+          .context(S3HeadObjectError)?;
+
+        if head_response.e_tag == active_bundle.etag {
+          info!(
+            "S3BundlePoller: No updates found for object: {}",
+            self.object_name
+          );
+
+          // Skip update download
+          return Ok(PollResult::Skip);
+        } else {
+          info!(
+            "S3BundlePoller: Object {} has changed. Starting bundle update.",
+            self.object_name
+          );
+        }
+      } else {
+        error!("S3BundlePoller: Expected the active bundle to have a valid ETag.");
+
+        return Err(Error::MissingBundleID);
+      }
+    }
+
+    // Head object
+    let mut head_request: HeadObjectRequest = Default::default();
+
+    head_request.bucket = self.bucket.clone();
+    head_request.key = self.object_name.clone();
+
+    let head_response = self
+      .client
+      .head_object(head_request)
+      .await
+      .context(S3HeadObjectError)?;
+
+    Ok(PollResult::UpdateReady {
+      etag: head_response.e_tag.ok_or(InternalError::S3MissingETag)?,
+    })
+  }
+
+  async fn retrieve(&self, bundle_id: &str, path: PathBuf) -> Result<()> {
+    info!("S3BundlePoller: Starting bundle download...");
+
+    let mut get_object_request: GetObjectRequest = Default::default();
+
+    get_object_request.bucket = self.bucket.clone();
+    get_object_request.key = self.object_name.clone();
+
+    let get_object_response = self
+      .client
+      .get_object(get_object_request)
+      .await
+      .context(S3GetObjectError)?;
+
+    let current_bundle_id = get_object_response
+      .e_tag
+      .ok_or(InternalError::S3MissingETag)?;
+
+    if current_bundle_id != bundle_id {
+      return Err(Error::MismatchedBundleID {
+        original_id: String::from(bundle_id),
+        current_id: current_bundle_id,
+      });
+    }
+
+    info!("S3BundlePoller: Unpacking bundle...");
+
+    // TODO: Write temp file to disk.
+    let archive = Archive::new(
+      get_object_response
+        .body
+        .ok_or(InternalError::S3MissingBody)?
+        .into_async_read()
+        .compat(),
+    );
+
+    archive.unpack(path).await.context(super::UnpackError)?;
+
+    Ok(())
+  }
+}
diff --git a/src/bundle/rundir.rs b/src/bundle/rundir.rs
new file mode 100644
index 0000000..615ee31
--- /dev/null
+++ b/src/bundle/rundir.rs
@@ -0,0 +1,270 @@
+use snafu::{ResultExt, Snafu};
+use std::path::{Path, PathBuf};
+
+#[derive(Snafu, Debug)]
+pub enum Error {
+  Initialize {
+    path: PathBuf,
+  },
+  PathIsNotDir {
+    path: PathBuf,
+  },
+  DirIsNotEmpty {
+    path: PathBuf,
+    child_path: PathBuf,
+  },
+  CreateDir {
+    path: PathBuf,
+    source: std::io::Error,
+  },
+  ScanDir {
+    path: PathBuf,
+    source: std::io::Error,
+  },
+  RecreateDir {
+    path: PathBuf,
+    source: std::io::Error,
+  },
+  RemoveSubDir {
+    path: PathBuf,
+    source: std::io::Error,
+  },
+  InvalidSubDirName {
+    name: String,
+    inner_error: Option<std::io::Error>,
+  },
+}
+
+type Result<T, E = Error> = std::result::Result<T, E>;
+
+pub struct RunDir {
+  path: PathBuf,
+  allow_cleaning: bool,
+}
+
+impl RunDir {
+  pub fn new<T: Into<PathBuf>>(path: T) -> RunDir {
+    RunDir {
+      path: path.into(),
+      allow_cleaning: false,
+    }
+  }
+
+  /// Set whether the directory can perform cleanup operations.
+  ///
+  /// Use with caution. This will clear existing directories on initialization
+  /// and cleanup.
+  pub fn allow_cleaning(mut self, allow_cleaning: bool) -> RunDir {
+    self.allow_cleaning = allow_cleaning;
+
+    self
+  }
+
+  /// Creates the initial RunDir.
+  ///
+  /// # Examples
+  ///
+  /// ```
+  /// use espresso::bundle::rundir::RunDir;
+  ///
+  /// let rundir = RunDir::new("tests/rundir").allow_cleaning(true);
+  ///
+  /// rundir.initialize().unwrap();
+  ///
+  /// rundir.cleanup().unwrap();
+  /// ```
+  pub fn initialize(&self) -> Result<()> {
+    if Path::exists(&self.path) {
+      info!("RunDir already exists: {}", self.path.display());
+
+      if !Path::is_dir(&self.path) {
+        error!("RunDir is not a directory: {}", self.path.display());
+
+        return Err(Error::PathIsNotDir {
+          path: self.path.clone(),
+        });
+      } else {
+        // Scan dir
+        let dir_iterator = std::fs::read_dir(&self.path).context(ScanDir {
+          path: self.path.clone(),
+        })?;
+
+        let mut existing_child_path = None;
+
+        for entry in dir_iterator {
+          let entry = entry.context(ScanDir {
+            path: self.path.clone(),
+          })?;
+
+          existing_child_path = Some(entry.path());
+
+          break;
+        }
+
+        if let Some(child_path) = existing_child_path {
+          if self.allow_cleaning {
+            info!("Recreating RunDir.");
+
+            std::fs::remove_dir_all(&self.path).context(RecreateDir {
+              path: self.path.clone(),
+            })?;
+
+            std::fs::create_dir_all(&self.path).context(RecreateDir {
+              path: self.path.clone(),
+            })?;
+          } else {
+            return Err(Error::DirIsNotEmpty {
+              path: self.path.clone(),
+              child_path,
+            });
+          }
+        }
+      }
+    } else {
+      info!("Creating new RunDir: {}", self.path.display());
+
+      std::fs::create_dir_all(&self.path).context(CreateDir {
+        path: self.path.clone(),
+      })?
+    }
+
+    Ok(())
+  }
+
+  pub fn cleanup(&self) -> Result<()> {
+    if self.allow_cleaning {
+      std::fs::remove_dir_all(&self.path).context(RecreateDir {
+        path: self.path.clone(),
+      })?;
+
+      info!("Cleaned up RunDir: {}", self.path.display());
+    } else {
+      warn!("Leaving RunDir unmodified. Manual cleanup may be needed.");
+    }
+
+    Ok(())
+  }
+
+  /// Creates a subdir within the RunDir.
+  pub fn create_subdir(&self, name: &str) -> Result<PathBuf> {
+    let pathbuf = self.validate_subdir_name(name)?;
+
+    std::fs::create_dir(&pathbuf).context(CreateDir {
+      path: pathbuf.clone(),
+    })?;
+
+    Ok(pathbuf)
+  }
+
+  /// Removes a subdir and all its contents from the RunDir.
+  pub fn remove_subdir_all(&self, name: &str) -> Result<()> {
+    let pathbuf = self.validate_subdir_name(name)?;
+
+    std::fs::remove_dir_all(&pathbuf).context(RemoveSubDir { path: pathbuf })?;
+
+    Ok(())
+  }
+
+  /// Checks if a subdir exists within the RunDir.
+  pub fn subdir_exists(&self, name: &str) -> Result<bool> {
+    let pathbuf = self.validate_subdir_name(name)?;
+
+    Ok(pathbuf.exists())
+  }
+
+  fn validate_subdir_name(&self, name: &str) -> Result<PathBuf> {
+    // Check that the name results in a dir exactly one level below the current one.
+    let mut pathbuf = self.path.clone();
+
+    pathbuf.push(name);
+
+    if let Some(parent) = pathbuf.parent() {
+      if PathBuf::from(parent) != PathBuf::from(&self.path) {
+        return Err(Error::InvalidSubDirName {
+          name: String::from(name),
+          inner_error: None,
+        });
+      }
+    } else {
+      return Err(Error::InvalidSubDirName {
+        name: String::from(name),
+        inner_error: None,
+      });
+    }
+
+    Ok(pathbuf)
+  }
+}
+
+#[cfg(test)]
+mod tests {
+  use super::{Error, RunDir};
+  use std::path::PathBuf;
+
+  #[test]
+  fn test_initialize() -> () {
+    // Create dir for the first time.
+    let result = RunDir::new("tests/rundir").initialize();
+
+    assert!(result.is_ok());
+
+    // Use existing empty dir.
+    let result = RunDir::new("tests/rundir").initialize();
+
+    assert!(result.is_ok());
+
+    // Fail when dir is not empty and allow_cleaning is not set.
+    std::fs::write("tests/rundir/hello.world", "test").unwrap();
+    let result = RunDir::new("tests/rundir").initialize();
+
+    match result {
+      Err(Error::DirIsNotEmpty { path, child_path }) => {
+        assert_eq!(path, PathBuf::from("tests/rundir"));
+        assert_eq!(child_path, PathBuf::from("tests/rundir/hello.world"));
+      }
+      _ => panic!("Expected an error."),
+    }
+
+    // Clean existing dir.
+    let result = RunDir::new("tests/rundir")
+      .allow_cleaning(true)
+      .initialize();
+
+    assert!(result.is_ok());
+
+    std::fs::remove_dir("tests/rundir").unwrap();
+
+    // Fail when dir is not a directory.
+    std::fs::write("tests/rundir", "hello").unwrap();
+    let result = RunDir::new("tests/rundir").initialize();
+
+    match result {
+      Err(Error::PathIsNotDir { path }) => {
+        assert_eq!(path, PathBuf::from("tests/rundir"));
+      }
+      _ => panic!("Expected an error."),
+    }
+
+    std::fs::remove_file("tests/rundir").unwrap();
+  }
+
+  #[test]
+  fn test_subdirs() -> () {
+    let rundir = RunDir::new("tests/rundir2").allow_cleaning(true);
+
+    rundir.initialize().unwrap();
+
+    assert_eq!(PathBuf::from("tests/rundir2/subtest").exists(), false);
+    assert_eq!(rundir.subdir_exists("subtest").unwrap(), false);
+
+    rundir.create_subdir("subtest").unwrap();
+    assert_eq!(PathBuf::from("tests/rundir2/subtest").exists(), true);
+    assert_eq!(rundir.subdir_exists("subtest").unwrap(), true);
+
+    rundir.remove_subdir_all("subtest").unwrap();
+    assert_eq!(PathBuf::from("tests/rundir2/subtest").exists(), false);
+    assert_eq!(rundir.subdir_exists("subtest").unwrap(), false);
+
+    rundir.cleanup().unwrap();
+  }
+}
diff --git a/src/config.rs b/src/config.rs
new file mode 100644
index 0000000..1787da4
--- /dev/null
+++ b/src/config.rs
@@ -0,0 +1,113 @@
+use serde_derive::{Deserialize, Serialize};
+use snafu::{ResultExt, Snafu};
+use std::{
+  env, fs,
+  net::SocketAddr,
+  path::{Path, PathBuf},
+};
+
+#[derive(Snafu, Debug)]
+pub enum Error {
+  /// The configuration file could not be found or read.
+  #[snafu(display("Could not open config from {}: {}", path.display(), source))]
+  OpenConfig {
+    path: PathBuf,
+    source: std::io::Error,
+  },
+  /// The configuration file could not be parsed or deserialized.
+  #[snafu(display("Could not deserialize config from {}: {}", path.display(), source))]
+  DeserializeConfig {
+    path: PathBuf,
+    source: toml::de::Error,
+  },
+  /// The current directory could not be determined.
+  GetCurrentDir { source: std::io::Error },
+}
+
+type Result<T, E = Error> = std::result::Result<T, E>;
+
+#[derive(Serialize, Deserialize, PartialEq, Debug)]
+pub struct Config {
+  pub bundle: BundleConfig,
+  pub unbundler: UnbundlerConfig,
+  pub server: ServerConfig,
+  pub stats: Option<StatsConfig>,
+}
+
+#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+pub struct ServerConfig {
+  pub address: SocketAddr,
+  pub run_dir: PathBuf,
+  pub auto_cleanup: Option<bool>,
+}
+
+#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+pub struct StatsConfig {
+  pub address: SocketAddr,
+}
+
+#[derive(Serialize, Deserialize, PartialEq, Debug)]
+pub struct UnbundlerConfig {
+  pub poll_seconds: u64,
+}
+
+#[derive(Serialize, Deserialize, PartialEq, Debug)]
+#[serde(tag = "type")]
+pub enum BundleConfig {
+  S3Bundle {
+    access_key: String,
+    secret_key: String,
+    endpoint: String,
+    bucket: String,
+    region: String,
+    object_name: String,
+  },
+  LocalBundle {
+    dir: PathBuf,
+  },
+}
+
+pub fn from_file(path: &Path) -> Result<Config> {
+  info!("Reading config file from {}", path.display());
+
+  let contents = fs::read_to_string(path).context(OpenConfig { path })?;
+
+  let config = toml::from_str(&contents);
+
+  config.context(DeserializeConfig { path })
+}
+
+pub fn from_current_dir() -> Result<Config> {
+  let mut current_path = env::current_dir().context(GetCurrentDir)?;
+
+  current_path.push("config.toml");
+
+  from_file(&current_path)
+}
+
+#[cfg(test)]
+mod tests {
+  use super::{from_file, BundleConfig, Config, ServerConfig, StatsConfig, UnbundlerConfig};
+  use std::path::{Path, PathBuf};
+
+  #[test]
+  fn test_from_file() {
+    assert_eq!(
+      from_file(&Path::new("config.sample.toml")).unwrap(),
+      Config {
+        stats: Some(StatsConfig {
+          address: "127.0.0.1:8089".parse().unwrap(),
+        }),
+        bundle: BundleConfig::LocalBundle {
+          dir: PathBuf::from("/tmp/")
+        },
+        server: ServerConfig {
+          address: "127.0.0.1:8088".parse().unwrap(),
+          run_dir: PathBuf::from("run"),
+          auto_cleanup: None,
+        },
+        unbundler: UnbundlerConfig { poll_seconds: 10 }
+      }
+    )
+  }
+}
diff --git a/src/files/LICENSE b/src/files/LICENSE
new file mode 100644
index 0000000..6682688
--- /dev/null
+++ b/src/files/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2017 Nikolay Kim
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/src/files/README.md b/src/files/README.md
new file mode 100644
index 0000000..9816cb9
--- /dev/null
+++ b/src/files/README.md
@@ -0,0 +1,4 @@
+# files
+
+Fork of https://github.com/actix/actix-web/tree/master/actix-files
+Modified to better support the espresso use-case.
diff --git a/src/files/chunked.rs b/src/files/chunked.rs
new file mode 100644
index 0000000..70a5e77
--- /dev/null
+++ b/src/files/chunked.rs
@@ -0,0 +1,98 @@
+use actix_web::{
+    error::{BlockingError, Error, ErrorInternalServerError},
+    web,
+};
+use bytes::Bytes;
+use futures_core::Stream;
+use futures_util::future::{FutureExt, LocalBoxFuture};
+use io::Seek;
+use std::{
+    cmp,
+    fs::File,
+    future::Future,
+    io,
+    io::Read,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+fn handle_error(err: BlockingError<io::Error>) -> Error {
+    match err {
+        BlockingError::Error(err) => err.into(),
+        BlockingError::Canceled => ErrorInternalServerError("Unexpected error"),
+    }
+}
+
+#[doc(hidden)]
+/// A helper created from a `std::fs::File` which reads the file
+/// chunk-by-chunk on a `ThreadPool`.
+pub struct ChunkedReadFile {
+    size: u64,
+    offset: u64,
+    file: Option<File>,
+    fut: Option<LocalBoxFuture<'static, Result<(File, Bytes), BlockingError<io::Error>>>>,
+    counter: u64,
+}
+
+impl ChunkedReadFile {
+    pub fn new(
+        size: u64,
+        offset: u64,
+        file: Option<File>,
+        fut: Option<LocalBoxFuture<'static, Result<(File, Bytes), BlockingError<io::Error>>>>,
+        counter: u64,
+    ) -> ChunkedReadFile {
+        ChunkedReadFile {
+            size,
+            offset,
+            file,
+            fut,
+            counter,
+        }
+    }
+}
+
+impl Stream for ChunkedReadFile {
+    type Item = Result<Bytes, Error>;
+
+    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
+        if let Some(ref mut fut) = self.fut {
+            return match Pin::new(fut).poll(cx) {
+                Poll::Ready(Ok((file, bytes))) => {
+                    self.fut.take();
+                    self.file = Some(file);
+                    self.offset += bytes.len() as u64;
+                    self.counter += bytes.len() as u64;
+                    Poll::Ready(Some(Ok(bytes)))
+                }
+                Poll::Ready(Err(e)) => Poll::Ready(Some(Err(handle_error(e)))),
+                Poll::Pending => Poll::Pending,
+            };
+        }
+
+        let size = self.size;
+        let offset = self.offset;
+        let counter = self.counter;
+
+        if size == counter {
+            Poll::Ready(None)
+        } else {
+            let mut file = self.file.take().expect("Use after completion");
+            self.fut = Some(
+                web::block(move || {
+                    let max_bytes: usize;
+                    max_bytes = cmp::min(size.saturating_sub(counter), 65_536) as usize;
+                    let mut buf = Vec::with_capacity(max_bytes);
+                    file.seek(io::SeekFrom::Start(offset))?;
+                    let nbytes = file.by_ref().take(max_bytes as u64).read_to_end(&mut buf)?;
+                    if nbytes == 0 {
+                        return Err(io::ErrorKind::UnexpectedEof.into());
+                    }
+                    Ok((file, Bytes::from(buf)))
+                })
+                .boxed_local(),
+            );
+            self.poll_next(cx)
+        }
+    }
+}
diff --git a/src/files/error.rs b/src/files/error.rs
new file mode 100644
index 0000000..f900691
--- /dev/null
+++ b/src/files/error.rs
@@ -0,0 +1,27 @@
+use actix_web::{http::StatusCode, HttpResponse, ResponseError};
+use snafu::Snafu;
+
+/// Errors which can occur when serving static files.
+#[derive(Snafu, Debug, PartialEq)]
+pub enum FilesError {
+  /// Path is not a directory
+  #[snafu(display("Path is not a directory. Unable to serve static files"))]
+  IsNotDirectory,
+
+  /// Cannot render directory
+  #[snafu(display("Unable to render directory without index file"))]
+  IsDirectory,
+
+  #[snafu(display("Serve directory is not ready."))]
+  ServeDirNotReady,
+
+  #[snafu(display("Unable to obtain read lock for serve dir."))]
+  ServerDirReadLockFail,
+}
+
+/// Return `NotFound` for `FilesError`
+impl ResponseError for FilesError {
+  fn error_response(&self) -> HttpResponse {
+    HttpResponse::new(StatusCode::NOT_FOUND)
+  }
+}
diff --git a/src/files/mime_ext.rs b/src/files/mime_ext.rs
new file mode 100644
index 0000000..86a76cf
--- /dev/null
+++ b/src/files/mime_ext.rs
@@ -0,0 +1,26 @@
+use mime_guess::from_ext;
+
+/// Return the MIME type associated with a filename extension (case-insensitive).
+/// If `ext` is empty or no associated type for the extension was found, returns
+/// the type `application/octet-stream`.
+#[inline]
+pub fn file_extension_to_mime(ext: &str) -> mime::Mime {
+    from_ext(ext).first_or_octet_stream()
+}
+
+#[cfg(test)]
+mod tests {
+    use super::file_extension_to_mime;
+
+    #[actix_rt::test]
+    async fn test_file_extension_to_mime() {
+        let m = file_extension_to_mime("jpg");
+        assert_eq!(m, mime::IMAGE_JPEG);
+
+        let m = file_extension_to_mime("invalid extension!!");
+        assert_eq!(m, mime::APPLICATION_OCTET_STREAM);
+
+        let m = file_extension_to_mime("");
+        assert_eq!(m, mime::APPLICATION_OCTET_STREAM);
+    }
+}
diff --git a/src/files/mod.rs b/src/files/mod.rs
new file mode 100644
index 0000000..79a1cb1
--- /dev/null
+++ b/src/files/mod.rs
@@ -0,0 +1,1214 @@
+#![allow(clippy::borrow_interior_mutable_const, clippy::type_complexity)]
+
+//! Static files support
+use std::cell::RefCell;
+use std::fmt::Write;
+use std::fs::DirEntry;
+use std::io;
+use std::path::{Path, PathBuf};
+use std::rc::Rc;
+use std::{
+  sync::{Arc, RwLock},
+  task::{Context, Poll},
+};
+
+use actix_service::boxed::{self, BoxService, BoxServiceFactory};
+use actix_service::{IntoServiceFactory, Service, ServiceFactory};
+use actix_web::dev::{
+  AppService, HttpServiceFactory, ResourceDef, ServiceRequest, ServiceResponse,
+};
+use actix_web::error::Error as ActixError;
+use actix_web::guard::Guard;
+use actix_web::http::header::{self, DispositionType};
+use actix_web::http::Method;
+use actix_web::{HttpRequest, HttpResponse};
+use error::FilesError as Error;
+use futures_util::future::{ok, Either, FutureExt, LocalBoxFuture, Ready};
+use percent_encoding::{utf8_percent_encode, CONTROLS};
+use v_htmlescape::escape as escape_html_entity;
+
+use named::NamedFile;
+use pathbuf::UriPathBuf;
+
+mod chunked;
+mod error;
+mod mime_ext;
+mod named;
+mod pathbuf;
+
+type HttpService = BoxService<ServiceRequest, ServiceResponse, ActixError>;
+type HttpNewService = BoxServiceFactory<(), ServiceRequest, ServiceResponse, ActixError, ()>;
+
+type DirectoryRenderer = dyn Fn(&Directory, &HttpRequest) -> Result<ServiceResponse, io::Error>;
+
+/// A directory; responds with the generated directory listing.
+#[derive(Debug)]
+pub struct Directory {
+  /// Base directory
+  pub base: PathBuf,
+  /// Path of subdirectory to generate listing for
+  pub path: PathBuf,
+}
+
+impl Directory {
+  /// Create a new directory
+  pub fn new(base: PathBuf, path: PathBuf) -> Directory {
+    Directory { base, path }
+  }
+
+  /// Is this entry visible from this directory?
+  pub fn is_visible(&self, entry: &io::Result<DirEntry>) -> bool {
+    if let Ok(ref entry) = *entry {
+      if let Some(name) = entry.file_name().to_str() {
+        if name.starts_with('.') {
+          return false;
+        }
+      }
+      if let Ok(ref md) = entry.metadata() {
+        let ft = md.file_type();
+        return ft.is_dir() || ft.is_file() || ft.is_symlink();
+      }
+    }
+    false
+  }
+}
+
+// show file url as relative to static path
+macro_rules! encode_file_url {
+  ($path:ident) => {
+    utf8_percent_encode(&$path, CONTROLS)
+  };
+}
+
+// " -- &quot;  & -- &amp;  ' -- &#x27;  < -- &lt;  > -- &gt;  / -- &#x2f;
+macro_rules! encode_file_name {
+  ($entry:ident) => {
+    escape_html_entity(&$entry.file_name().to_string_lossy())
+  };
+}
+
+fn directory_listing(dir: &Directory, req: &HttpRequest) -> Result<ServiceResponse, io::Error> {
+  let index_of = format!("Index of {}", req.path());
+  let mut body = String::new();
+  let base = Path::new(req.path());
+
+  for entry in dir.path.read_dir()? {
+    if dir.is_visible(&entry) {
+      let entry = entry.unwrap();
+      let p = match entry.path().strip_prefix(&dir.path) {
+        Ok(p) if cfg!(windows) => base.join(p).to_string_lossy().replace("\\", "/"),
+        Ok(p) => base.join(p).to_string_lossy().into_owned(),
+        Err(_) => continue,
+      };
+
+      // if file is a directory, add '/' to the end of the name
+      if let Ok(metadata) = entry.metadata() {
+        if metadata.is_dir() {
+          let _ = write!(
+            body,
+            "<li><a href=\"{}\">{}/</a></li>",
+            encode_file_url!(p),
+            encode_file_name!(entry),
+          );
+        } else {
+          let _ = write!(
+            body,
+            "<li><a href=\"{}\">{}</a></li>",
+            encode_file_url!(p),
+            encode_file_name!(entry),
+          );
+        }
+      } else {
+        continue;
+      }
+    }
+  }
+
+  let html = format!(
+    "<html>\
+         <head><title>{}</title></head>\
+         <body><h1>{}</h1>\
+         <ul>\
+         {}\
+         </ul></body>\n</html>",
+    index_of, index_of, body
+  );
+  Ok(ServiceResponse::new(
+    req.clone(),
+    HttpResponse::Ok()
+      .content_type("text/html; charset=utf-8")
+      .body(html),
+  ))
+}
+
+type MimeOverride = dyn Fn(&mime::Name) -> DispositionType;
+
+/// Static files handling
+///
+/// `Files` service must be registered with `App::service()` method.
+///
+/// ```rust
+/// use actix_web::App;
+/// use actix_files as fs;
+///
+/// fn main() {
+///     let app = App::new()
+///         .service(fs::Files::new("/static", "."));
+/// }
+/// ```
+pub struct Files {
+  path: String,
+  directory: Arc<RwLock<Option<PathBuf>>>,
+  index: Option<String>,
+  show_index: bool,
+  redirect_to_slash: bool,
+  default: Rc<RefCell<Option<Rc<HttpNewService>>>>,
+  renderer: Rc<DirectoryRenderer>,
+  mime_override: Option<Rc<MimeOverride>>,
+  file_flags: named::Flags,
+  // FIXME: Should re-visit later.
+  #[allow(clippy::redundant_allocation)]
+  guards: Option<Rc<Box<dyn Guard>>>,
+}
+
+impl Clone for Files {
+  fn clone(&self) -> Self {
+    Self {
+      directory: self.directory.clone(),
+      index: self.index.clone(),
+      show_index: self.show_index,
+      redirect_to_slash: self.redirect_to_slash,
+      default: self.default.clone(),
+      renderer: self.renderer.clone(),
+      file_flags: self.file_flags,
+      path: self.path.clone(),
+      mime_override: self.mime_override.clone(),
+      guards: self.guards.clone(),
+    }
+  }
+}
+
+impl Files {
+  /// Create new `Files` instance for specified base directory.
+  ///
+  /// `File` uses `ThreadPool` for blocking filesystem operations.
+  /// By default pool with 5x threads of available cpus is used.
+  /// Pool size can be changed by setting ACTIX_THREADPOOL environment variable.
+  pub fn new(path: &str, directory: Arc<RwLock<Option<PathBuf>>>) -> Files {
+    // let orig_dir = dir.into();
+    // let dir = match orig_dir.canonicalize() {
+    //   Ok(canon_dir) => canon_dir,
+    //   Err(_) => {
+    //     log::error!("Specified path is not a directory: {:?}", orig_dir);
+    //     PathBuf::new()
+    //   }
+    // };
+
+    Files {
+      path: path.to_string(),
+      directory,
+      index: None,
+      show_index: false,
+      redirect_to_slash: false,
+      default: Rc::new(RefCell::new(None)),
+      renderer: Rc::new(directory_listing),
+      mime_override: None,
+      file_flags: named::Flags::default(),
+      guards: None,
+    }
+  }
+
+  /// Show files listing for directories.
+  ///
+  /// By default show files listing is disabled.
+  pub fn show_files_listing(mut self) -> Self {
+    self.show_index = true;
+    self
+  }
+
+  /// Redirects to a slash-ended path when browsing a directory.
+  ///
+  /// By default never redirect.
+  pub fn redirect_to_slash_directory(mut self) -> Self {
+    self.redirect_to_slash = true;
+    self
+  }
+
+  /// Set custom directory renderer
+  pub fn files_listing_renderer<F>(mut self, f: F) -> Self
+  where
+    for<'r, 's> F:
+      Fn(&'r Directory, &'s HttpRequest) -> Result<ServiceResponse, io::Error> + 'static,
+  {
+    self.renderer = Rc::new(f);
+    self
+  }
+
+  /// Specifies mime override callback
+  pub fn mime_override<F>(mut self, f: F) -> Self
+  where
+    F: Fn(&mime::Name) -> DispositionType + 'static,
+  {
+    self.mime_override = Some(Rc::new(f));
+    self
+  }
+
+  /// Set index file
+  ///
+  /// Shows specific index file for directory "/" instead of
+  /// showing files listing.
+  pub fn index_file<T: Into<String>>(mut self, index: T) -> Self {
+    self.index = Some(index.into());
+    self
+  }
+
+  #[inline]
+  /// Specifies whether to use ETag or not.
+  ///
+  /// Default is true.
+  pub fn use_etag(mut self, value: bool) -> Self {
+    self.file_flags.set(named::Flags::ETAG, value);
+    self
+  }
+
+  #[inline]
+  /// Specifies whether to use Last-Modified or not.
+  ///
+  /// Default is true.
+  pub fn use_last_modified(mut self, value: bool) -> Self {
+    self.file_flags.set(named::Flags::LAST_MD, value);
+    self
+  }
+
+  /// Specifies custom guards to use for directory listings and files.
+  ///
+  /// Default behaviour allows GET and HEAD.
+  #[inline]
+  pub fn use_guards<G: Guard + 'static>(mut self, guards: G) -> Self {
+    self.guards = Some(Rc::new(Box::new(guards)));
+    self
+  }
+
+  /// Disable `Content-Disposition` header.
+  ///
+  /// By default Content-Disposition` header is enabled.
+  #[inline]
+  pub fn disable_content_disposition(mut self) -> Self {
+    self.file_flags.remove(named::Flags::CONTENT_DISPOSITION);
+    self
+  }
+
+  /// Sets default handler which is used when no matched file could be found.
+  pub fn default_handler<F, U>(mut self, f: F) -> Self
+  where
+    F: IntoServiceFactory<U>,
+    U: ServiceFactory<
+        Config = (),
+        Request = ServiceRequest,
+        Response = ServiceResponse,
+        Error = ActixError,
+      > + 'static,
+  {
+    // create and configure default resource
+    self.default = Rc::new(RefCell::new(Some(Rc::new(boxed::factory(
+      f.into_factory().map_init_err(|_| ()),
+    )))));
+
+    self
+  }
+}
+
+impl HttpServiceFactory for Files {
+  fn register(self, config: &mut AppService) {
+    if self.default.borrow().is_none() {
+      *self.default.borrow_mut() = Some(config.default_service());
+    }
+    let rdef = if config.is_root() {
+      ResourceDef::root_prefix(&self.path)
+    } else {
+      ResourceDef::prefix(&self.path)
+    };
+    config.register_service(rdef, None, self, None)
+  }
+}
+
+impl ServiceFactory for Files {
+  type Request = ServiceRequest;
+  type Response = ServiceResponse;
+  type Error = ActixError;
+  type Config = ();
+  type Service = FilesService;
+  type InitError = ();
+  type Future = LocalBoxFuture<'static, Result<Self::Service, Self::InitError>>;
+
+  fn new_service(&self, _: ()) -> Self::Future {
+    let mut srv = FilesService {
+      directory: self.directory.clone(),
+      index: self.index.clone(),
+      show_index: self.show_index,
+      redirect_to_slash: self.redirect_to_slash,
+      default: None,
+      renderer: self.renderer.clone(),
+      mime_override: self.mime_override.clone(),
+      file_flags: self.file_flags,
+      guards: self.guards.clone(),
+    };
+
+    if let Some(ref default) = *self.default.borrow() {
+      default
+        .new_service(())
+        .map(move |result| match result {
+          Ok(default) => {
+            srv.default = Some(default);
+            Ok(srv)
+          }
+          Err(_) => Err(()),
+        })
+        .boxed_local()
+    } else {
+      ok(srv).boxed_local()
+    }
+  }
+}
+
+pub struct FilesService {
+  directory: Arc<RwLock<Option<PathBuf>>>,
+  index: Option<String>,
+  show_index: bool,
+  redirect_to_slash: bool,
+  default: Option<HttpService>,
+  renderer: Rc<DirectoryRenderer>,
+  mime_override: Option<Rc<MimeOverride>>,
+  file_flags: named::Flags,
+  // FIXME: Should re-visit later.
+  #[allow(clippy::redundant_allocation)]
+  guards: Option<Rc<Box<dyn Guard>>>,
+}
+
+impl FilesService {
+  fn handle_err(
+    &mut self,
+    e: io::Error,
+    req: ServiceRequest,
+  ) -> Either<
+    Ready<Result<ServiceResponse, ActixError>>,
+    LocalBoxFuture<'static, Result<ServiceResponse, ActixError>>,
+  > {
+    log::debug!("Files: Failed to handle {}: {}", req.path(), e);
+    if let Some(ref mut default) = self.default {
+      Either::Right(default.call(req))
+    } else {
+      Either::Left(ok(req.error_response(e)))
+    }
+  }
+}
+
+impl Service for FilesService {
+  type Request = ServiceRequest;
+  type Response = ServiceResponse;
+  type Error = ActixError;
+  type Future = Either<
+    Ready<Result<Self::Response, Self::Error>>,
+    LocalBoxFuture<'static, Result<Self::Response, Self::Error>>,
+  >;
+
+  fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
+    Poll::Ready(Ok(()))
+  }
+
+  fn call(&mut self, req: ServiceRequest) -> Self::Future {
+    let is_method_valid = if let Some(guard) = &self.guards {
+      // execute user defined guards
+      (**guard).check(req.head())
+    } else {
+      // default behavior
+      matches!(*req.method(), Method::HEAD | Method::GET)
+    };
+
+    if !is_method_valid {
+      return Either::Left(ok(
+        req.into_response(
+          actix_web::HttpResponse::MethodNotAllowed()
+            .header(header::CONTENT_TYPE, "text/plain")
+            .body("Request did not meet this resource's requirements."),
+        ),
+      ));
+    }
+
+    let real_path = match UriPathBuf::new(req.match_info().path()) {
+      Ok(item) => item,
+      Err(e) => return Either::Left(ok(req.error_response(e))),
+    };
+
+    let path_ref: PathBuf = real_path.into();
+
+    let maybe_dir = match self.directory.read().map(|dir| dir.clone()) {
+      Ok(maybe_dir) => maybe_dir,
+      Err(_) => return Either::Left(ok(req.error_response(Error::ServerDirReadLockFail))),
+    };
+
+    let dir = match maybe_dir {
+      Some(dir) => dir,
+      None => return Either::Left(ok(req.error_response(Error::ServeDirNotReady))),
+    };
+
+    // full file path
+    let path = match dir.join(&path_ref).canonicalize() {
+      Ok(path) => path,
+      Err(e) => return self.handle_err(e, req),
+    };
+
+    if path.is_dir() {
+      if let Some(ref redir_index) = self.index {
+        if self.redirect_to_slash && !req.path().ends_with('/') {
+          let redirect_to = format!("{}/", req.path());
+          return Either::Left(ok(
+            req.into_response(
+              HttpResponse::Found()
+                .header(header::LOCATION, redirect_to)
+                .body("")
+                .into_body(),
+            ),
+          ));
+        }
+
+        let path = path.join(redir_index);
+
+        match NamedFile::open(path) {
+          Ok(mut named_file) => {
+            if let Some(ref mime_override) = self.mime_override {
+              let new_disposition = mime_override(&named_file.content_type.type_());
+              named_file.content_disposition.disposition = new_disposition;
+            }
+
+            named_file.flags = self.file_flags;
+            let (req, _) = req.into_parts();
+            Either::Left(ok(match named_file.into_response(&req) {
+              Ok(item) => ServiceResponse::new(req, item),
+              Err(e) => ServiceResponse::from_err(e, req),
+            }))
+          }
+          Err(e) => self.handle_err(e, req),
+        }
+      } else if self.show_index {
+        let dir = Directory::new(dir.clone(), path);
+        let (req, _) = req.into_parts();
+        let x = (self.renderer)(&dir, &req);
+        match x {
+          Ok(resp) => Either::Left(ok(resp)),
+          Err(e) => Either::Left(ok(ServiceResponse::from_err(e, req))),
+        }
+      } else {
+        Either::Left(ok(ServiceResponse::from_err(
+          Error::IsDirectory,
+          req.into_parts().0,
+        )))
+      }
+    } else {
+      match NamedFile::open(path) {
+        Ok(mut named_file) => {
+          if let Some(ref mime_override) = self.mime_override {
+            let new_disposition = mime_override(&named_file.content_type.type_());
+            named_file.content_disposition.disposition = new_disposition;
+          }
+
+          named_file.flags = self.file_flags;
+          let (req, _) = req.into_parts();
+          match named_file.into_response(&req) {
+            Ok(item) => Either::Left(ok(ServiceResponse::new(req.clone(), item))),
+            Err(e) => Either::Left(ok(ServiceResponse::from_err(e, req))),
+          }
+        }
+        Err(e) => self.handle_err(e, req),
+      }
+    }
+  }
+}
+
+#[cfg(test)]
+mod tests {
+  use std::fs;
+  use std::ops::Add;
+  use std::time::{Duration, SystemTime};
+
+  use super::*;
+  use actix_web::guard;
+  use actix_web::http::header::{self, ContentDisposition, DispositionParam, DispositionType};
+  use actix_web::http::{Method, StatusCode};
+  use actix_web::middleware::Compress;
+  use actix_web::test::{self, TestRequest};
+  use actix_web::{web, App, Responder};
+  use bytes::Bytes;
+  use fs::File;
+  use named::NamedFile;
+
+  fn serve_dir<T: Into<PathBuf>>(path: T) -> Arc<RwLock<Option<PathBuf>>> {
+    Arc::new(RwLock::new(Some(path.into())))
+  }
+
+  #[actix_rt::test]
+  async fn test_if_modified_since_without_if_none_match() {
+    let file = NamedFile::open("Cargo.toml").unwrap();
+    let since = header::HttpDate::from(SystemTime::now().add(Duration::from_secs(60)));
+
+    let req = TestRequest::default()
+      .header(header::IF_MODIFIED_SINCE, since)
+      .to_http_request();
+    let resp = file.respond_to(&req).await.unwrap();
+    assert_eq!(resp.status(), StatusCode::NOT_MODIFIED);
+  }
+
+  #[actix_rt::test]
+  async fn test_if_modified_since_with_if_none_match() {
+    let file = NamedFile::open("Cargo.toml").unwrap();
+    let since = header::HttpDate::from(SystemTime::now().add(Duration::from_secs(60)));
+
+    let req = TestRequest::default()
+      .header(header::IF_NONE_MATCH, "miss_etag")
+      .header(header::IF_MODIFIED_SINCE, since)
+      .to_http_request();
+    let resp = file.respond_to(&req).await.unwrap();
+    assert_ne!(resp.status(), StatusCode::NOT_MODIFIED);
+  }
+
+  #[actix_rt::test]
+  async fn test_named_file_text() {
+    assert!(NamedFile::open("test--").is_err());
+    let mut file = NamedFile::open("Cargo.toml").unwrap();
+    {
+      file.file();
+      let _f: &File = &file;
+    }
+    {
+      let _f: &mut File = &mut file;
+    }
+
+    let req = TestRequest::default().to_http_request();
+    let resp = file.respond_to(&req).await.unwrap();
+    assert_eq!(
+      resp.headers().get(header::CONTENT_TYPE).unwrap(),
+      "text/x-toml"
+    );
+    assert_eq!(
+      resp.headers().get(header::CONTENT_DISPOSITION).unwrap(),
+      "inline; filename=\"Cargo.toml\""
+    );
+  }
+
+  #[actix_rt::test]
+  async fn test_named_file_content_disposition() {
+    assert!(NamedFile::open("test--").is_err());
+    let mut file = NamedFile::open("Cargo.toml").unwrap();
+    {
+      file.file();
+      let _f: &File = &file;
+    }
+    {
+      let _f: &mut File = &mut file;
+    }
+
+    let req = TestRequest::default().to_http_request();
+    let resp = file.respond_to(&req).await.unwrap();
+    assert_eq!(
+      resp.headers().get(header::CONTENT_DISPOSITION).unwrap(),
+      "inline; filename=\"Cargo.toml\""
+    );
+
+    let file = NamedFile::open("Cargo.toml")
+      .unwrap()
+      .disable_content_disposition();
+    let req = TestRequest::default().to_http_request();
+    let resp = file.respond_to(&req).await.unwrap();
+    assert!(resp.headers().get(header::CONTENT_DISPOSITION).is_none());
+  }
+
+  #[actix_rt::test]
+  async fn test_named_file_non_ascii_file_name() {
+    let mut file = NamedFile::from_file(File::open("Cargo.toml").unwrap(), "貨物.toml").unwrap();
+    {
+      file.file();
+      let _f: &File = &file;
+    }
+    {
+      let _f: &mut File = &mut file;
+    }
+
+    let req = TestRequest::default().to_http_request();
+    let resp = file.respond_to(&req).await.unwrap();
+    assert_eq!(
+      resp.headers().get(header::CONTENT_TYPE).unwrap(),
+      "text/x-toml"
+    );
+    assert_eq!(
+      resp.headers().get(header::CONTENT_DISPOSITION).unwrap(),
+      "inline; filename=\"貨物.toml\"; filename*=UTF-8''%E8%B2%A8%E7%89%A9.toml"
+    );
+  }
+
+  #[actix_rt::test]
+  async fn test_named_file_set_content_type() {
+    let mut file = NamedFile::open("Cargo.toml")
+      .unwrap()
+      .set_content_type(mime::TEXT_XML);
+    {
+      file.file();
+      let _f: &File = &file;
+    }
+    {
+      let _f: &mut File = &mut file;
+    }
+
+    let req = TestRequest::default().to_http_request();
+    let resp = file.respond_to(&req).await.unwrap();
+    assert_eq!(
+      resp.headers().get(header::CONTENT_TYPE).unwrap(),
+      "text/xml"
+    );
+    assert_eq!(
+      resp.headers().get(header::CONTENT_DISPOSITION).unwrap(),
+      "inline; filename=\"Cargo.toml\""
+    );
+  }
+
+  #[actix_rt::test]
+  async fn test_named_file_image() {
+    let mut file = NamedFile::open("tests/test.png").unwrap();
+    {
+      file.file();
+      let _f: &File = &file;
+    }
+    {
+      let _f: &mut File = &mut file;
+    }
+
+    let req = TestRequest::default().to_http_request();
+    let resp = file.respond_to(&req).await.unwrap();
+    assert_eq!(
+      resp.headers().get(header::CONTENT_TYPE).unwrap(),
+      "image/png"
+    );
+    assert_eq!(
+      resp.headers().get(header::CONTENT_DISPOSITION).unwrap(),
+      "inline; filename=\"test.png\""
+    );
+  }
+
+  #[actix_rt::test]
+  async fn test_named_file_image_attachment() {
+    let cd = ContentDisposition {
+      disposition: DispositionType::Attachment,
+      parameters: vec![DispositionParam::Filename(String::from("test.png"))],
+    };
+    let mut file = NamedFile::open("tests/test.png")
+      .unwrap()
+      .set_content_disposition(cd);
+    {
+      file.file();
+      let _f: &File = &file;
+    }
+    {
+      let _f: &mut File = &mut file;
+    }
+
+    let req = TestRequest::default().to_http_request();
+    let resp = file.respond_to(&req).await.unwrap();
+    assert_eq!(
+      resp.headers().get(header::CONTENT_TYPE).unwrap(),
+      "image/png"
+    );
+    assert_eq!(
+      resp.headers().get(header::CONTENT_DISPOSITION).unwrap(),
+      "attachment; filename=\"test.png\""
+    );
+  }
+
+  #[actix_rt::test]
+  async fn test_named_file_binary() {
+    let mut file = NamedFile::open("tests/test.binary").unwrap();
+    {
+      file.file();
+      let _f: &File = &file;
+    }
+    {
+      let _f: &mut File = &mut file;
+    }
+
+    let req = TestRequest::default().to_http_request();
+    let resp = file.respond_to(&req).await.unwrap();
+    assert_eq!(
+      resp.headers().get(header::CONTENT_TYPE).unwrap(),
+      "application/octet-stream"
+    );
+    assert_eq!(
+      resp.headers().get(header::CONTENT_DISPOSITION).unwrap(),
+      "attachment; filename=\"test.binary\""
+    );
+  }
+
+  #[actix_rt::test]
+  async fn test_named_file_status_code_text() {
+    let mut file = NamedFile::open("Cargo.toml")
+      .unwrap()
+      .set_status_code(StatusCode::NOT_FOUND);
+    {
+      file.file();
+      let _f: &File = &file;
+    }
+    {
+      let _f: &mut File = &mut file;
+    }
+
+    let req = TestRequest::default().to_http_request();
+    let resp = file.respond_to(&req).await.unwrap();
+    assert_eq!(
+      resp.headers().get(header::CONTENT_TYPE).unwrap(),
+      "text/x-toml"
+    );
+    assert_eq!(
+      resp.headers().get(header::CONTENT_DISPOSITION).unwrap(),
+      "inline; filename=\"Cargo.toml\""
+    );
+    assert_eq!(resp.status(), StatusCode::NOT_FOUND);
+  }
+
+  #[actix_rt::test]
+  async fn test_mime_override() {
+    fn all_attachment(_: &mime::Name) -> DispositionType {
+      DispositionType::Attachment
+    }
+
+    let mut srv = test::init_service(
+      App::new().service(
+        Files::new("/", serve_dir("."))
+          .mime_override(all_attachment)
+          .index_file("Cargo.toml"),
+      ),
+    )
+    .await;
+
+    let request = TestRequest::get().uri("/").to_request();
+    let response = test::call_service(&mut srv, request).await;
+    assert_eq!(response.status(), StatusCode::OK);
+
+    let content_disposition = response
+      .headers()
+      .get(header::CONTENT_DISPOSITION)
+      .expect("To have CONTENT_DISPOSITION");
+    let content_disposition = content_disposition
+      .to_str()
+      .expect("Convert CONTENT_DISPOSITION to str");
+    assert_eq!(content_disposition, "attachment; filename=\"Cargo.toml\"");
+  }
+
+  #[actix_rt::test]
+  async fn test_named_file_ranges_status_code() {
+    let mut srv = test::init_service(
+      App::new().service(Files::new("/test", serve_dir(".")).index_file("Cargo.toml")),
+    )
+    .await;
+
+    // Valid range header
+    let request = TestRequest::get()
+      .uri("/t%65st/Cargo.toml")
+      .header(header::RANGE, "bytes=10-20")
+      .to_request();
+    let response = test::call_service(&mut srv, request).await;
+    assert_eq!(response.status(), StatusCode::PARTIAL_CONTENT);
+
+    // Invalid range header
+    let request = TestRequest::get()
+      .uri("/t%65st/Cargo.toml")
+      .header(header::RANGE, "bytes=1-0")
+      .to_request();
+    let response = test::call_service(&mut srv, request).await;
+
+    assert_eq!(response.status(), StatusCode::RANGE_NOT_SATISFIABLE);
+  }
+
+  #[actix_rt::test]
+  async fn test_named_file_content_range_headers() {
+    let srv = test::start(|| App::new().service(Files::new("/", serve_dir("."))));
+
+    // Valid range header
+    let response = srv
+      .get("/tests/test.binary")
+      .header(header::RANGE, "bytes=10-20")
+      .send()
+      .await
+      .unwrap();
+    let content_range = response.headers().get(header::CONTENT_RANGE).unwrap();
+    assert_eq!(content_range.to_str().unwrap(), "bytes 10-20/100");
+
+    // Invalid range header
+    let response = srv
+      .get("/tests/test.binary")
+      .header(header::RANGE, "bytes=10-5")
+      .send()
+      .await
+      .unwrap();
+    let content_range = response.headers().get(header::CONTENT_RANGE).unwrap();
+    assert_eq!(content_range.to_str().unwrap(), "bytes */100");
+  }
+
+  #[actix_rt::test]
+  async fn test_named_file_content_length_headers() {
+    let srv = test::start(|| App::new().service(Files::new("/", serve_dir("."))));
+
+    // Valid range header
+    let response = srv
+      .get("/tests/test.binary")
+      .header(header::RANGE, "bytes=10-20")
+      .send()
+      .await
+      .unwrap();
+    let content_length = response.headers().get(header::CONTENT_LENGTH).unwrap();
+    assert_eq!(content_length.to_str().unwrap(), "11");
+
+    // Valid range header, starting from 0
+    let response = srv
+      .get("/tests/test.binary")
+      .header(header::RANGE, "bytes=0-20")
+      .send()
+      .await
+      .unwrap();
+    let content_length = response.headers().get(header::CONTENT_LENGTH).unwrap();
+    assert_eq!(content_length.to_str().unwrap(), "21");
+
+    // Without range header
+    let mut response = srv.get("/tests/test.binary").send().await.unwrap();
+    let content_length = response.headers().get(header::CONTENT_LENGTH).unwrap();
+    assert_eq!(content_length.to_str().unwrap(), "100");
+
+    // Should be no transfer-encoding
+    let transfer_encoding = response.headers().get(header::TRANSFER_ENCODING);
+    assert!(transfer_encoding.is_none());
+
+    // Check file contents
+    let bytes = response.body().await.unwrap();
+    let data = Bytes::from(fs::read("tests/test.binary").unwrap());
+    assert_eq!(bytes, data);
+  }
+
+  #[actix_rt::test]
+  async fn test_head_content_length_headers() {
+    let srv = test::start(|| App::new().service(Files::new("/", serve_dir("."))));
+
+    let response = srv.head("/tests/test.binary").send().await.unwrap();
+
+    let content_length = response
+      .headers()
+      .get(header::CONTENT_LENGTH)
+      .unwrap()
+      .to_str()
+      .unwrap();
+
+    assert_eq!(content_length, "100");
+  }
+
+  #[actix_rt::test]
+  async fn test_static_files_with_spaces() {
+    let mut srv = test::init_service(
+      App::new().service(Files::new("/", serve_dir(".")).index_file("Cargo.toml")),
+    )
+    .await;
+    let request = TestRequest::get()
+      .uri("/tests/test%20space.binary")
+      .to_request();
+    let response = test::call_service(&mut srv, request).await;
+    assert_eq!(response.status(), StatusCode::OK);
+
+    let bytes = test::read_body(response).await;
+    let data = Bytes::from(fs::read("tests/test space.binary").unwrap());
+    assert_eq!(bytes, data);
+  }
+
+  #[actix_rt::test]
+  async fn test_files_not_allowed() {
+    let mut srv = test::init_service(App::new().service(Files::new("/", serve_dir(".")))).await;
+
+    let req = TestRequest::default()
+      .uri("/Cargo.toml")
+      .method(Method::POST)
+      .to_request();
+
+    let resp = test::call_service(&mut srv, req).await;
+    assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
+
+    let mut srv = test::init_service(App::new().service(Files::new("/", serve_dir(".")))).await;
+    let req = TestRequest::default()
+      .method(Method::PUT)
+      .uri("/Cargo.toml")
+      .to_request();
+    let resp = test::call_service(&mut srv, req).await;
+    assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
+  }
+
+  #[actix_rt::test]
+  async fn test_files_guards() {
+    let mut srv = test::init_service(
+      App::new().service(Files::new("/", serve_dir(".")).use_guards(guard::Post())),
+    )
+    .await;
+
+    let req = TestRequest::default()
+      .uri("/Cargo.toml")
+      .method(Method::POST)
+      .to_request();
+
+    let resp = test::call_service(&mut srv, req).await;
+    assert_eq!(resp.status(), StatusCode::OK);
+  }
+
+  #[actix_rt::test]
+  async fn test_named_file_content_encoding() {
+    let mut srv = test::init_service(App::new().wrap(Compress::default()).service(
+      web::resource("/").to(|| async {
+        NamedFile::open("Cargo.toml")
+          .unwrap()
+          .set_content_encoding(header::ContentEncoding::Identity)
+      }),
+    ))
+    .await;
+
+    let request = TestRequest::get()
+      .uri("/")
+      .header(header::ACCEPT_ENCODING, "gzip")
+      .to_request();
+    let res = test::call_service(&mut srv, request).await;
+    assert_eq!(res.status(), StatusCode::OK);
+    assert!(!res.headers().contains_key(header::CONTENT_ENCODING));
+  }
+
+  #[actix_rt::test]
+  async fn test_named_file_content_encoding_gzip() {
+    let mut srv = test::init_service(App::new().wrap(Compress::default()).service(
+      web::resource("/").to(|| async {
+        NamedFile::open("Cargo.toml")
+          .unwrap()
+          .set_content_encoding(header::ContentEncoding::Gzip)
+      }),
+    ))
+    .await;
+
+    let request = TestRequest::get()
+      .uri("/")
+      .header(header::ACCEPT_ENCODING, "gzip")
+      .to_request();
+    let res = test::call_service(&mut srv, request).await;
+    assert_eq!(res.status(), StatusCode::OK);
+    assert_eq!(
+      res
+        .headers()
+        .get(header::CONTENT_ENCODING)
+        .unwrap()
+        .to_str()
+        .unwrap(),
+      "gzip"
+    );
+  }
+
+  #[actix_rt::test]
+  async fn test_named_file_allowed_method() {
+    let req = TestRequest::default().method(Method::GET).to_http_request();
+    let file = NamedFile::open("Cargo.toml").unwrap();
+    let resp = file.respond_to(&req).await.unwrap();
+    assert_eq!(resp.status(), StatusCode::OK);
+  }
+
+  #[actix_rt::test]
+  async fn test_static_files() {
+    let mut srv =
+      test::init_service(App::new().service(Files::new("/", serve_dir(".")).show_files_listing()))
+        .await;
+    let req = TestRequest::with_uri("/missing").to_request();
+
+    let resp = test::call_service(&mut srv, req).await;
+    assert_eq!(resp.status(), StatusCode::NOT_FOUND);
+
+    let mut srv = test::init_service(App::new().service(Files::new("/", serve_dir(".")))).await;
+
+    let req = TestRequest::default().to_request();
+    let resp = test::call_service(&mut srv, req).await;
+    assert_eq!(resp.status(), StatusCode::NOT_FOUND);
+
+    let mut srv =
+      test::init_service(App::new().service(Files::new("/", serve_dir(".")).show_files_listing()))
+        .await;
+    let req = TestRequest::with_uri("/tests").to_request();
+    let resp = test::call_service(&mut srv, req).await;
+    assert_eq!(
+      resp.headers().get(header::CONTENT_TYPE).unwrap(),
+      "text/html; charset=utf-8"
+    );
+
+    let bytes = test::read_body(resp).await;
+    assert!(format!("{:?}", bytes).contains("/tests/test.png"));
+  }
+
+  #[actix_rt::test]
+  async fn test_redirect_to_slash_directory() {
+    // should not redirect if no index
+    let mut srv = test::init_service(
+      App::new().service(Files::new("/", serve_dir(".")).redirect_to_slash_directory()),
+    )
+    .await;
+    let req = TestRequest::with_uri("/tests").to_request();
+    let resp = test::call_service(&mut srv, req).await;
+    assert_eq!(resp.status(), StatusCode::NOT_FOUND);
+
+    // should redirect if index present
+    let mut srv = test::init_service(
+      App::new().service(
+        Files::new("/", serve_dir("."))
+          .index_file("test.png")
+          .redirect_to_slash_directory(),
+      ),
+    )
+    .await;
+    let req = TestRequest::with_uri("/tests").to_request();
+    let resp = test::call_service(&mut srv, req).await;
+    assert_eq!(resp.status(), StatusCode::FOUND);
+
+    // should not redirect if the path is wrong
+    let req = TestRequest::with_uri("/not_existing").to_request();
+    let resp = test::call_service(&mut srv, req).await;
+    assert_eq!(resp.status(), StatusCode::NOT_FOUND);
+  }
+
+  #[actix_rt::test]
+  async fn test_static_files_bad_directory() {
+    let _st: Files = Files::new("/", serve_dir("missing"));
+    let _st: Files = Files::new("/", serve_dir("Cargo.toml"));
+  }
+
+  #[actix_rt::test]
+  async fn test_default_handler_file_missing() {
+    let mut st = Files::new("/", serve_dir("."))
+      .default_handler(|req: ServiceRequest| {
+        ok(req.into_response(HttpResponse::Ok().body("default content")))
+      })
+      .new_service(())
+      .await
+      .unwrap();
+    let req = TestRequest::with_uri("/missing").to_srv_request();
+
+    let resp = test::call_service(&mut st, req).await;
+    assert_eq!(resp.status(), StatusCode::OK);
+    let bytes = test::read_body(resp).await;
+    assert_eq!(bytes, Bytes::from_static(b"default content"));
+  }
+
+  //     #[actix_rt::test]
+  //     async fn test_serve_index() {
+  //         let st = Files::new(".").index_file("test.binary");
+  //         let req = TestRequest::default().uri("/tests").finish();
+
+  //         let resp = st.handle(&req).respond_to(&req).unwrap();
+  //         let resp = resp.as_msg();
+  //         assert_eq!(resp.status(), StatusCode::OK);
+  //         assert_eq!(
+  //             resp.headers()
+  //                 .get(header::CONTENT_TYPE)
+  //                 .expect("content type"),
+  //             "application/octet-stream"
+  //         );
+  //         assert_eq!(
+  //             resp.headers()
+  //                 .get(header::CONTENT_DISPOSITION)
+  //                 .expect("content disposition"),
+  //             "attachment; filename=\"test.binary\""
+  //         );
+
+  //         let req = TestRequest::default().uri("/tests/").finish();
+  //         let resp = st.handle(&req).respond_to(&req).unwrap();
+  //         let resp = resp.as_msg();
+  //         assert_eq!(resp.status(), StatusCode::OK);
+  //         assert_eq!(
+  //             resp.headers().get(header::CONTENT_TYPE).unwrap(),
+  //             "application/octet-stream"
+  //         );
+  //         assert_eq!(
+  //             resp.headers().get(header::CONTENT_DISPOSITION).unwrap(),
+  //             "attachment; filename=\"test.binary\""
+  //         );
+
+  //         // nonexistent index file
+  //         let req = TestRequest::default().uri("/tests/unknown").finish();
+  //         let resp = st.handle(&req).respond_to(&req).unwrap();
+  //         let resp = resp.as_msg();
+  //         assert_eq!(resp.status(), StatusCode::NOT_FOUND);
+
+  //         let req = TestRequest::default().uri("/tests/unknown/").finish();
+  //         let resp = st.handle(&req).respond_to(&req).unwrap();
+  //         let resp = resp.as_msg();
+  //         assert_eq!(resp.status(), StatusCode::NOT_FOUND);
+  //     }
+
+  //     #[actix_rt::test]
+  //     async fn test_serve_index_nested() {
+  //         let st = Files::new(".").index_file("mod.rs");
+  //         let req = TestRequest::default().uri("/src/client").finish();
+  //         let resp = st.handle(&req).respond_to(&req).unwrap();
+  //         let resp = resp.as_msg();
+  //         assert_eq!(resp.status(), StatusCode::OK);
+  //         assert_eq!(
+  //             resp.headers().get(header::CONTENT_TYPE).unwrap(),
+  //             "text/x-rust"
+  //         );
+  //         assert_eq!(
+  //             resp.headers().get(header::CONTENT_DISPOSITION).unwrap(),
+  //             "inline; filename=\"mod.rs\""
+  //         );
+  //     }
+
+  //     #[actix_rt::test]
+  //     fn integration_serve_index() {
+  //         let mut srv = test::TestServer::with_factory(|| {
+  //             App::new().handler(
+  //                 "test",
+  //                 Files::new(".").index_file("Cargo.toml"),
+  //             )
+  //         });
+
+  //         let request = srv.get().uri(srv.url("/test")).finish().unwrap();
+  //         let response = srv.execute(request.send()).unwrap();
+  //         assert_eq!(response.status(), StatusCode::OK);
+  //         let bytes = srv.execute(response.body()).unwrap();
+  //         let data = Bytes::from(fs::read("Cargo.toml").unwrap());
+  //         assert_eq!(bytes, data);
+
+  //         let request = srv.get().uri(srv.url("/test/")).finish().unwrap();
+  //         let response = srv.execute(request.send()).unwrap();
+  //         assert_eq!(response.status(), StatusCode::OK);
+  //         let bytes = srv.execute(response.body()).unwrap();
+  //         let data = Bytes::from(fs::read("Cargo.toml").unwrap());
+  //         assert_eq!(bytes, data);
+
+  //         // nonexistent index file
+  //         let request = srv.get().uri(srv.url("/test/unknown")).finish().unwrap();
+  //         let response = srv.execute(request.send()).unwrap();
+  //         assert_eq!(response.status(), StatusCode::NOT_FOUND);
+
+  //         let request = srv.get().uri(srv.url("/test/unknown/")).finish().unwrap();
+  //         let response = srv.execute(request.send()).unwrap();
+  //         assert_eq!(response.status(), StatusCode::NOT_FOUND);
+  //     }
+
+  //     #[actix_rt::test]
+  //     fn integration_percent_encoded() {
+  //         let mut srv = test::TestServer::with_factory(|| {
+  //             App::new().handler(
+  //                 "test",
+  //                 Files::new(".").index_file("Cargo.toml"),
+  //             )
+  //         });
+
+  //         let request = srv
+  //             .get()
+  //             .uri(srv.url("/test/%43argo.toml"))
+  //             .finish()
+  //             .unwrap();
+  //         let response = srv.execute(request.send()).unwrap();
+  //         assert_eq!(response.status(), StatusCode::OK);
+  //     }
+}
diff --git a/src/files/named.rs b/src/files/named.rs
new file mode 100644
index 0000000..59f3a54
--- /dev/null
+++ b/src/files/named.rs
@@ -0,0 +1,437 @@
+use std::fs::{File, Metadata};
+use std::io;
+use std::ops::{Deref, DerefMut};
+use std::path::{Path, PathBuf};
+use std::time::{SystemTime, UNIX_EPOCH};
+
+#[cfg(unix)]
+use std::os::unix::fs::MetadataExt;
+
+use bitflags::bitflags;
+use mime_guess::from_path;
+
+use actix_http::body::SizedStream;
+use actix_web::dev::BodyEncoding;
+use actix_web::http::header::{
+    self, Charset, ContentDisposition, DispositionParam, DispositionType, ExtendedValue,
+};
+use actix_web::http::{ContentEncoding, StatusCode};
+use actix_web::{Error, HttpMessage, HttpRequest, HttpResponse, Responder};
+use futures_util::future::{ready, Ready};
+
+use super::chunked::ChunkedReadFile;
+use actix_files::HttpRange;
+
+bitflags! {
+    pub(crate) struct Flags: u8 {
+        const ETAG = 0b0000_0001;
+        const LAST_MD = 0b0000_0010;
+        const CONTENT_DISPOSITION = 0b0000_0100;
+    }
+}
+
+impl Default for Flags {
+    fn default() -> Self {
+        Flags::all()
+    }
+}
+
+/// A file with an associated name.
+#[derive(Debug)]
+pub struct NamedFile {
+    path: PathBuf,
+    file: File,
+    modified: Option<SystemTime>,
+    pub(crate) md: Metadata,
+    pub(crate) flags: Flags,
+    pub(crate) status_code: StatusCode,
+    pub(crate) content_type: mime::Mime,
+    pub(crate) content_disposition: header::ContentDisposition,
+    pub(crate) encoding: Option<ContentEncoding>,
+}
+
+impl NamedFile {
+    /// Creates an instance from a previously opened file.
+    ///
+    /// The given `path` need not exist and is only used to determine the `ContentType` and
+    /// `ContentDisposition` headers.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// use actix_files::NamedFile;
+    /// use std::io::{self, Write};
+    /// use std::env;
+    /// use std::fs::File;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let mut file = File::create("foo.txt")?;
+    ///     file.write_all(b"Hello, world!")?;
+    ///     let named_file = NamedFile::from_file(file, "bar.txt")?;
+    ///     # std::fs::remove_file("foo.txt");
+    ///     Ok(())
+    /// }
+    /// ```
+    pub fn from_file<P: AsRef<Path>>(file: File, path: P) -> io::Result<NamedFile> {
+        let path = path.as_ref().to_path_buf();
+
+        // Get the name of the file and use it to construct default Content-Type
+        // and Content-Disposition values
+        let (content_type, content_disposition) = {
+            let filename = match path.file_name() {
+                Some(name) => name.to_string_lossy(),
+                None => {
+                    return Err(io::Error::new(
+                        io::ErrorKind::InvalidInput,
+                        "Provided path has no filename",
+                    ));
+                }
+            };
+
+            let ct = from_path(&path).first_or_octet_stream();
+            let disposition = match ct.type_() {
+                mime::IMAGE | mime::TEXT | mime::VIDEO => DispositionType::Inline,
+                _ => DispositionType::Attachment,
+            };
+            let mut parameters = vec![DispositionParam::Filename(String::from(filename.as_ref()))];
+            if !filename.is_ascii() {
+                parameters.push(DispositionParam::FilenameExt(ExtendedValue {
+                    charset: Charset::Ext(String::from("UTF-8")),
+                    language_tag: None,
+                    value: filename.into_owned().into_bytes(),
+                }))
+            }
+            let cd = ContentDisposition {
+                disposition,
+                parameters,
+            };
+            (ct, cd)
+        };
+
+        let md = file.metadata()?;
+        let modified = md.modified().ok();
+        let encoding = None;
+        Ok(NamedFile {
+            path,
+            file,
+            content_type,
+            content_disposition,
+            md,
+            modified,
+            encoding,
+            status_code: StatusCode::OK,
+            flags: Flags::default(),
+        })
+    }
+
+    /// Attempts to open a file in read-only mode.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// use actix_files::NamedFile;
+    ///
+    /// let file = NamedFile::open("foo.txt");
+    /// ```
+    pub fn open<P: AsRef<Path>>(path: P) -> io::Result<NamedFile> {
+        Self::from_file(File::open(&path)?, path)
+    }
+
+    /// Returns reference to the underlying `File` object.
+    #[inline]
+    pub fn file(&self) -> &File {
+        &self.file
+    }
+
+    /// Retrieve the path of this file.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// # use std::io;
+    /// use actix_files::NamedFile;
+    ///
+    /// # fn path() -> io::Result<()> {
+    /// let file = NamedFile::open("test.txt")?;
+    /// assert_eq!(file.path().as_os_str(), "foo.txt");
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[inline]
+    pub fn path(&self) -> &Path {
+        self.path.as_path()
+    }
+
+    /// Set response **Status Code**
+    pub fn set_status_code(mut self, status: StatusCode) -> Self {
+        self.status_code = status;
+        self
+    }
+
+    /// Set the MIME Content-Type for serving this file. By default
+    /// the Content-Type is inferred from the filename extension.
+    #[inline]
+    pub fn set_content_type(mut self, mime_type: mime::Mime) -> Self {
+        self.content_type = mime_type;
+        self
+    }
+
+    /// Set the Content-Disposition for serving this file. This allows
+    /// changing the inline/attachment disposition as well as the filename
+    /// sent to the peer. By default the disposition is `inline` for text,
+    /// image, and video content types, and `attachment` otherwise, and
+    /// the filename is taken from the path provided in the `open` method
+    /// after converting it to UTF-8 using.
+    /// [to_string_lossy](https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.to_string_lossy).
+    #[inline]
+    pub fn set_content_disposition(mut self, cd: header::ContentDisposition) -> Self {
+        self.content_disposition = cd;
+        self.flags.insert(Flags::CONTENT_DISPOSITION);
+        self
+    }
+
+    /// Disable `Content-Disposition` header.
+    ///
+    /// By default Content-Disposition` header is enabled.
+    #[inline]
+    pub fn disable_content_disposition(mut self) -> Self {
+        self.flags.remove(Flags::CONTENT_DISPOSITION);
+        self
+    }
+
+    /// Set content encoding for serving this file
+    #[inline]
+    pub fn set_content_encoding(mut self, enc: ContentEncoding) -> Self {
+        self.encoding = Some(enc);
+        self
+    }
+
+    #[inline]
+    ///Specifies whether to use ETag or not.
+    ///
+    ///Default is true.
+    pub fn use_etag(mut self, value: bool) -> Self {
+        self.flags.set(Flags::ETAG, value);
+        self
+    }
+
+    #[inline]
+    ///Specifies whether to use Last-Modified or not.
+    ///
+    ///Default is true.
+    pub fn use_last_modified(mut self, value: bool) -> Self {
+        self.flags.set(Flags::LAST_MD, value);
+        self
+    }
+
+    pub(crate) fn etag(&self) -> Option<header::EntityTag> {
+        // This etag format is similar to Apache's.
+        self.modified.as_ref().map(|mtime| {
+            let ino = {
+                #[cfg(unix)]
+                {
+                    self.md.ino()
+                }
+                #[cfg(not(unix))]
+                {
+                    0
+                }
+            };
+
+            let dur = mtime
+                .duration_since(UNIX_EPOCH)
+                .expect("modification time must be after epoch");
+            header::EntityTag::strong(format!(
+                "{:x}:{:x}:{:x}:{:x}",
+                ino,
+                self.md.len(),
+                dur.as_secs(),
+                dur.subsec_nanos()
+            ))
+        })
+    }
+
+    pub(crate) fn last_modified(&self) -> Option<header::HttpDate> {
+        self.modified.map(|mtime| mtime.into())
+    }
+
+    pub fn into_response(self, req: &HttpRequest) -> Result<HttpResponse, Error> {
+        if self.status_code != StatusCode::OK {
+            let mut resp = HttpResponse::build(self.status_code);
+            resp.set(header::ContentType(self.content_type.clone()))
+                .if_true(self.flags.contains(Flags::CONTENT_DISPOSITION), |res| {
+                    res.header(
+                        header::CONTENT_DISPOSITION,
+                        self.content_disposition.to_string(),
+                    );
+                });
+            if let Some(current_encoding) = self.encoding {
+                resp.encoding(current_encoding);
+            }
+            let reader = ChunkedReadFile::new(self.md.len(), 0, Some(self.file), None, 0);
+            return Ok(resp.streaming(reader));
+        }
+
+        let etag = if self.flags.contains(Flags::ETAG) {
+            self.etag()
+        } else {
+            None
+        };
+        let last_modified = if self.flags.contains(Flags::LAST_MD) {
+            self.last_modified()
+        } else {
+            None
+        };
+
+        // check preconditions
+        let precondition_failed = if !any_match(etag.as_ref(), req) {
+            true
+        } else if let (Some(ref m), Some(header::IfUnmodifiedSince(ref since))) =
+            (last_modified, req.get_header())
+        {
+            let t1: SystemTime = m.clone().into();
+            let t2: SystemTime = since.clone().into();
+            match (t1.duration_since(UNIX_EPOCH), t2.duration_since(UNIX_EPOCH)) {
+                (Ok(t1), Ok(t2)) => t1 > t2,
+                _ => false,
+            }
+        } else {
+            false
+        };
+
+        // check last modified
+        let not_modified = if !none_match(etag.as_ref(), req) {
+            true
+        } else if req.headers().contains_key(&header::IF_NONE_MATCH) {
+            false
+        } else if let (Some(ref m), Some(header::IfModifiedSince(ref since))) =
+            (last_modified, req.get_header())
+        {
+            let t1: SystemTime = m.clone().into();
+            let t2: SystemTime = since.clone().into();
+            match (t1.duration_since(UNIX_EPOCH), t2.duration_since(UNIX_EPOCH)) {
+                (Ok(t1), Ok(t2)) => t1 <= t2,
+                _ => false,
+            }
+        } else {
+            false
+        };
+
+        let mut resp = HttpResponse::build(self.status_code);
+        resp.set(header::ContentType(self.content_type.clone()))
+            .if_true(self.flags.contains(Flags::CONTENT_DISPOSITION), |res| {
+                res.header(
+                    header::CONTENT_DISPOSITION,
+                    self.content_disposition.to_string(),
+                );
+            });
+        // default compressing
+        if let Some(current_encoding) = self.encoding {
+            resp.encoding(current_encoding);
+        }
+
+        resp.if_some(last_modified, |lm, resp| {
+            resp.set(header::LastModified(lm));
+        })
+        .if_some(etag, |etag, resp| {
+            resp.set(header::ETag(etag));
+        });
+
+        resp.header(header::ACCEPT_RANGES, "bytes");
+
+        let mut length = self.md.len();
+        let mut offset = 0;
+
+        // check for range header
+        if let Some(ranges) = req.headers().get(&header::RANGE) {
+            if let Ok(rangesheader) = ranges.to_str() {
+                if let Ok(rangesvec) = HttpRange::parse(rangesheader, length) {
+                    length = rangesvec[0].length;
+                    offset = rangesvec[0].start;
+                    resp.encoding(ContentEncoding::Identity);
+                    resp.header(
+                        header::CONTENT_RANGE,
+                        format!("bytes {}-{}/{}", offset, offset + length - 1, self.md.len()),
+                    );
+                } else {
+                    resp.header(header::CONTENT_RANGE, format!("bytes */{}", length));
+                    return Ok(resp.status(StatusCode::RANGE_NOT_SATISFIABLE).finish());
+                };
+            } else {
+                return Ok(resp.status(StatusCode::BAD_REQUEST).finish());
+            };
+        };
+
+        if precondition_failed {
+            return Ok(resp.status(StatusCode::PRECONDITION_FAILED).finish());
+        } else if not_modified {
+            return Ok(resp.status(StatusCode::NOT_MODIFIED).finish());
+        }
+
+        let reader = ChunkedReadFile::new(length, offset, Some(self.file), None, 0);
+
+        if offset != 0 || length != self.md.len() {
+            resp.status(StatusCode::PARTIAL_CONTENT);
+        }
+
+        Ok(resp.body(SizedStream::new(length, reader)))
+    }
+}
+
+impl Deref for NamedFile {
+    type Target = File;
+
+    fn deref(&self) -> &File {
+        &self.file
+    }
+}
+
+impl DerefMut for NamedFile {
+    fn deref_mut(&mut self) -> &mut File {
+        &mut self.file
+    }
+}
+
+/// Returns true if `req` has no `If-Match` header or one which matches `etag`.
+fn any_match(etag: Option<&header::EntityTag>, req: &HttpRequest) -> bool {
+    match req.get_header::<header::IfMatch>() {
+        None | Some(header::IfMatch::Any) => true,
+        Some(header::IfMatch::Items(ref items)) => {
+            if let Some(some_etag) = etag {
+                for item in items {
+                    if item.strong_eq(some_etag) {
+                        return true;
+                    }
+                }
+            }
+            false
+        }
+    }
+}
+
+/// Returns true if `req` doesn't have an `If-None-Match` header matching `req`.
+fn none_match(etag: Option<&header::EntityTag>, req: &HttpRequest) -> bool {
+    match req.get_header::<header::IfNoneMatch>() {
+        Some(header::IfNoneMatch::Any) => false,
+        Some(header::IfNoneMatch::Items(ref items)) => {
+            if let Some(some_etag) = etag {
+                for item in items {
+                    if item.weak_eq(some_etag) {
+                        return false;
+                    }
+                }
+            }
+            true
+        }
+        None => true,
+    }
+}
+
+impl Responder for NamedFile {
+    type Error = Error;
+    type Future = Ready<Result<HttpResponse, Error>>;
+
+    fn respond_to(self, req: &HttpRequest) -> Self::Future {
+        ready(self.into_response(req))
+    }
+}
diff --git a/src/files/pathbuf.rs b/src/files/pathbuf.rs
new file mode 100644
index 0000000..467f556
--- /dev/null
+++ b/src/files/pathbuf.rs
@@ -0,0 +1,113 @@
+use actix_web::{dev::Payload, http::StatusCode, FromRequest, HttpRequest, ResponseError};
+use futures_util::future::{ready, Ready};
+use snafu::Snafu;
+use std::path::PathBuf;
+
+#[derive(Snafu, Debug, PartialEq)]
+pub enum Error {
+    /// The segment started with the wrapped invalid character.
+    #[snafu(display("The segment started with the wrapped invalid character."))]
+    BadStart { char: char },
+    /// The segment contained the wrapped invalid character.
+    #[snafu(display("The segment contained the wrapped invalid character."))]
+    BadChar { char: char },
+    /// The segment ended with the wrapped invalid character.
+    #[snafu(display("The segment ended with the wrapped invalid character."))]
+    BadEnd { char: char },
+}
+
+/// Return `BadRequest` for `Error`.
+impl ResponseError for Error {
+    fn status_code(&self) -> StatusCode {
+        StatusCode::BAD_REQUEST
+    }
+}
+
+type Result<T, E = Error> = std::result::Result<T, E>;
+
+#[derive(Debug)]
+pub struct UriPathBuf(PathBuf);
+
+impl UriPathBuf {
+    pub fn new(path: &str) -> Result<Self> {
+        let mut buf = PathBuf::new();
+
+        for segment in path.split('/') {
+            if segment == ".." {
+                buf.pop();
+            } else if segment.starts_with('.') {
+                return Err(Error::BadStart { char: '.' });
+            } else if segment.starts_with('*') {
+                return Err(Error::BadStart { char: '*' });
+            } else if segment.ends_with(':') {
+                return Err(Error::BadEnd { char: ':' });
+            } else if segment.ends_with('>') {
+                return Err(Error::BadEnd { char: '>' });
+            } else if segment.ends_with('<') {
+                return Err(Error::BadEnd { char: '<' });
+            } else if segment.is_empty() {
+                continue;
+            } else if cfg!(windows) && segment.contains('\\') {
+                return Err(Error::BadChar { char: '\\' });
+            } else {
+                buf.push(segment)
+            }
+        }
+
+        Ok(UriPathBuf(buf))
+    }
+}
+
+impl FromRequest for UriPathBuf {
+    type Error = Error;
+    type Future = Ready<Result<Self, Self::Error>>;
+    type Config = ();
+
+    fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
+        ready(UriPathBuf::new(req.match_info().path()))
+    }
+}
+
+impl From<UriPathBuf> for PathBuf {
+    fn from(buf: UriPathBuf) -> PathBuf {
+        buf.0
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::{Error, UriPathBuf};
+    use std::{iter::FromIterator, path::PathBuf};
+
+    #[actix_rt::test]
+    async fn test_path_buf() {
+        assert_eq!(
+            UriPathBuf::new("/test/.tt").map(|t| t.0),
+            Err(Error::BadStart { char: '.' })
+        );
+        assert_eq!(
+            UriPathBuf::new("/test/*tt").map(|t| t.0),
+            Err(Error::BadStart { char: '*' })
+        );
+        assert_eq!(
+            UriPathBuf::new("/test/tt:").map(|t| t.0),
+            Err(Error::BadEnd { char: ':' })
+        );
+        assert_eq!(
+            UriPathBuf::new("/test/tt<").map(|t| t.0),
+            Err(Error::BadEnd { char: '<' })
+        );
+        assert_eq!(
+            UriPathBuf::new("/test/tt>").map(|t| t.0),
+            Err(Error::BadEnd { char: '>' })
+        );
+        assert_eq!(
+            UriPathBuf::new("/seg1/seg2/").unwrap().0,
+            PathBuf::from_iter(vec!["seg1", "seg2"])
+        );
+        assert_eq!(
+            UriPathBuf::new("/seg1/../seg2/").unwrap().0,
+            PathBuf::from_iter(vec!["seg2"])
+        );
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..958b56e
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,9 @@
+#[macro_use]
+extern crate log;
+
+pub mod bundle;
+mod config;
+pub mod files;
+mod monitor;
+mod stats;
+pub mod thread;
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..c97f1f4
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,157 @@
+#[macro_use]
+extern crate log;
+
+use actix::prelude::*;
+use lazy_static::lazy_static;
+use monitor::Monitor;
+use server::Server;
+use snafu::{ResultExt, Snafu};
+use stats::StatsServer;
+use std::sync::mpsc;
+use std::{
+  collections::HashSet,
+  net::SocketAddr,
+  sync::{Arc, RwLock},
+};
+
+mod bundle;
+mod config;
+mod files;
+mod monitor;
+mod server;
+mod stats;
+mod thread;
+
+lazy_static! {
+  static ref MONITOR: Monitor = Monitor::new();
+}
+
+#[derive(Snafu, Debug)]
+pub enum Error {
+  OpenConfig {
+    source: config::Error,
+  },
+  Bind {
+    address: SocketAddr,
+    source: std::io::Error,
+  },
+  Unbundle {
+    source: bundle::Error,
+  },
+  Serve {
+    source: server::Error,
+  },
+  ServeStats {
+    source: stats::Error,
+  },
+  RecvNotify,
+}
+
+type Result<T, E = Error> = std::result::Result<T, E>;
+
+#[actix_rt::main]
+async fn main() -> Result<()> {
+  inner_main().await
+}
+
+async fn inner_main() -> Result<()> {
+  MONITOR.init();
+
+  pretty_env_logger::init();
+
+  // Set up a channel for receiving thread notifications.
+  let (monitor_tx, monitor_rx) = mpsc::channel();
+
+  // Keep track of what threads have been started.
+  let mut server_thread_ids = HashSet::new();
+  let mut server_thread_handles = vec![];
+
+  // Load config from current dir.
+  let config = Arc::new(config::from_current_dir().context(OpenConfig)?);
+
+  // Set up unbundler.
+  let serve_dir = Arc::new(RwLock::new(None));
+  let unbundler = Arc::new(bundle::Unbundler::new(config.clone(), serve_dir.clone()));
+
+  // Set up main server.
+  let server = Server::new(config.server.clone(), serve_dir);
+
+  let (server_handle, server_join_handle, server_thread_handle) =
+    server.spawn(monitor_tx.clone()).await.context(Serve)?;
+
+  server_thread_ids.insert(server_join_handle.thread().id());
+  server_thread_handles.push(server_thread_handle);
+
+  // Set up optional stats server.
+  let mut maybe_stats_server_handle = None;
+
+  match &config.stats {
+    Some(stats_config) => {
+      let stats_server = StatsServer::new(stats_config.clone(), unbundler.clone());
+
+      let (stats_server_handle, stats_join_handle, stats_thread_handle) = stats_server
+        .spawn(monitor_tx.clone())
+        .await
+        .context(ServeStats)?;
+
+      maybe_stats_server_handle = Some(stats_server_handle);
+      server_thread_ids.insert(stats_join_handle.thread().id());
+      server_thread_handles.push(stats_thread_handle);
+    }
+    None => {}
+  }
+
+  let (unbundler_join_handle, unbundler_thread_handle) =
+    thread::spawn(monitor_tx.clone(), move || {
+      let test = unbundler.clone();
+      let mut sys = System::new("unbundler");
+
+      let result = sys
+        .block_on(async move { test.enter().await })
+        .context(Unbundle);
+
+      match result {
+        Err(e) => error!("Unbundler failed: {:?}", e),
+        Ok(_) => {}
+      }
+    });
+
+  let (_, monitor_thread_handle) = thread::spawn(monitor_tx.clone(), move || {
+    let mut watched_thread_ids = HashSet::new();
+
+    watched_thread_ids.insert(unbundler_join_handle.thread().id());
+
+    for server_thread_id in server_thread_ids {
+      watched_thread_ids.insert(server_thread_id);
+    }
+
+    match MONITOR.watch(watched_thread_ids) {
+      Err(_) => error!("Failed to watch threads for panics."),
+      Ok(_) => {}
+    }
+  });
+
+  // Wait for a thread to finish.
+  loop {
+    monitor_rx.recv().map_err(|_| Error::RecvNotify)?;
+
+    if Ok(true) == monitor_thread_handle.has_ended() {
+      info!("Stopping servers due to a panic.");
+
+      break;
+    } else if Ok(true) == unbundler_thread_handle.has_ended() {
+      info!("Stopping servers due to unbundler shutdown.");
+
+      break;
+    }
+  }
+
+  // Stop server threads.
+  server_handle.stop(true).await;
+
+  if let Some(stats_server_handle) = maybe_stats_server_handle {
+    stats_server_handle.stop(true).await;
+  }
+
+  Ok(())
+}
diff --git a/src/monitor.rs b/src/monitor.rs
new file mode 100644
index 0000000..5625c5d
--- /dev/null
+++ b/src/monitor.rs
@@ -0,0 +1,140 @@
+use snafu::Snafu;
+use std::{
+  collections::{HashMap, HashSet},
+  panic,
+  sync::{Condvar, Mutex},
+  thread::{self, Thread, ThreadId},
+};
+
+#[derive(Debug, Snafu)]
+pub enum Error {
+  WatchStateLock,
+  #[snafu(display("There should only be one active call to watch()."))]
+  MultipleWatches,
+}
+
+pub type Result<T, E = Error> = std::result::Result<T, E>;
+
+pub struct State {
+  panicked: HashMap<ThreadId, Thread>,
+  watched: Option<HashSet<ThreadId>>,
+}
+
+pub struct Monitor {
+  condvar: Condvar,
+  state: Mutex<State>,
+}
+
+impl Monitor {
+  pub fn new() -> Self {
+    Monitor {
+      condvar: Condvar::new(),
+      state: Mutex::new(State {
+        panicked: HashMap::new(),
+        watched: None,
+      }),
+    }
+  }
+
+  pub fn init(&'static self) -> () {
+    let hook = panic::take_hook();
+
+    panic::set_hook(Box::new(move |panic_info| {
+      match self.state.lock() {
+        Ok(mut state) => {
+          match &state.watched {
+            Some(watched) => {
+              let current_thread = thread::current();
+
+              // Only notify if the thread ID is being watched.
+              if watched.contains(&current_thread.id()) {
+                state.panicked.insert(current_thread.id(), current_thread);
+
+                self.condvar.notify_all();
+              }
+            }
+            None => {}
+          }
+        }
+        Err(_) => error!("Unable to update map of panicked threads."),
+      }
+
+      hook(panic_info)
+    }))
+  }
+
+  pub fn watch(&self, thread_ids: HashSet<ThreadId>) -> Result<Vec<Thread>> {
+    let mut watched_panicked = vec![];
+    let mut state = self.state.lock().map_err(|_| Error::WatchStateLock)?;
+
+    if let Some(_) = state.watched {
+      return Err(Error::MultipleWatches);
+    } else if thread_ids.is_empty() {
+      return Ok(vec![]);
+    }
+
+    state.panicked = HashMap::new();
+    state.watched = Some(thread_ids.clone());
+
+    loop {
+      for thread_id in &thread_ids {
+        if let Some(thread) = state.panicked.get(&thread_id) {
+          watched_panicked.push(thread.clone().clone());
+        }
+      }
+
+      if !watched_panicked.is_empty() {
+        return Ok(watched_panicked);
+      }
+
+      state = self
+        .condvar
+        .wait(state)
+        .map_err(|_| Error::WatchStateLock)?;
+    }
+  }
+}
+
+#[cfg(test)]
+mod tests {
+  use super::Monitor;
+  use lazy_static::lazy_static;
+  use std::{collections::HashSet, sync::mpsc, thread, time::Duration};
+
+  lazy_static! {
+    static ref MONITOR: Monitor = Monitor::new();
+  }
+
+  #[test]
+  pub fn test_watch() {
+    MONITOR.init();
+
+    MONITOR.watch(HashSet::new()).unwrap();
+
+    let (tx, rx) = mpsc::channel();
+
+    let handle = thread::spawn(move || {
+      rx.recv().unwrap();
+
+      panic!("Oh no");
+    });
+
+    let mut thread_ids = HashSet::new();
+    thread_ids.insert(handle.thread().id());
+
+    thread::sleep(Duration::from_millis(10));
+
+    let test_handle = thread::spawn(move || {
+      let watch_result = MONITOR.watch(thread_ids).unwrap();
+
+      assert_eq!(watch_result.is_empty(), false);
+      assert_eq!(watch_result[0].id(), handle.thread().id());
+    });
+
+    thread::sleep(Duration::from_millis(10));
+
+    tx.send(true).unwrap();
+
+    test_handle.join().unwrap();
+  }
+}
diff --git a/src/server.rs b/src/server.rs
new file mode 100644
index 0000000..e1bc12b
--- /dev/null
+++ b/src/server.rs
@@ -0,0 +1,69 @@
+use crate::{config::ServerConfig, files::Files, thread, thread::ThreadHandle};
+use actix::System;
+use actix_web::{
+  dev::Server as ActixServer, middleware::Logger, App, HttpResponse, HttpServer, Responder,
+};
+use snafu::{ResultExt, Snafu};
+use std::{
+  path::PathBuf,
+  sync::{
+    mpsc::{self, RecvError, SendError, Sender},
+    Arc, RwLock,
+  },
+  thread::{JoinHandle, Thread},
+};
+
+#[derive(Debug, Snafu)]
+pub enum Error {
+  ChannelSend { source: SendError<Server> },
+  ChannelReceive { source: RecvError },
+  Bind { source: std::io::Error },
+  SystemRun { source: std::io::Error },
+}
+
+type Result<T, E = Error> = std::result::Result<T, E>;
+
+pub struct Server {
+  config: ServerConfig,
+  serve_dir: Arc<RwLock<Option<PathBuf>>>,
+}
+
+impl Server {
+  pub fn new(config: ServerConfig, serve_dir: Arc<RwLock<Option<PathBuf>>>) -> Self {
+    Server { config, serve_dir }
+  }
+
+  pub async fn spawn(
+    self,
+    notify_sender: Sender<Thread>,
+  ) -> Result<(ActixServer, JoinHandle<Result<()>>, ThreadHandle)> {
+    let (tx, rx) = mpsc::channel();
+
+    let server_address = self.config.address.clone();
+    let serve_dir = Arc::clone(&self.serve_dir);
+
+    let (join_handle, thread_handle) = thread::spawn(notify_sender, move || {
+      let sys = System::new("http-server");
+
+      let srv = HttpServer::new(move || {
+        App::new()
+          .wrap(Logger::default())
+          .service(Files::new("/", Arc::clone(&serve_dir)))
+      })
+      .bind(server_address)
+      .context(Bind)?
+      .shutdown_timeout(60)
+      .run();
+
+      let _ = tx.send(srv);
+
+      sys.run().context(SystemRun)
+    });
+
+    Ok((
+      rx.recv().context(ChannelReceive)?,
+      join_handle,
+      thread_handle,
+    ))
+  }
+}
diff --git a/src/stats.rs b/src/stats.rs
new file mode 100644
index 0000000..1d73db0
--- /dev/null
+++ b/src/stats.rs
@@ -0,0 +1,76 @@
+use crate::thread::{self, ThreadHandle};
+use crate::{bundle::Unbundler, config::StatsConfig};
+use actix::System;
+use actix_web::{dev::Server, middleware::Logger, App, HttpResponse, HttpServer, Responder};
+use mpsc::{RecvError, SendError, Sender};
+use snafu::{ResultExt, Snafu};
+use std::{
+  sync::{mpsc, Arc},
+  thread::{JoinHandle, Thread},
+};
+
+#[derive(Debug, Snafu)]
+pub enum Error {
+  ChannelSend { source: SendError<Server> },
+  ChannelReceive { source: RecvError },
+  Bind { source: std::io::Error },
+  SystemRun { source: std::io::Error },
+}
+
+type Result<T, E = Error> = std::result::Result<T, E>;
+
+struct State {
+  unbundler: Arc<Unbundler>,
+}
+
+pub struct StatsServer {
+  config: StatsConfig,
+  unbundler: Arc<Unbundler>,
+}
+
+impl StatsServer {
+  pub fn new(config: StatsConfig, unbundler: Arc<Unbundler>) -> Self {
+    StatsServer { config, unbundler }
+  }
+
+  pub async fn spawn(
+    self,
+    notify_sender: Sender<Thread>,
+  ) -> Result<(Server, JoinHandle<Result<()>>, ThreadHandle)> {
+    let (tx, rx) = mpsc::channel();
+
+    let (join_handle, thread_handle) = thread::spawn(notify_sender, move || {
+      let sys = System::new("stats-http-server");
+
+      let unbundler = self.unbundler.clone();
+      let server_address = self.config.address;
+
+      let srv = HttpServer::new(move || {
+        App::new()
+          .wrap(Logger::default())
+          .route("/status", actix_web::web::get().to(get_status))
+          .data(State {
+            unbundler: Arc::clone(&unbundler),
+          })
+      })
+      .bind(server_address)
+      .context(Bind)?
+      .shutdown_timeout(60)
+      .run();
+
+      tx.send(srv).context(ChannelSend)?;
+
+      sys.run().context(SystemRun)
+    });
+
+    Ok((
+      rx.recv().context(ChannelReceive)?,
+      join_handle,
+      thread_handle,
+    ))
+  }
+}
+
+async fn get_status(data: actix_web::web::Data<State>) -> impl Responder {
+  HttpResponse::Ok().body(format!("Test {:?}", data.unbundler.get_status().unwrap()))
+}
diff --git a/src/thread.rs b/src/thread.rs
new file mode 100644
index 0000000..5a5404c
--- /dev/null
+++ b/src/thread.rs
@@ -0,0 +1,165 @@
+use mpsc::Sender;
+use snafu::Snafu;
+use std::{
+  sync::{mpsc, Arc, RwLock},
+  thread::JoinHandle,
+};
+
+#[derive(Snafu, Debug, PartialEq)]
+pub enum Error {
+  // Unable to obtain a read lock to check the status of a thread.
+  LockRead,
+}
+
+pub type Result<T, E = Error> = std::result::Result<T, E>;
+
+/// A lightweight abstration over a regular thread that provides an API for
+/// determining if a thread has terminated.
+pub struct ThreadHandle {
+  ended: Arc<RwLock<bool>>,
+}
+
+impl ThreadHandle {
+  /// Attempts to check if the thread has ended.
+  ///
+  /// An error may be returned if the underlying channel is disconnected.
+  pub fn has_ended(&self) -> Result<bool> {
+    let result = self.ended.read().map_err(|_| Error::LockRead)?;
+
+    Ok(result.clone())
+  }
+}
+
+/// Like `std::thread::spawn`, but returns a `ThreadHandle` instead.
+///
+/// # Examples
+///
+/// Create ten threads and wait for all threads to finish.
+///
+/// ```
+/// use espresso::thread::spawn;
+/// use std::{
+///    collections::HashMap,
+///    sync::{mpsc, Arc, Barrier},
+///  };
+///
+/// let (monitor_tx, monitor_rx) = mpsc::channel();
+/// let barrier = Arc::new(Barrier::new(10));
+///
+/// let mut handles = HashMap::new();
+///
+/// for _ in 0..10 {
+///   let bc = barrier.clone();
+///
+///   let (join_handle, thread_handle) = spawn(monitor_tx.clone(), move || {
+///     /// Sync all threads.
+///     bc.wait();
+///   });
+///
+///   handles.insert(join_handle.thread().id(), thread_handle);
+/// }
+///
+/// // Loop until we have been notified of every thread ending.
+/// loop {
+///   let thread = monitor_rx.recv().unwrap();
+///
+///   handles.remove(&thread.id());
+///
+///   if handles.is_empty() {
+///     break;
+///   }
+/// }
+/// ```
+pub fn spawn<F, T>(
+  notify_sender: Sender<std::thread::Thread>,
+  f: F,
+) -> (JoinHandle<T>, ThreadHandle)
+where
+  F: FnOnce() -> T,
+  F: Send + 'static,
+  T: Send + 'static,
+{
+  let ended = Arc::new(RwLock::new(false));
+  let ended_for_spawn = ended.clone();
+
+  let join_handle = std::thread::spawn(move || {
+    let ended = ended_for_spawn.clone();
+
+    let result = f();
+
+    let mut ended = ended.write().unwrap();
+    *ended = true;
+    notify_sender.send(std::thread::current()).unwrap();
+
+    result
+  });
+
+  (join_handle, ThreadHandle { ended })
+}
+
+#[cfg(test)]
+mod tests {
+  use super::spawn;
+  use std::{
+    collections::HashMap,
+    sync::{mpsc, Arc, Barrier},
+  };
+
+  #[test]
+  fn test_spawn() {
+    let (monitor_tx, monitor_rx) = mpsc::channel();
+    let (ready_tx, ready_rx) = mpsc::channel();
+    let (end_tx, end_rx) = mpsc::channel();
+
+    let (join_handle, handle) = spawn(monitor_tx, move || {
+      ready_tx.send(()).unwrap();
+
+      end_rx.recv().unwrap();
+    });
+
+    ready_rx.recv().unwrap();
+
+    assert_eq!((&handle).has_ended(), Ok(false));
+
+    end_tx.send(()).unwrap();
+
+    monitor_rx.recv().unwrap();
+    join_handle.join().unwrap();
+
+    assert_eq!(handle.has_ended(), Ok(true));
+  }
+
+  #[test]
+  fn test_multiple() {
+    let (monitor_tx, monitor_rx) = mpsc::channel();
+    let barrier = Arc::new(Barrier::new(11));
+
+    let mut handles = HashMap::new();
+
+    for _ in 0..10 {
+      let bc = barrier.clone();
+
+      let (join_handle, thread_handle) = spawn(monitor_tx.clone(), move || {
+        bc.wait();
+      });
+
+      handles.insert(join_handle.thread().id(), thread_handle);
+    }
+
+    for (_, handle) in &handles {
+      assert_eq!(handle.has_ended(), Ok(false));
+    }
+
+    barrier.wait();
+
+    loop {
+      let thread = monitor_rx.recv().unwrap();
+
+      handles.remove(&thread.id());
+
+      if handles.is_empty() {
+        break;
+      }
+    }
+  }
+}
diff --git a/stack.yaml b/stack.yaml
deleted file mode 100644
index f2aa4ae..0000000
--- a/stack.yaml
+++ /dev/null
@@ -1,70 +0,0 @@
-# This file was automatically generated by 'stack init'
-#
-# Some commonly used options have been documented as comments in this file.
-# For advanced use and comprehensive documentation of the format, please see:
-# https://docs.haskellstack.org/en/stable/yaml_configuration/
-
-# Resolver to choose a 'specific' stackage snapshot or a compiler version.
-# A snapshot resolver dictates the compiler version and the set of packages
-# to be used for project dependencies. For example:
-#
-# resolver: lts-3.5
-# resolver: nightly-2015-09-21
-# resolver: ghc-7.10.2
-#
-# The location of a snapshot can be provided as a file or url. Stack assumes
-# a snapshot provided as a file might change, whereas a url resource does not.
-#
-# resolver: ./custom-snapshot.yaml
-# resolver: https://example.com/snapshots/2018-01-01.yaml
-resolver: lts-14.17
-
-# User packages to be built.
-# Various formats can be used as shown in the example below.
-#
-# packages:
-# - some-directory
-# - https://example.com/foo/bar/baz-0.0.2.tar.gz
-#   subdirs:
-#   - auto-update
-#   - wai
-packages:
-  - .
-  - ../kawaii
-# Dependency packages to be pulled from upstream that are not in the resolver.
-# These entries can reference officially published versions as well as
-# forks / in-progress versions pinned to a git hash. For example:
-#
-# extra-deps:
-# - acme-missiles-0.3
-# - git: https://github.com/commercialhaskell/stack.git
-#   commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
-#
-extra-deps:
-  []
-  # - git: https://gitlab.chromabits.com/etcinit/kawaii.git
-  #   commit: e44766f543b71895e3cbe1737fa99c9e5ddfc2ba
-#
-# Override default flag values for local packages and extra-deps
-# flags: {}
-
-# Extra package databases containing global packages
-# extra-package-dbs: []
-
-# Control whether we use the GHC we find on the path
-# system-ghc: true
-#
-# Require a specific version of stack, using version ranges
-# require-stack-version: -any # Default
-# require-stack-version: ">=2.1"
-#
-# Override the architecture used by stack, especially useful on Windows
-# arch: i386
-# arch: x86_64
-#
-# Extra directories used by stack for building
-# extra-include-dirs: [/path/to/dir]
-# extra-lib-dirs: [/path/to/dir]
-#
-# Allow a newer minor version of GHC than the snapshot specifies
-# compiler-check: newer-minor
diff --git a/stack.yaml.lock b/stack.yaml.lock
deleted file mode 100644
index fc538c1..0000000
--- a/stack.yaml.lock
+++ /dev/null
@@ -1,12 +0,0 @@
-# This file was autogenerated by Stack.
-# You should not edit this file by hand.
-# For more information, please see the documentation at:
-#   https://docs.haskellstack.org/en/stable/lock_files
-
-packages: []
-snapshots:
-- completed:
-    size: 524799
-    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/14/17.yaml
-    sha256: 1d72b33c0fc048e23f4f18fd76a6ad79dd1d8a3c054644098a71a09855e40c7c
-  original: lts-14.17
diff --git a/tests/test space.binary b/tests/test space.binary
new file mode 100644
index 0000000..ef8ff02
--- /dev/null
+++ b/tests/test space.binary	
@@ -0,0 +1 @@
+ÂTǑɂVù2þvI ª–\ÇRË™–ˆæeސvDØ:è—½¬RVÖYpíÿ;ÍÏGñùp!2÷CŒ.–û®õpA!ûߦÙx	j+Uc÷±©X”c%Û;ï"yì­AI
\ No newline at end of file
diff --git a/tests/test.binary b/tests/test.binary
new file mode 100644
index 0000000..ef8ff02
--- /dev/null
+++ b/tests/test.binary
@@ -0,0 +1 @@
+ÂTǑɂVù2þvI ª–\ÇRË™–ˆæeސvDØ:è—½¬RVÖYpíÿ;ÍÏGñùp!2÷CŒ.–û®õpA!ûߦÙx	j+Uc÷±©X”c%Û;ï"yì­AI
\ No newline at end of file
diff --git a/tests/test.png b/tests/test.png
new file mode 100644
index 0000000000000000000000000000000000000000..2ab19f24f851de6ff5b21662e718f56d27302930
GIT binary patch
literal 67390
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

literal 0
HcmV?d00001

-- 
GitLab