diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 6afa048c1690c880f0e3a564aaccf52bf3632d4b..3ebb21f8b02e9fb903333377272b354396e71af7 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -126,6 +126,20 @@ jobs:
           file: deploy/Dockerfile
           tags: s3rius/rustus:latest,s3rius/rustus:${{env.APP_VERSION}}
 
+  publish_crate:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v2
+      - name: Install stable toolchain
+        uses: actions-rs/toolchain@v1
+        with:
+          toolchain: stable
+          override: true
+      - uses: katyo/publish-crates@v1
+        with:
+          registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}
+
   docker_build_alpine:
     runs-on: ubuntu-latest
     needs:
@@ -152,4 +166,4 @@ jobs:
           file: deploy/alpine.Dockerfile
           tags: s3rius/rustus:${{env.APP_VERSION}}-alpine
           build-args: |
-            app_version=${{env.APP_VERSION}}
\ No newline at end of file
+            app_version=${{env.APP_VERSION}}
diff --git a/Cargo.lock b/Cargo.lock
index decd5b46166d001dbe5212500deca539f0ca3bcb..7a4aef8fc16ce8e3fea1b508e41ae5eb59dc4566 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,23 +2,6 @@
 # It is not intended for manual editing.
 version = 3
 
-[[package]]
-name = "actix-codec"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a36c014a3e811624313b51a227b775ecba55d36ef9462bbaac7d4f13e54c9271"
-dependencies = [
- "bitflags",
- "bytes",
- "futures-core",
- "futures-sink",
- "log",
- "memchr",
- "pin-project-lite",
- "tokio",
- "tokio-util 0.6.9",
-]
-
 [[package]]
 name = "actix-codec"
 version = "0.5.0"
@@ -38,9 +21,9 @@ dependencies = [
 
 [[package]]
 name = "actix-files"
-version = "0.6.0-beta.16"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b49f1b48724a52605ba40b67ede24f5a6cbc246817f9278d280d393a28e8b0e"
+checksum = "d81bde9a79336aa51ebed236e91fc1a0528ff67cfdf4f68ca4c61ede9fd26fb5"
 dependencies = [
  "actix-http",
  "actix-service",
@@ -61,11 +44,11 @@ dependencies = [
 
 [[package]]
 name = "actix-http"
-version = "3.0.0-rc.4"
+version = "3.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "512e43eb60683c4ea2d1183f20076c899b2977849b896d8a639a12bd4652dd6d"
+checksum = "a5885cb81a0d4d0d322864bea1bb6c2a8144626b4fdc625d4c51eba197e7797a"
 dependencies = [
- "actix-codec 0.5.0",
+ "actix-codec",
  "actix-rt",
  "actix-service",
  "actix-utils",
@@ -122,9 +105,9 @@ dependencies = [
 
 [[package]]
 name = "actix-rt"
-version = "2.6.0"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdf3f2183be1241ed4dd22611850b85d38de0b08a09f1f7bcccbd0809084b359"
+checksum = "7ea16c295198e958ef31930a6ef37d0fb64e9ca3b6116e6b93a8bdae96ee1000"
 dependencies = [
  "actix-macros",
  "futures-core",
@@ -133,20 +116,20 @@ dependencies = [
 
 [[package]]
 name = "actix-server"
-version = "2.0.0"
+version = "2.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9e7472ac180abb0a8e592b653744345983a7a14f44691c8394a799d0df4dbbf"
+checksum = "0da34f8e659ea1b077bb4637948b815cd3768ad5a188fdcd74ff4d84240cd824"
 dependencies = [
  "actix-rt",
  "actix-service",
  "actix-utils",
  "futures-core",
  "futures-util",
- "log",
  "mio 0.8.0",
  "num_cpus",
  "socket2",
  "tokio",
+ "tracing",
 ]
 
 [[package]]
@@ -172,11 +155,11 @@ dependencies = [
 
 [[package]]
 name = "actix-web"
-version = "4.0.0-rc.3"
+version = "4.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83e3c85bc4116b69913b03f16cff8cade1212508fcd321847d9cfe3d3e41f991"
+checksum = "f4e5ebffd51d50df56a3ae0de0e59487340ca456f05dd0b90c0a7a6dd6a74d31"
 dependencies = [
- "actix-codec 0.4.2",
+ "actix-codec",
  "actix-http",
  "actix-macros",
  "actix-router",
@@ -187,6 +170,7 @@ dependencies = [
  "actix-web-codegen",
  "ahash",
  "bytes",
+ "bytestring",
  "cfg-if",
  "cookie",
  "derive_more",
@@ -211,9 +195,9 @@ dependencies = [
 
 [[package]]
 name = "actix-web-codegen"
-version = "0.5.0-rc.2"
+version = "4.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d0976042e6ddc82c7d0dedd64d39959bc26d9bba098b2f6c32a73fbef784eaf"
+checksum = "7525bedf54704abb1d469e88d7e7e9226df73778798a69cea5022d53b2ae91bc"
 dependencies = [
  "actix-router",
  "proc-macro2",
@@ -331,9 +315,9 @@ checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
 
 [[package]]
 name = "async-task"
-version = "4.1.0"
+version = "4.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d306121baf53310a3fd342d88dc0824f6bbeace68347593658525565abee8"
+checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9"
 
 [[package]]
 name = "async-trait"
@@ -1091,9 +1075,9 @@ dependencies = [
 
 [[package]]
 name = "h2"
-version = "0.3.11"
+version = "0.3.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e"
+checksum = "62eeb471aa3e3c9197aa4bfeabfe02982f6dc96f750486c0bb0009ac58b26d2b"
 dependencies = [
  "bytes",
  "fnv",
@@ -1306,9 +1290,9 @@ dependencies = [
 
 [[package]]
 name = "ipnet"
-version = "2.3.1"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
+checksum = "35e70ee094dc02fd9c13fdad4940090f22dbd6ac7c9e7094a46cf0232a50bc7c"
 
 [[package]]
 name = "ipnetwork"
@@ -1699,9 +1683,9 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.9.0"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
+checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
 
 [[package]]
 name = "opaque-debug"
@@ -2080,9 +2064,9 @@ dependencies = [
 
 [[package]]
 name = "rbatis"
-version = "3.0.31"
+version = "3.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7d3ebffcbf93beb72bf3854c590b027e8590069d5cb0d9e614ed5adc9e349a5"
+checksum = "c8713306748b70f300b4f95a3155d1ea2b559ebe3dca6c0e6aa02788e83d2b19"
 dependencies = [
  "async-trait",
  "chrono",
@@ -2126,9 +2110,9 @@ dependencies = [
 
 [[package]]
 name = "rbatis-macro-driver"
-version = "3.0.5"
+version = "3.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82273c716eca70f4945cd0485dbc3a525726242ea7fee713ca490f081ca47f86"
+checksum = "7599aab108652a411f5cebd41a4640f3ca42a781c1964afb30d9e6bc3e1cecef"
 dependencies = [
  "html_parser",
  "proc-macro2",
@@ -2216,9 +2200,9 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.2.10"
+version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
+checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c"
 dependencies = [
  "bitflags",
 ]
@@ -2235,9 +2219,9 @@ dependencies = [
 
 [[package]]
 name = "regex"
-version = "1.5.4"
+version = "1.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
+checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -2391,7 +2375,7 @@ dependencies = [
 
 [[package]]
 name = "rustus"
-version = "0.4.6"
+version = "0.4.7"
 dependencies = [
  "actix-files",
  "actix-rt",
@@ -2762,7 +2746,6 @@ version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b555e70fbbf84e269ec3858b7a6515bcfe7a166a7cc9c636dd6efd20431678b6"
 dependencies = [
- "actix-rt",
  "once_cell",
  "tokio",
  "tokio-rustls",
@@ -3087,6 +3070,7 @@ dependencies = [
  "pin-project-lite",
  "signal-hook-registry",
  "socket2",
+ "tokio-macros",
  "winapi",
 ]
 
@@ -3101,6 +3085,17 @@ dependencies = [
  "tokio",
 ]
 
+[[package]]
+name = "tokio-macros"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "tokio-native-tls"
 version = "0.3.0"
@@ -3169,20 +3164,21 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
 
 [[package]]
 name = "tracing"
-version = "0.1.31"
+version = "0.1.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f"
+checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f"
 dependencies = [
  "cfg-if",
+ "log",
  "pin-project-lite",
  "tracing-core",
 ]
 
 [[package]]
 name = "tracing-core"
-version = "0.1.22"
+version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23"
+checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c"
 dependencies = [
  "lazy_static",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index 4af3e82fa119f8c2137e4395399b92dca8b11ab5..74642940f29dc77356ac042aae2baa3eb8077e3d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,36 +1,49 @@
 [package]
 name = "rustus"
-version = "0.4.6"
+version = "0.4.7"
 edition = "2021"
 description = "TUS protocol implementation written in Rust."
+keywords = [
+    "tus",
+    "server",
+    "actix-web",
+]
+license-file = "LICENSE"
+authors = [
+    "Pavel Kirilin <win10@list.ru>",
+    "Maxim Naumov <overlordin777@gmail.com>",
+]
+homepage = "https://github.com/s3rius/rustus"
+readme = "README.md"
+
 
 [[bin]]
 name = "rustus"
 
 [dependencies]
-async-trait = "0.1.52"
+async-trait = "^0.1.52"
 base64 = "^0.13.0"
-lazy_static = "1.4.0"
+lazy_static = "^1.4.0"
 log = "^0.4.14"
-serde_json = "1"
+serde_json = "^1"
 strfmt = "^0.1.6"
 thiserror = "^1.0"
-url = "2.2.2"
-bytes = "1.1.0"
+url = "^2.2.2"
+bytes = "^1.1.0"
 
 [dependencies.futures]
-version = "0.3.21"
+version = "^0.3.21"
 
 [dependencies.serde]
-version = "1"
+version = "^1"
 features = ["derive"]
 
 [dependencies.openssl]
-version = "0.10.38"
+version = "^0.10.38"
 features = ["vendored"]
 
 [dependencies.actix-files]
-version = "0.6.0-beta.13"
+version = "^0.6.0-beta.13"
 
 [dependencies.actix-web]
 version = "^4.0.0-rc.3"
@@ -46,15 +59,15 @@ version = "^0.99.9"
 
 [dependencies.fern]
 features = ["colored"]
-version = "0.6.0"
+version = "^0.6.0"
 
 [dependencies.lapin]
 optional = true
-version = "^1.9.0"
+version = "^1.0.0"
 
 [dependencies.mobc-lapin]
 optional = true
-version = "0.7.0"
+version = "^0.7.0"
 
 [dependencies.mobc-redis]
 optional = true
@@ -62,13 +75,13 @@ version = "^0.7.0"
 
 [dependencies.rbatis]
 default-features = false
-features = ["runtime-actix-rustls", "all-database"]
+features = ["runtime-tokio-rustls", "all-database"]
 optional = true
 version = "^3.0"
 
 [dependencies.rbson]
 optional = true
-version = "2.0"
+version = "^2.0"
 
 [dependencies.reqwest]
 features = ["json"]
@@ -80,15 +93,15 @@ version = "^0.3"
 
 [dependencies.strum]
 features = ["derive"]
-version = "0.23"
+version = "^0.23"
 
 [dependencies.tokio]
-features = ["time", "process", "fs", "io-std", "io-util", "rt-multi-thread", "bytes"]
-version = "1.4.0"
+features = ["time", "process", "fs", "io-std", "io-util", "rt-multi-thread", "bytes", "rt", "macros"]
+version = "^1.4.0"
 
 [dependencies.tokio-amqp]
 optional = true
-version = "1.0.0"
+version = "^1.0.0"
 
 [dependencies.uuid]
 features = ["v4"]
diff --git a/src/info_storages/file_info_storage.rs b/src/info_storages/file_info_storage.rs
index a2cdf351b933153d29e310944c10d150d1adcc72..461ca73b5fa276af0089a6cd618356343e13398c 100644
--- a/src/info_storages/file_info_storage.rs
+++ b/src/info_storages/file_info_storage.rs
@@ -45,7 +45,7 @@ impl InfoStorage for FileInfoStorage {
     async fn set_info(&self, file_info: &FileInfo, create: bool) -> RustusResult<()> {
         let info = file_info.clone();
         let path = self.info_file_path(info.id.as_str());
-        actix_web::rt::task::spawn_blocking(move || {
+        tokio::task::spawn_blocking(move || {
             let file = OpenOptions::new()
                 .write(true)
                 .create(create)
@@ -68,7 +68,7 @@ impl InfoStorage for FileInfoStorage {
 
     async fn get_info(&self, file_id: &str) -> RustusResult<FileInfo> {
         let info_path = self.info_file_path(file_id);
-        actix_web::rt::task::spawn_blocking(move || {
+        tokio::task::spawn_blocking(move || {
             if !info_path.exists() {
                 return Err(RustusError::FileNotFound);
             }
@@ -84,7 +84,7 @@ impl InfoStorage for FileInfoStorage {
     async fn remove_info(&self, file_id: &str) -> RustusResult<()> {
         let id = String::from(file_id);
         let info_path = self.info_file_path(id.as_str());
-        actix_web::rt::task::spawn_blocking(move || {
+        tokio::task::spawn_blocking(move || {
             if !info_path.exists() {
                 return Err(RustusError::FileNotFound);
             }
diff --git a/src/info_storages/models/file_info.rs b/src/info_storages/models/file_info.rs
index 42089ab3f7eee772dd8cc77fab40d27e4d361095..e1dbc45f4f6746500c80c4eb4149d98220b3ec66 100644
--- a/src/info_storages/models/file_info.rs
+++ b/src/info_storages/models/file_info.rs
@@ -91,7 +91,7 @@ impl FileInfo {
 
     pub async fn json(&self) -> RustusResult<String> {
         let info_clone = self.clone();
-        actix_web::rt::task::spawn_blocking(move || {
+        tokio::task::spawn_blocking(move || {
             serde_json::to_string(&info_clone).map_err(RustusError::from)
         })
         .await
@@ -102,7 +102,7 @@ impl FileInfo {
     }
 
     pub async fn from_json(data: String) -> RustusResult<Self> {
-        actix_web::rt::task::spawn_blocking(move || {
+        tokio::task::spawn_blocking(move || {
             serde_json::from_str::<Self>(data.as_str()).map_err(RustusError::from)
         })
         .await
diff --git a/src/main.rs b/src/main.rs
index 400db9f634bc7efa98514cc4047095d7291a6821..16713c62440ab5438afe459584457a7d2bdb3ac3 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -135,7 +135,7 @@ fn setup_logging(app_config: &RustusConf) -> RustusResult<()> {
 
 /// Main program entrypoint.
 #[cfg_attr(coverage, no_coverage)]
-#[actix_web::main]
+#[tokio::main]
 async fn main() -> std::io::Result<()> {
     let app_conf = RustusConf::from_args();
     // Configuring logging.
diff --git a/src/protocol/core/write_bytes.rs b/src/protocol/core/write_bytes.rs
index 93cf9000bbdaeb8b632301907866ccd2a936a483..49418abfcca6a3b82f1bdb1faddba87b9b7f16a1 100644
--- a/src/protocol/core/write_bytes.rs
+++ b/src/protocol/core/write_bytes.rs
@@ -105,7 +105,7 @@ pub async fn write_bytes(
             .hooks_format
             .format(&request, &file_info)?;
         let headers = request.headers().clone();
-        actix_web::rt::spawn(async move {
+        tokio::task::spawn_local(async move {
             state
                 .notification_manager
                 .send_message(message, hook, &headers)
diff --git a/src/protocol/creation/routes.rs b/src/protocol/creation/routes.rs
index c11fe66199e1efe4d8029561b9d7f92d7ef28d07..86c8b3440e421694db23a60c5b50164b3bdfc196 100644
--- a/src/protocol/creation/routes.rs
+++ b/src/protocol/creation/routes.rs
@@ -200,7 +200,7 @@ pub async fn create_file(
         let headers = request.headers().clone();
         // Adding send_message task to tokio reactor.
         // Thin function would be executed in background.
-        actix_web::rt::spawn(async move {
+        tokio::task::spawn_local(async move {
             state
                 .notification_manager
                 .send_message(message, Hook::PostCreate, &headers)
diff --git a/src/protocol/termination/routes.rs b/src/protocol/termination/routes.rs
index 8da92a2a941570621cf593f949f3d77a8b8e6c23..31a5df31015d62e77ba0a962e08cd83507f58fcd 100644
--- a/src/protocol/termination/routes.rs
+++ b/src/protocol/termination/routes.rs
@@ -29,7 +29,7 @@ pub async fn terminate(
                 .hooks_format
                 .format(&request, &file_info)?;
             let headers = request.headers().clone();
-            actix_web::rt::spawn(async move {
+            tokio::task::spawn_local(async move {
                 state
                     .notification_manager
                     .send_message(message, Hook::PostTerminate, &headers)
diff --git a/src/storages/file_storage.rs b/src/storages/file_storage.rs
index 537378fc68b3826852ad10bee628df4df41ad734..86bf09d2c474b879ed7cedc200e22388bf077aef 100644
--- a/src/storages/file_storage.rs
+++ b/src/storages/file_storage.rs
@@ -89,7 +89,7 @@ impl Storage for FileStorage {
         }
         let path = String::from(file_info.path.as_ref().unwrap());
         let force_sync = self.force_fsync;
-        actix_web::rt::task::spawn_blocking(move || {
+        tokio::task::spawn_blocking(move || {
             // Opening file in w+a mode.
             // It means that we're going to append some
             // bytes to the end of a file.
@@ -121,7 +121,7 @@ impl Storage for FileStorage {
         let info = file_info.clone();
         // New path to file.
         let file_path = self.data_file_path(info.id.as_str())?;
-        actix_web::rt::task::spawn_blocking(move || {
+        tokio::task::spawn_blocking(move || {
             // Creating new file.
             OpenOptions::new()
                 .create(true)
@@ -144,7 +144,7 @@ impl Storage for FileStorage {
         parts_info: Vec<FileInfo>,
     ) -> RustusResult<()> {
         let info = file_info.clone();
-        actix_web::rt::task::spawn_blocking(move || {
+        tokio::task::spawn_blocking(move || {
             let mut file = OpenOptions::new()
                 .write(true)
                 .append(true)
@@ -172,7 +172,7 @@ impl Storage for FileStorage {
 
     async fn remove_file(&self, file_info: &FileInfo) -> RustusResult<()> {
         let info = file_info.clone();
-        actix_web::rt::task::spawn_blocking(move || {
+        tokio::task::spawn_blocking(move || {
             // Let's remove the file itself.
             let data_path = PathBuf::from(info.path.as_ref().unwrap().clone());
             if !data_path.exists() {