From a3abfca7304d8a0c6f63306a7655dcb603e02725 Mon Sep 17 00:00:00 2001 From: Sanskar Jethi Date: Wed, 17 Nov 2021 22:56:30 +0000 Subject: [PATCH 1/3] Release v0.8.1 --- Cargo.lock | 2 +- Cargo.toml | 2 +- integration_tests/conftest.py | 3 +++ pyproject.toml | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c03b3a581..3658b0fb4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1180,7 +1180,7 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "robyn" -version = "0.8.0" +version = "0.8.1" dependencies = [ "actix-files", "actix-http", diff --git a/Cargo.toml b/Cargo.toml index efb588d95..3e82fe793 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "robyn" -version = "0.8.0" +version = "0.8.1" authors = ["Sanskar Jethi "] edition = "2018" description = "A web server that is fast!" diff --git a/integration_tests/conftest.py b/integration_tests/conftest.py index d9231a2e6..8e5e37858 100644 --- a/integration_tests/conftest.py +++ b/integration_tests/conftest.py @@ -14,6 +14,7 @@ def session(): time.sleep(1) yield process.terminate() + del os.environ["ROBYN_URL"] @pytest.fixture def global_session(): @@ -24,5 +25,7 @@ def global_session(): time.sleep(1) yield process.terminate() + del os.environ["ROBYN_URL"] + diff --git a/pyproject.toml b/pyproject.toml index e1d06d34b..09ed29b9e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "robyn" -version = "0.8.0" +version = "0.8.1" description = "A web server that is fast!" authors = ["Sanskar Jethi "] From 0d579192e74d6e72626abbcf26e1e2058f581daf Mon Sep 17 00:00:00 2001 From: Sanskar Jethi Date: Wed, 1 Dec 2021 23:53:41 +0000 Subject: [PATCH 2/3] Add Web Socket Integration Part 1 (#109) * Implement web sockets * Add method handling in web sockets * Working web sockets * Web socket support works with sync functions * Clean code --- Cargo.lock | 475 +++++++++++++++----------- Cargo.toml | 2 + docs/api.md | 62 +++- docs/roadmap.md | 2 - integration_tests/base_routes.py | 31 +- integration_tests/conftest.py | 1 + integration_tests/test_web_sockets.py | 18 + robyn/__init__.py | 10 +- robyn/processpool.py | 8 +- robyn/test-requirements.txt | 2 + robyn/ws.py | 27 ++ src/lib.rs | 1 + src/processor.rs | 5 +- src/router.rs | 85 ++++- src/server.rs | 60 +++- src/web_socket_connection.rs | 116 +++++++ 16 files changed, 667 insertions(+), 238 deletions(-) create mode 100644 integration_tests/test_web_sockets.py create mode 100644 robyn/ws.py create mode 100644 src/web_socket_connection.rs diff --git a/Cargo.lock b/Cargo.lock index 3658b0fb4..1f7e23872 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,16 +1,41 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "actix" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3720d0064a0ce5c0de7bd93bdb0a6caebab2a9b5668746145d7b3b0c5da02914" +dependencies = [ + "actix-rt", + "actix_derive", + "bitflags", + "bytes", + "crossbeam-channel", + "futures-core", + "futures-sink", + "futures-task", + "futures-util", + "log", + "once_cell", + "parking_lot", + "pin-project-lite", + "smallvec", + "tokio", + "tokio-util", +] + [[package]] name = "actix-codec" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d5dbeb2d9e51344cb83ca7cc170f1217f9fe25bfc50160e6e200b5c31c1019a" +checksum = "13895df506faee81e423febbae3a33b27fca71831b96bb3d60adf16ebcfea952" dependencies = [ "bitflags", "bytes", "futures-core", "futures-sink", "log", + "memchr", "pin-project-lite", "tokio", "tokio-util", @@ -18,13 +43,12 @@ dependencies = [ [[package]] name = "actix-files" -version = "0.6.0-beta.6" +version = "0.6.0-beta.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b864740ed79d26e6e3c33fd2a1e03a071daaa43c88e6900ff1f9378fca88ce" +checksum = "e963fdf6f2108738b0cce01d5df9cd2a78afa03f362ee8be08c0f948f75d1cd7" dependencies = [ "actix-http", "actix-service", - "actix-utils", "actix-web", "askama_escape", "bitflags", @@ -36,18 +60,18 @@ dependencies = [ "mime", "mime_guess", "percent-encoding", + "pin-project-lite", ] [[package]] name = "actix-http" -version = "3.0.0-beta.8" +version = "3.0.0-beta.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd16d6b846983ffabfd081e1a67abd7698094fcbe7b3d9bcf1acbc6f546a516" +checksum = "1bc3f9d97e32d75fae3ad7d955ac005eea3fd3ea60a89132768700911a60fd94" dependencies = [ "actix-codec", "actix-rt", "actix-service", - "actix-tls", "actix-utils", "ahash", "base64", @@ -63,30 +87,26 @@ dependencies = [ "h2", "http", "httparse", + "httpdate", "itoa", "language-tags", "local-channel", "log", "mime", - "once_cell", "percent-encoding", "pin-project", "pin-project-lite", "rand", - "regex", - "serde", "sha-1", "smallvec", - "time", - "tokio", "zstd", ] [[package]] name = "actix-macros" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f86cd6857c135e6e9fe57b1619a88d1f94a7df34c00e11fe13e64fd3438837" +checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6" dependencies = [ "quote", "syn", @@ -94,11 +114,12 @@ dependencies = [ [[package]] name = "actix-router" -version = "0.2.7" +version = "0.5.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad299af73649e1fc893e333ccf86f377751eb95ff875d095131574c6f43452c" +checksum = "36b95ce0d76d1aa2f98b681702807475ade0f99bd4552546a6843a966d42ea3d" dependencies = [ "bytestring", + "firestorm", "http", "log", "regex", @@ -107,9 +128,9 @@ dependencies = [ [[package]] name = "actix-rt" -version = "2.2.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc7d7cd957c9ed92288a7c3c96af81fa5291f65247a76a34dac7b6af74e52ba0" +checksum = "05c2f80ce8d0c990941c7a7a931f69fd0701b76d521f8d36298edf59cd3fbf1f" dependencies = [ "actix-macros", "futures-core", @@ -118,49 +139,33 @@ dependencies = [ [[package]] name = "actix-server" -version = "2.0.0-beta.5" +version = "2.0.0-beta.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26369215fcc3b0176018b3b68756a8bcc275bb000e6212e454944913a1f9bf87" +checksum = "411dd3296dd317ff5eff50baa13f31923ea40ec855dd7f2d3ed8639948f0195f" dependencies = [ "actix-rt", "actix-service", "actix-utils", "futures-core", + "futures-util", "log", "mio", "num_cpus", - "slab", + "socket2", "tokio", ] [[package]] name = "actix-service" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f5f9d66a8730d0fae62c26f3424f5751e5518086628a40b7ab6fca4a705034" +checksum = "8d3dc6a618b082974a08d7a4781d24d4691cba51500059bfebe6656a61ebfe1e" dependencies = [ "futures-core", - "paste 1.0.5", + "paste 1.0.6", "pin-project-lite", ] -[[package]] -name = "actix-tls" -version = "3.0.0-beta.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65b7bb60840962ef0332f7ea01a57d73a24d2cb663708511ff800250bbfef569" -dependencies = [ - "actix-codec", - "actix-rt", - "actix-service", - "actix-utils", - "derive_more", - "futures-core", - "http", - "log", - "tokio-util", -] - [[package]] name = "actix-utils" version = "3.0.0" @@ -173,9 +178,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.0.0-beta.8" +version = "4.0.0-beta.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c503f726f895e55dac39adeafd14b5ee00cc956796314e9227fc7ae2e176f443" +checksum = "e87cfc4efaad42f8a054e269d1b85046397ff4e8707e49128dea3f99a512a9d6" dependencies = [ "actix-codec", "actix-http", @@ -200,7 +205,7 @@ dependencies = [ "log", "mime", "once_cell", - "paste 1.0.5", + "paste 1.0.6", "pin-project", "regex", "serde", @@ -208,15 +213,44 @@ dependencies = [ "serde_urlencoded", "smallvec", "socket2", - "time", + "time 0.3.5", "url", ] +[[package]] +name = "actix-web-actors" +version = "4.0.0-beta.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b43c8e03f1877bc010316de455ee479aa0de0ae0717d49041db5f38fa192de" +dependencies = [ + "actix", + "actix-codec", + "actix-http", + "actix-web", + "bytes", + "bytestring", + "futures-core", + "pin-project", + "tokio", +] + [[package]] name = "actix-web-codegen" -version = "0.5.0-beta.3" +version = "0.5.0-beta.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfe80a8828fa88a0420dc8fdd4c16b8207326c917f17701881b063eadc2a8d3b" +dependencies = [ + "actix-router", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "actix_derive" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d048c6986743105c1e8e9729fbc8d5d1667f2f62393a58be8d85a7d9a5a6c8d" +checksum = "6d44b8fee1ced9671ba043476deddef739dd0959bf77030b26b738cc591737a7" dependencies = [ "proc-macro2", "quote", @@ -231,9 +265,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ "getrandom", "once_cell", @@ -251,9 +285,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.42" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486" +checksum = "0a03e93e97a28fbc9f42fbc5ba0886a3c67eb637b476dbee711f80a6ffe8223d" [[package]] name = "askama_escape" @@ -281,9 +315,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block-buffer" @@ -316,15 +350,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.7.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" +checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" [[package]] name = "bytes" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "bytestring" @@ -337,9 +371,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.69" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" dependencies = [ "jobserver", ] @@ -369,33 +403,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f1c7727e460397e56abc4bddc1d49e07a1ad78fc98eb2e1c8f032a58a2f80d" dependencies = [ "percent-encoding", - "time", + "time 0.2.27", "version_check", ] [[package]] name = "cpufeatures" -version = "0.1.5" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.2.1" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3825b1e8580894917dc4468cb634a1b4e9745fddc854edad72d9c04644c0319f" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" dependencies = [ "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +dependencies = [ + "cfg-if", + "lazy_static", ] [[package]] name = "ctor" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" +checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" dependencies = [ "quote", "syn", @@ -447,18 +501,24 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "encoding_rs" -version = "0.8.28" +version = "0.8.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" +checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746" dependencies = [ "cfg-if", ] +[[package]] +name = "firestorm" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31586bda1b136406162e381a3185a506cdfc1631708dd40cba2f6628d8634499" + [[package]] name = "flate2" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" dependencies = [ "cfg-if", "crc32fast", @@ -484,9 +544,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.16" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b" +checksum = "8cd0210d8c325c245ff06fd95a3b13689a1a276ac8cfa8e8720cb840bfb84b9e" dependencies = [ "futures-channel", "futures-core", @@ -499,9 +559,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.16" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9" +checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27" dependencies = [ "futures-core", "futures-sink", @@ -509,15 +569,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.16" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99" +checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445" [[package]] name = "futures-executor" -version = "0.3.16" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d0d535a57b87e1ae31437b892713aee90cd2d7b0ee48727cd11fc72ef54761c" +checksum = "7b808bf53348a36cab739d7e04755909b9fcaaa69b7d7e588b37b6ec62704c97" dependencies = [ "futures-core", "futures-task", @@ -526,18 +586,16 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.16" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582" +checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11" [[package]] name = "futures-macro" -version = "0.3.16" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57" +checksum = "a89f17b21645bc4ed773c69af9c9a0effd4a3f1a3876eadd453469f8854e7fdd" dependencies = [ - "autocfg", - "proc-macro-hack", "proc-macro2", "quote", "syn", @@ -545,23 +603,22 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.16" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53" +checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af" [[package]] name = "futures-task" -version = "0.3.16" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2" +checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12" [[package]] name = "futures-util" -version = "0.3.16" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78" +checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e" dependencies = [ - "autocfg", "futures-channel", "futures-core", "futures-io", @@ -571,8 +628,6 @@ dependencies = [ "memchr", "pin-project-lite", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] @@ -610,9 +665,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.3" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "825343c4eef0b63f541f8903f395dc5beb362a979b5799a84062527ef1e37726" +checksum = "7fd819562fcebdac5afc5c113c3ec36f902840b70fd4fc458799c8ce4607ae55" dependencies = [ "bytes", "fnv", @@ -644,9 +699,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" +checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" dependencies = [ "bytes", "fnv", @@ -661,9 +716,15 @@ checksum = "eee9694f83d9b7c09682fdb32213682939507884e5bcf227be9aff5d644b90dc" [[package]] name = "httparse" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68" +checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "idna" @@ -711,18 +772,18 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", ] [[package]] name = "inventory" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0f7efb804ec95e33db9ad49e4252f049e37e8b0a4652e3cd61f7999f2eff7f" +checksum = "f0eb5160c60ba1e809707918ee329adb99d222888155835c6feedba19f6c3fd4" dependencies = [ "ctor", "ghost", @@ -731,9 +792,9 @@ dependencies = [ [[package]] name = "inventory-impl" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75c094e94816723ab936484666968f5b58060492e880f3c8d00489a1e244fa51" +checksum = "7e41b53715c6f0c4be49510bb82dee2c1e51c8586d885abe65396e82ed518548" dependencies = [ "proc-macro2", "quote", @@ -742,15 +803,15 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "jobserver" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5ca711fd837261e14ec9e674f092cbb931d3fa1482b017ae59328ddc6f3212b" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" dependencies = [ "libc", ] @@ -769,9 +830,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.98" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119" [[package]] name = "local-channel" @@ -793,9 +854,9 @@ checksum = "84f9a2d3e27ce99ce2c3aad0b09b1a7b916293ea9b2bf624c13fe646fadd8da4" [[package]] name = "lock_api" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" dependencies = [ "scopeguard", ] @@ -811,21 +872,21 @@ dependencies = [ [[package]] name = "matches" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "matchit" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96eb506a2b58cf156e8ea212ec185d0e3a24014d8381c9f73cca8fe3d6e86546" +checksum = "58b6f41fdfbec185dd3dff58b51e323f5bc61692c0de38419a957b0dcfccca3c" [[package]] name = "memchr" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "mime" @@ -855,9 +916,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" dependencies = [ "libc", "log", @@ -908,9 +969,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "parking_lot" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", @@ -919,9 +980,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ "cfg-if", "instant", @@ -943,9 +1004,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" +checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" [[package]] name = "paste-impl" @@ -1005,9 +1066,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" [[package]] name = "proc-macro-hack" @@ -1015,26 +1076,20 @@ version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" - [[package]] name = "proc-macro2" -version = "1.0.28" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" +checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" dependencies = [ "unicode-xid", ] [[package]] name = "pyo3" -version = "0.14.1" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "338f7f3701e11fd7f76508c91fbcaabc982564bcaf4d1ca7e1574ff2b4778aec" +checksum = "35100f9347670a566a67aa623369293703322bb9db77d99d7df7313b575ae0c8" dependencies = [ "cfg-if", "indoc", @@ -1048,13 +1103,14 @@ dependencies = [ [[package]] name = "pyo3-asyncio" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08097b330a06c83c704112fde04d27dda074818451809a4384b2a66c6d51d7b9" +checksum = "d4c1305dd07022dff29a85b0a9fcf414bee3139d35730acd4d0268b352c02e57" dependencies = [ "futures", "inventory", "once_cell", + "pin-project-lite", "pyo3", "pyo3-asyncio-macros", "tokio", @@ -1062,9 +1118,9 @@ dependencies = [ [[package]] name = "pyo3-asyncio-macros" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3be08f3da9195947db0b6b64a9a5e91da602444c76f96ed32748d1ef1a89961" +checksum = "8a93d8c020d68356d2ecb36b3462529f38e7b87ca6c54d2a8cc5479fb731e699" dependencies = [ "proc-macro2", "quote", @@ -1073,18 +1129,18 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.14.1" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb2e98cc9ccc83d4f7115c8f925e0057e88c8d324b1bc4c2db4a7270c06ac9d" +checksum = "d12961738cacbd7f91b7c43bc25cfeeaa2698ad07a04b3be0aa88b950865738f" dependencies = [ "once_cell", ] [[package]] name = "pyo3-macros" -version = "0.14.1" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb8671a42d0ecc4bec8cc107ae96d49292ca20cd1968e09b98af4aafd516adf" +checksum = "fc0bc5215d704824dfddddc03f93cb572e1155c68b6761c37005e1c288808ea8" dependencies = [ "pyo3-macros-backend", "quote", @@ -1093,9 +1149,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.14.1" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9addf6dc422f05d4949cc0990195ee74fa43e3c3780cc9a1972fe9e7b68a9f48" +checksum = "71623fc593224afaab918aa3afcaf86ed2f43d34f6afde7f3922608f253240df" dependencies = [ "proc-macro2", "pyo3-build-config", @@ -1105,9 +1161,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" dependencies = [ "proc-macro2", ] @@ -1154,9 +1210,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ "bitflags", ] @@ -1182,9 +1238,11 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" name = "robyn" version = "0.8.1" dependencies = [ + "actix", "actix-files", "actix-http", "actix-web", + "actix-web-actors", "anyhow", "dashmap", "futures-util", @@ -1260,18 +1318,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.127" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8" +checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.127" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc" +checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" dependencies = [ "proc-macro2", "quote", @@ -1280,9 +1338,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.66" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127" +checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527" dependencies = [ "itoa", "ryu", @@ -1303,9 +1361,9 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a0c8611594e2ab4ebbf06ec7cbbf0a99450b8570e96cbf5188b5d5f6ef18d81" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ "block-buffer", "cfg-if", @@ -1331,21 +1389,21 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] name = "smallvec" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" [[package]] name = "socket2" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765f090f0e423d2b55843402a07915add955e7d60657db13707a159727326cad" +checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" dependencies = [ "libc", "winapi", @@ -1411,9 +1469,9 @@ checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" [[package]] name = "syn" -version = "1.0.74" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" dependencies = [ "proc-macro2", "quote", @@ -1435,6 +1493,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "time" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41effe7cfa8af36f439fac33861b66b049edc6f9a32331e2312660529c1c24ad" +dependencies = [ + "itoa", + "libc", +] + [[package]] name = "time-macros" version = "0.1.1" @@ -1460,9 +1528,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.3.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" dependencies = [ "tinyvec_macros", ] @@ -1475,9 +1543,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.9.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b7b349f11a7047e6d1276853e612d152f5e8a352c61917887cc2169e2366b4c" +checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144" dependencies = [ "autocfg", "bytes", @@ -1495,9 +1563,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.3.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110" +checksum = "c9efc1aba077437943f7515666aa2b882dfabfbfdf89c819ea75a8d6e9eaba5e" dependencies = [ "proc-macro2", "quote", @@ -1506,9 +1574,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.7" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592" +checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" dependencies = [ "bytes", "futures-core", @@ -1520,9 +1588,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.26" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d" +checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ "cfg-if", "pin-project-lite", @@ -1531,18 +1599,18 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.18" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052" +checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" dependencies = [ "lazy_static", ] [[package]] name = "typenum" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" [[package]] name = "ucd-trie" @@ -1561,12 +1629,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" -dependencies = [ - "matches", -] +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" [[package]] name = "unicode-normalization" @@ -1615,9 +1680,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.75" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b608ecc8f4198fe8680e2ed18eccab5f0cd4caaf3d83516fa5fb2e927fda2586" +checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1625,9 +1690,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.75" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "580aa3a91a63d23aac5b6b267e2d13cb4f363e31dce6c352fca4752ae12e479f" +checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" dependencies = [ "bumpalo", "lazy_static", @@ -1640,9 +1705,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.75" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171ebf0ed9e1458810dfcb31f2e766ad6b3a89dbda42d8901f2b268277e5f09c" +checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1650,9 +1715,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.75" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c2657dd393f03aa2a659c25c6ae18a13a4048cebd220e147933ea837efc589f" +checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" dependencies = [ "proc-macro2", "quote", @@ -1663,9 +1728,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.75" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e0c4a743a309662d45f4ede961d7afa4ba4131a59a639f29b0069c3798bbcc2" +checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" [[package]] name = "winapi" @@ -1691,18 +1756,18 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "zstd" -version = "0.7.0+zstd.1.4.9" +version = "0.9.0+zstd.1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9428752481d8372e15b1bf779ea518a179ad6c771cca2d2c60e4fbff3cc2cd52" +checksum = "07749a5dc2cb6b36661290245e350f15ec3bbb304e493db54a1d354480522ccd" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "3.1.0+zstd.1.4.9" +version = "4.1.1+zstd.1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa1926623ad7fe406e090555387daf73db555b948134b4d73eac5eb08fb666d" +checksum = "c91c90f2c593b003603e5e0493c837088df4469da25aafff8bce42ba48caf079" dependencies = [ "libc", "zstd-sys", @@ -1710,9 +1775,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "1.5.0+zstd.1.4.9" +version = "1.6.1+zstd.1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e6c094340240369025fc6b731b054ee2a834328fa584310ac96aa4baebdc465" +checksum = "615120c7a2431d16cf1cf979e7fc31ba7a5b5e5707b29c8a99e5dbf8a8392a33" dependencies = [ "cc", "libc", diff --git a/Cargo.toml b/Cargo.toml index 3e82fe793..10c5e716c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,8 @@ futures-util = "0.3.15" matchit = "0.4.3" actix-http = "3.0.0-beta.8" socket2 = { version = "0.4.1", features = ["all"] } +actix = "0.12.0" +actix-web-actors = "4.0.0-beta.1" [package.metadata.maturin] name = "robyn" diff --git a/docs/api.md b/docs/api.md index 52f3dbeab..f7a89ac51 100644 --- a/docs/api.md +++ b/docs/api.md @@ -90,8 +90,17 @@ Robyn supports every HTTP request method. The examples of some of them are below ``` +### Having Dynamic Routes +You can now add params in the routes and access them from the request object. -## Returning a JSON Response +```python3 +@app.post("/jsonify/:id") +async def json(request): + print(request["params"]["id"]) + return jsonify({"hello": "world"}) +``` + +### Returning a JSON Response You can also serve JSON responses when serving HTTP request using the following way. ```python3 @@ -139,4 +148,53 @@ app.add_header("server", "robyn") ``` -To see a complete service in action, you can go to the folder [../test_python/test.py](../test_python/test.py) +## WebSockets + +You can now serve websockets using Robyn. + +Firstly, you need to create a WebSocket Class and wrap it around your Robyn app. + +```python3 +from robyn import Robyn, static_file, jsonify, WS + + +app = Robyn(__file__) +websocket = WS(app, "/web_socket") +``` + +Now, you can define 3 methods for every web_socket for their lifecycle, they are as follows: + +```python3 +@websocket.on("message") +def connect(): + global i + i+=1 + if i==0: + return "Whaaat??" + elif i==1: + return "Whooo??" + elif i==2: + return "*chika* *chika* Slim Shady." + elif i==3: + i= -1 + return "" + +@websocket.on("close") +def close(): + return "Goodbye world, from ws" + +@websocket.on("connect") +def message(): + return "Hello world, from ws" + +``` + + +## MutliCore Scaling + +The three methods: + - "message" is called when the socket receives a message + - "close" is called when the socket is disconnected + - "connect" is called when the socket connects + +To see a complete service in action, you can go to the folder [../integration_tests/base_routes.py](../integration_tests/base_routes.py) diff --git a/docs/roadmap.md b/docs/roadmap.md index f23283886..da5533524 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,8 +1,6 @@ ## Future Roadmap -- Integrate actix router - Integrate WebSockets -- Reveal Logo - Add session/cookie plugins - Add the plugin documentation diff --git a/integration_tests/base_routes.py b/integration_tests/base_routes.py index 023b6205c..5cf09d685 100644 --- a/integration_tests/base_routes.py +++ b/integration_tests/base_routes.py @@ -1,14 +1,33 @@ - - -# robyn_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../robyn") -# sys.path.insert(0, robyn_path) - -from robyn import Robyn, static_file, jsonify, SocketHeld +from robyn import Robyn, static_file, jsonify, WS import asyncio import os import pathlib app = Robyn(__file__) +websocket = WS(app, "/web_socket") +i = -1 + +@websocket.on("message") +def connect(): + global i + i+=1 + if i==0: + return "Whaaat??" + elif i==1: + return "Whooo??" + elif i==2: + i = -1 + return "*chika* *chika* Slim Shady." + +@websocket.on("close") +def close(): + print("Hello world") + return "Hello world, from ws" + +@websocket.on("connect") +def message(): + print("Hello world") + return "Hello world, from ws" callCount = 0 diff --git a/integration_tests/conftest.py b/integration_tests/conftest.py index 8e5e37858..ce256c7ad 100644 --- a/integration_tests/conftest.py +++ b/integration_tests/conftest.py @@ -7,6 +7,7 @@ @pytest.fixture def session(): + subprocess.call(["freeport", "5000"]) os.environ["ROBYN_URL"] = "127.0.0.1" current_file_path = pathlib.Path(__file__).parent.resolve() base_routes = os.path.join(current_file_path, "./base_routes.py") diff --git a/integration_tests/test_web_sockets.py b/integration_tests/test_web_sockets.py new file mode 100644 index 000000000..69f71c72a --- /dev/null +++ b/integration_tests/test_web_sockets.py @@ -0,0 +1,18 @@ +from websockets import connect +import asyncio + +BASE_URL = "ws://127.0.0.1:5000" + +def test_web_socket(session): + async def start_ws(uri): + async with connect(uri) as websocket: + await websocket.send("My name is?") + assert( await websocket.recv() == "Whaaat??") + await websocket.send("My name is?") + assert( await websocket.recv() == "Whooo??") + await websocket.send("My name is?") + assert( await websocket.recv() == "*chika* *chika* Slim Shady.") + + asyncio.run(start_ws(f"{BASE_URL}/web_socket")) + + diff --git a/robyn/__init__.py b/robyn/__init__.py index c5cebcc81..6113c708b 100644 --- a/robyn/__init__.py +++ b/robyn/__init__.py @@ -12,6 +12,7 @@ from .dev_event_handler import EventHandler from .processpool import spawn_process from .log_colors import Colors +from .ws import WS # 3rd party imports and exports @@ -36,6 +37,7 @@ def __init__(self, file_object): self.headers = [] self.routes = [] self.directories = [] + self.web_sockets = {} def add_route(self, route_type, endpoint, handler): @@ -62,6 +64,10 @@ def add_header(self, key, value): def remove_header(self, key): self.server.remove_header(key) + + def add_web_socket(self, endpoint, ws): + self.web_sockets[endpoint] = ws + def start(self, url="127.0.0.1", port=5000): """ @@ -76,7 +82,7 @@ def start(self, url="127.0.0.1", port=5000): copied = socket.try_clone() p = Process( target=spawn_process, - args=(url, port, self.directories, self.headers, self.routes, copied, f"Process {process_number}", workers), + args=(url, port, self.directories, self.headers, self.routes, self.web_sockets, copied, f"Process {process_number}", workers), ) p.start() @@ -95,6 +101,7 @@ def start(self, url="127.0.0.1", port=5000): observer.stop() observer.join() + def get(self, endpoint): """ [The @app.get decorator to add a get route] @@ -195,3 +202,4 @@ def inner(handler): return inner + diff --git a/robyn/processpool.py b/robyn/processpool.py index 07b247a90..729ff1c8c 100644 --- a/robyn/processpool.py +++ b/robyn/processpool.py @@ -9,7 +9,7 @@ mp.allow_connection_pickling() -def spawn_process(url, port, directories, headers, routes, socket, process_name, workers): +def spawn_process(url, port, directories, headers, routes, web_sockets, socket, process_name, workers): """ This function is called by the main process handler to create a server runtime. This functions allows one runtime per process. @@ -51,5 +51,11 @@ def spawn_process(url, port, directories, headers, routes, socket, process_name, route_type, endpoint, handler, is_async, number_of_params = route server.add_route(route_type, endpoint, handler, is_async, number_of_params) + for endpoint in web_sockets: + web_socket = web_sockets[endpoint] + print(web_socket.methods) + server.add_web_socket_route(endpoint, web_socket.methods["connect"], web_socket.methods["close"], web_socket.methods["message"]) + + server.start(url, port, socket, process_name, workers) asyncio.get_event_loop().run_forever() diff --git a/robyn/test-requirements.txt b/robyn/test-requirements.txt index 3977436a3..7b87038d3 100644 --- a/robyn/test-requirements.txt +++ b/robyn/test-requirements.txt @@ -4,3 +4,5 @@ watchdog requests==2.26.0 uvloop==0.16.0 multiprocess==0.70.12.2 +websockets==10.1 +freeport==0.1.15 diff --git a/robyn/ws.py b/robyn/ws.py new file mode 100644 index 000000000..ffc590462 --- /dev/null +++ b/robyn/ws.py @@ -0,0 +1,27 @@ +import asyncio +from inspect import signature + +class WS: + """This is the python wrapper for the web socket that will be used here. + """ + def __init__(self, robyn_object, endpoint) -> None: + self.robyn_object = robyn_object + self.endpoint = endpoint + self.methods = {} + + def on(self, type): + def inner(handler): + if type not in ["connect", "close", "message"]: + raise Exception(f"Socket method {type} does not exist") + else: + self.methods[type] = ( handler, self._is_async(handler), self._num_params(handler) ) + self.robyn_object.add_web_socket(self.endpoint, self) + + return inner + + def _num_params(self, handler): + return len(signature(handler).parameters) + + def _is_async(self, handler): + return asyncio.iscoroutinefunction(handler) + diff --git a/src/lib.rs b/src/lib.rs index 8b68e660a..e62184a2c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ mod router; mod server; mod shared_socket; mod types; +mod web_socket_connection; use server::Server; use shared_socket::SocketHeld; diff --git a/src/processor.rs b/src/processor.rs index 5a656379f..dac303db9 100644 --- a/src/processor.rs +++ b/src/processor.rs @@ -41,7 +41,7 @@ pub async fn handle_request( req: &HttpRequest, route_params: HashMap, ) -> HttpResponse { - let contents = match execute_function( + let contents = match execute_http_function( function, payload, headers, @@ -79,8 +79,9 @@ fn read_file(file_path: &str) -> String { String::from_utf8_lossy(&buf).to_string() } +// Change this! #[inline] -async fn execute_function( +async fn execute_http_function( function: PyFunction, payload: &mut web::Payload, headers: &Headers, diff --git a/src/router.rs b/src/router.rs index da835a0c8..3b6c08d6c 100644 --- a/src/router.rs +++ b/src/router.rs @@ -6,6 +6,7 @@ use pyo3::prelude::*; use pyo3::types::PyAny; use actix_web::http::Method; +use dashmap::DashMap; use matchit::Node; /// Contains the thread safe hashmaps of different routes @@ -20,6 +21,7 @@ pub struct Router { options_routes: Arc>>, connect_routes: Arc>>, trace_routes: Arc>>, + web_socket_routes: DashMap>, } impl Router { @@ -34,6 +36,7 @@ impl Router { options_routes: Arc::new(RwLock::new(Node::new())), connect_routes: Arc::new(RwLock::new(Node::new())), trace_routes: Arc::new(RwLock::new(Node::new())), + web_socket_routes: DashMap::new(), } } @@ -53,21 +56,30 @@ impl Router { } } + #[inline] + pub fn get_web_socket_map(&self) -> &DashMap> { + &self.web_socket_routes + } + #[inline] fn get_relevant_map_str(&self, route: &str) -> Option<&Arc>>> { - let method = match Method::from_bytes(route.as_bytes()) { - Ok(res) => res, - Err(_) => return None, - }; + if route != "WS" { + let method = match Method::from_bytes(route.as_bytes()) { + Ok(res) => res, + Err(_) => return None, + }; - self.get_relevant_map(method) + return self.get_relevant_map(method); + } else { + return None; + } } // Checks if the functions is an async function // Inserts them in the router according to their nature(CoRoutine/SyncFunction) pub fn add_route( &self, - route_type: &str, + route_type: &str, // we can just have route type as WS route: &str, handler: Py, is_async: bool, @@ -91,12 +103,71 @@ impl Router { .unwrap(); } + // Checks if the functions is an async function + // Inserts them in the router according to their nature(CoRoutine/SyncFunction) + pub fn add_websocket_route( + &self, + route: &str, + connect_route: (Py, bool, u8), + close_route: (Py, bool, u8), + message_route: (Py, bool, u8), + ) { + let table = self.get_web_socket_map(); + let (connect_route_function, connect_route_is_async, connect_route_params) = connect_route; + let (close_route_function, close_route_is_async, close_route_params) = close_route; + let (message_route_function, message_route_is_async, message_route_params) = message_route; + + let insert_in_router = |table: &DashMap>, + handler: Py, + is_async: bool, + number_of_params: u8, + socket_type: &str| { + let function = if is_async { + PyFunction::CoRoutine(handler) + } else { + PyFunction::SyncFunction(handler) + }; + + let mut route_map = HashMap::new(); + route_map.insert(socket_type.to_string(), (function, number_of_params)); + + println!("{:?}", table); + table.insert(route.to_string(), route_map); + }; + + insert_in_router( + table, + connect_route_function, + connect_route_is_async, + connect_route_params, + "connect", + ); + + insert_in_router( + table, + close_route_function, + close_route_is_async, + close_route_params, + "close", + ); + + insert_in_router( + table, + message_route_function, + message_route_is_async, + message_route_params, + "message", + ); + } + pub fn get_route( &self, route_method: Method, - route: &str, + route: &str, // check for the route method here ) -> Option<((PyFunction, u8), HashMap)> { + // need to split this function in multiple smaller functions let table = self.get_relevant_map(route_method)?; + match table.read().unwrap().at(route) { Ok(res) => { let mut route_params = HashMap::new(); diff --git a/src/server.rs b/src/server.rs index 625d99b2d..2149ff51d 100644 --- a/src/server.rs +++ b/src/server.rs @@ -2,18 +2,21 @@ use crate::processor::{apply_headers, handle_request}; use crate::router::Router; use crate::shared_socket::SocketHeld; use crate::types::Headers; -use actix_files::Files; +use crate::web_socket_connection::start_web_socket; + use std::convert::TryInto; use std::sync::atomic::AtomicBool; use std::sync::atomic::Ordering::{Relaxed, SeqCst}; use std::sync::{Arc, RwLock}; use std::thread; -// pyO3 module + +use actix_files::Files; use actix_http::KeepAlive; use actix_web::*; use dashmap::DashMap; + +// pyO3 module use pyo3::prelude::*; -use pyo3::types::PyAny; static STARTED: AtomicBool = AtomicBool::new(false); @@ -84,14 +87,13 @@ impl Server { thread::spawn(move || { //init_current_thread_once(); actix_web::rt::System::new().block_on(async move { - let addr = format!("{}:{}", url, port); - println!("The number of workers are {}", workers.clone()); HttpServer::new(move || { let mut app = App::new(); let event_loop_hdl = event_loop_hdl.clone(); let directories = directories.read().unwrap(); + let router_copy = router.clone(); // this loop matches three types of directory serving // 1. Serves a build folder. e.g. the build folder generated from yarn build @@ -116,13 +118,32 @@ impl Server { } } - app.app_data(web::Data::new(router.clone())) - .app_data(web::Data::new(headers.clone())) - .default_service(web::route().to(move |router, headers, payload, req| { - pyo3_asyncio::tokio::scope_local(event_loop_hdl.clone(), async move { - index(router, headers, payload, req).await - }) - })) + app = app + .app_data(web::Data::new(router.clone())) + .app_data(web::Data::new(headers.clone())); + + let web_socket_map = router_copy.get_web_socket_map(); + for elem in (web_socket_map).iter() { + let route = elem.key().clone(); + let params = elem.value().clone(); + app = app.route( + &route, + web::get().to( + move |_router: web::Data>, + _headers: web::Data>, + stream: web::Payload, + req: HttpRequest| { + start_web_socket(req, stream, Arc::new(params.clone())) + }, + ), + ); + } + + app.default_service(web::route().to(move |router, headers, payload, req| { + pyo3_asyncio::tokio::scope_local(event_loop_hdl.clone(), async move { + index(router, headers, payload, req).await + }) + })) }) .keep_alive(KeepAlive::Os) .workers(*workers.clone()) @@ -180,6 +201,21 @@ impl Server { self.router .add_route(route_type, route, handler, is_async, number_of_params); } + + /// Add a new web socket route to the routing tables + /// can be called after the server has been started + pub fn add_web_socket_route( + &self, + route: &str, + // handler, is_async, number of params + connect_route: (Py, bool, u8), + close_route: (Py, bool, u8), + message_route: (Py, bool, u8), + ) { + println!("WS Route added for {} ", route); + self.router + .add_websocket_route(route, connect_route, close_route, message_route); + } } impl Default for Server { diff --git a/src/web_socket_connection.rs b/src/web_socket_connection.rs new file mode 100644 index 000000000..33d1e3381 --- /dev/null +++ b/src/web_socket_connection.rs @@ -0,0 +1,116 @@ +use crate::types::PyFunction; + +use actix::{Actor, StreamHandler}; +use actix_web::{web, Error, HttpRequest, HttpResponse}; +use actix_web_actors::ws; +use actix_web_actors::ws::WebsocketContext; +use pyo3::prelude::*; + +use std::collections::HashMap; +use std::sync::Arc; + +/// Define HTTP actor +struct MyWs { + router: Arc>, +} + +// By default mailbox capacity is 16 messages. +impl Actor for MyWs { + type Context = ws::WebsocketContext; + + fn started(&mut self, ctx: &mut WebsocketContext) { + println!("Actor is alive"); + } + + fn stopped(&mut self, _ctx: &mut WebsocketContext) { + println!("Actor is alive"); + } +} + +/// Handler for ws::Message message +impl StreamHandler> for MyWs { + fn handle(&mut self, msg: Result, ctx: &mut Self::Context) { + match msg { + Ok(ws::Message::Ping(msg)) => { + println!("Ping message {:?}", msg); + let handler_function = &self.router.get("connect").unwrap().0; + let _number_of_params = &self.router.get("connect").unwrap().1; + println!("{:?}", handler_function); + match handler_function { + PyFunction::SyncFunction(handler) => Python::with_gil(|py| { + let handler = handler.as_ref(py); + // call execute function + let op = handler.call0().unwrap(); + let op: &str = op.extract().unwrap(); + + println!("{}", op); + }), + PyFunction::CoRoutine(handler) => { + println!("Async functions are not supported in WS right now."); + } + } + ctx.pong(&msg) + } + + Ok(ws::Message::Pong(msg)) => { + println!("Pong message {:?}", msg); + ctx.pong(&msg) + } + + Ok(ws::Message::Text(text)) => { + // need to also passs this text as a param + let handler_function = &self.router.get("message").unwrap().0; + let _number_of_params = &self.router.get("message").unwrap().1; + println!("{:?}", handler_function); + match handler_function { + PyFunction::SyncFunction(handler) => Python::with_gil(|py| { + let handler = handler.as_ref(py); + // call execute function + let op = handler.call0().unwrap(); + let op: &str = op.extract().unwrap(); + + return ctx.text(op); + }), + PyFunction::CoRoutine(_handler) => { + println!("Async functions are not supported in WS right now."); + return ctx.text("Async Functions are not supported in WS right now."); + } + } + } + + Ok(ws::Message::Binary(bin)) => ctx.binary(bin), + Ok(ws::Message::Close(_close_reason)) => { + println!("Socket was closed"); + let router = &self.router; + let handler_function = &self.router.get("close").unwrap().0; + let number_of_params = &self.router.get("close").unwrap().1; + println!("{:?}", handler_function); + match handler_function { + PyFunction::SyncFunction(handler) => Python::with_gil(|py| { + let handler = handler.as_ref(py); + // call execute function + let op = handler.call0().unwrap(); + let op: &str = op.extract().unwrap(); + + println!("{:?}", op); + }), + PyFunction::CoRoutine(handler) => { + println!("Async functions are not supported in WS right now."); + } + } + } + _ => (), + } + } +} + +pub async fn start_web_socket( + req: HttpRequest, + stream: web::Payload, + router: Arc>, +) -> Result { + // execute the async function here + let resp = ws::start(MyWs { router }, &req, stream); + println!("{:?}", resp); + resp +} From 7c4c19c73cdc2cdd4ebd6e8eca9f313c77e005a5 Mon Sep 17 00:00:00 2001 From: Sanskar Jethi Date: Wed, 1 Dec 2021 23:54:51 +0000 Subject: [PATCH 3/3] Release v0.9.0 --- Cargo.toml | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 10c5e716c..663bb4c41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "robyn" -version = "0.8.1" +version = "0.9.0" authors = ["Sanskar Jethi "] edition = "2018" description = "A web server that is fast!" diff --git a/pyproject.toml b/pyproject.toml index 09ed29b9e..c71cc1ea7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "robyn" -version = "0.8.1" +version = "0.9.0" description = "A web server that is fast!" authors = ["Sanskar Jethi "]