feat(runtime/http): server side websocket support (#10359)

Co-authored-by: Nayeem Rahman <nayeemrmn99@gmail.com>
Co-authored-by: Luca Casonato <hello@lcas.dev>
This commit is contained in:
Leo K 2021-07-08 13:33:01 +02:00 committed by GitHub
parent 215f6f2c9e
commit 5e092b19fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 579 additions and 217 deletions

302
Cargo.lock generated
View file

@ -26,11 +26,11 @@ checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
[[package]]
name = "ahash"
version = "0.7.2"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f200cbb1e856866d9eade941cf3aa0c5d7dd36f74311c4273b494f4ef036957"
checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98"
dependencies = [
"getrandom 0.2.2",
"getrandom 0.2.3",
"once_cell",
"version_check",
]
@ -100,7 +100,7 @@ checksum = "f93f52ce8fac3d0e6720a92b0576d737c01b1b5db4dd786e962e5925f00bf755"
dependencies = [
"darling",
"pmutil",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"swc_macros_common",
"syn 1.0.65",
@ -122,9 +122,9 @@ dependencies = [
[[package]]
name = "async-stream"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a26cb53174ddd320edfff199a853f93d571f48eeb4dde75e67a9a3dbb7b7e5e"
checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625"
dependencies = [
"async-stream-impl",
"futures-core",
@ -132,11 +132,11 @@ dependencies = [
[[package]]
name = "async-stream-impl"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db134ba52475c060f3329a8ef0f8786d6b872ed01515d4b79c162e5798da1340"
checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308"
dependencies = [
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -147,7 +147,7 @@ version = "0.1.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722"
dependencies = [
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -170,7 +170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42cbf586c80ada5e5ccdecae80d3ef0854f224e2dd74435f8d87e6831b8d0a38"
dependencies = [
"proc-macro-error",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -270,9 +270,9 @@ checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7"
[[package]]
name = "bumpalo"
version = "3.6.1"
version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631"
[[package]]
name = "byteorder"
@ -288,9 +288,9 @@ checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
[[package]]
name = "cc"
version = "1.0.67"
version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
dependencies = [
"jobserver",
]
@ -341,6 +341,17 @@ dependencies = [
"vec_map",
]
[[package]]
name = "clipboard-win"
version = "4.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4ea1881992efc993e4dc50a324cdbd03216e41bdc8385720ff47efc9bd2ca8"
dependencies = [
"error-code",
"str-buf",
"winapi 0.3.9",
]
[[package]]
name = "cocoa-foundation"
version = "0.1.0"
@ -408,9 +419,9 @@ dependencies = [
[[package]]
name = "cpufeatures"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8"
checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef"
dependencies = [
"libc",
]
@ -445,11 +456,10 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.4"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278"
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [
"autocfg 1.0.1",
"cfg-if 1.0.0",
"lazy_static",
]
@ -483,7 +493,7 @@ checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
dependencies = [
"fnv",
"ident_case",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"strsim 0.9.3",
"syn 1.0.65",
@ -721,12 +731,15 @@ dependencies = [
name = "deno_net"
version = "0.1.0"
dependencies = [
"base64 0.13.0",
"bytes",
"deno_core",
"deno_websocket",
"http",
"hyper",
"lazy_static",
"log",
"ring",
"rustls",
"serde",
"tokio",
@ -842,6 +855,7 @@ version = "0.15.1"
dependencies = [
"deno_core",
"http",
"hyper",
"serde",
"tokio",
"tokio-rustls",
@ -867,7 +881,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cc7b9cef1e351660e5443924e4f43ab25fbbed3e9a5f052df3677deb4d6b320"
dependencies = [
"convert_case",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -1009,7 +1023,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595"
dependencies = [
"heck",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -1021,16 +1035,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b940da354ae81ef0926c5eaa428207b8f4f091d3956c891dfbd124162bed99"
dependencies = [
"pmutil",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"swc_macros_common",
"syn 1.0.65",
]
[[package]]
name = "env_logger"
version = "0.8.3"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f"
checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
dependencies = [
"atty",
"humantime",
@ -1071,6 +1085,16 @@ dependencies = [
"libc",
]
[[package]]
name = "error-code"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5115567ac25674e0043e472be13d14e537f37ea8aa4bdc4aef0c89add1db1ff"
dependencies = [
"libc",
"str-buf",
]
[[package]]
name = "exec"
version = "0.3.1"
@ -1113,6 +1137,16 @@ dependencies = [
"regex",
]
[[package]]
name = "fd-lock"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0010f02effd88c702318c5dde0463206be67495d0b4d906ba7c0a8f166cc7f06"
dependencies = [
"libc",
"winapi 0.3.9",
]
[[package]]
name = "filetime"
version = "0.2.14"
@ -1181,36 +1215,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0951635027ca477be98f8774abd6f0345233439d63f307e47101acb40c7cc63d"
dependencies = [
"pmutil",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"swc_macros_common",
"syn 1.0.65",
]
[[package]]
name = "fs2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
dependencies = [
"libc",
"winapi 0.3.9",
]
[[package]]
name = "fsevent"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97f347202c95c98805c216f9e1df210e8ebaec9fdb2365700a43c10797a35e63"
dependencies = [
"bitflags",
"fsevent-sys",
]
[[package]]
name = "fsevent-sys"
version = "3.1.0"
version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca6f5e6817058771c10f0eb0f05ddf1e35844266f972004fe8e4b21fda295bd5"
checksum = "5c0e564d24da983c053beff1bb7178e237501206840a3e6bf4e267b9e8ae734a"
dependencies = [
"libc",
]
@ -1281,7 +1295,7 @@ checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121"
dependencies = [
"autocfg 1.0.1",
"proc-macro-hack",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -1367,9 +1381,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.2"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
"cfg-if 1.0.0",
"libc",
@ -1552,9 +1566,9 @@ dependencies = [
[[package]]
name = "gpu-alloc"
version = "0.4.5"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc76088804bb65a6f3b880bea9306fdaeffb25ebb453105fafa691282ee9fdba"
checksum = "cbc1b6ca374e81862526786d9cb42357ce03706ed1b8761730caafd02ab91f3a"
dependencies = [
"bitflags",
"gpu-alloc-types",
@ -1623,7 +1637,7 @@ version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
dependencies = [
"ahash 0.7.2",
"ahash 0.7.4",
]
[[package]]
@ -1637,18 +1651,18 @@ dependencies = [
[[package]]
name = "heck"
version = "0.3.2"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.1.18"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
@ -1694,9 +1708,9 @@ checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68"
[[package]]
name = "httpdate"
version = "1.0.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9"
checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
[[package]]
name = "humantime"
@ -1706,9 +1720,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "hyper"
version = "0.14.9"
version = "0.14.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07d6baa1b441335f3ce5098ac421fb6547c46dda735ca1bc6d0153c838f9dd83"
checksum = "7728a72c4c7d72665fde02204bcbd93b247721025b222ef78606f14513e0fd03"
dependencies = [
"bytes",
"futures-channel",
@ -1768,12 +1782,12 @@ checksum = "1f7280c75fb2e2fc47080ec80ccc481376923acb04501957fc38f935c3de5088"
[[package]]
name = "indexmap"
version = "1.6.2"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
dependencies = [
"autocfg 1.0.1",
"hashbrown 0.9.1",
"hashbrown 0.11.2",
"serde",
]
@ -1835,9 +1849,9 @@ dependencies = [
[[package]]
name = "ipnet"
version = "2.3.0"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135"
checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
[[package]]
name = "is-macro"
@ -1847,7 +1861,7 @@ checksum = "a322dd16d960e322c3d92f541b4c1a4f0a2e81e1fdeee430d8cecc8b72e8015f"
dependencies = [
"Inflector",
"pmutil",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -1939,9 +1953,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.94"
version = "0.2.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
[[package]]
name = "libloading"
@ -2006,9 +2020,9 @@ dependencies = [
[[package]]
name = "lsp-types"
version = "0.89.0"
version = "0.89.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07731ecd4ee0654728359a5b95e2a254c857876c04b85225496a35d60345daa7"
checksum = "852e0dedfd52cc32325598b2631e0eba31b7b708959676a9f837042f276b09a2"
dependencies = [
"bitflags",
"serde",
@ -2049,7 +2063,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca1d48da0e4a6100b4afd52fae99f36d47964a209624021280ad9ffdd410e83d"
dependencies = [
"heck",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -2113,9 +2127,9 @@ dependencies = [
[[package]]
name = "mio"
version = "0.7.11"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956"
checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16"
dependencies = [
"libc",
"log",
@ -2180,14 +2194,13 @@ dependencies = [
[[package]]
name = "notify"
version = "5.0.0-pre.8"
version = "5.0.0-pre.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46bbbcd078f1f00ddb7a9abe70b96e91229b44b0b3afdec610f8e5137f8f014b"
checksum = "51f18203a26893ca1d3526cf58084025d5639f91c44f8b70ab3b724f60e819a0"
dependencies = [
"bitflags",
"crossbeam-channel",
"filetime",
"fsevent",
"fsevent-sys",
"inotify",
"libc",
@ -2308,9 +2321,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.7.2"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]]
name = "opaque-debug"
@ -2428,7 +2441,7 @@ dependencies = [
"phf_generator",
"phf_shared",
"proc-macro-hack",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -2457,16 +2470,16 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f"
dependencies = [
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
[[package]]
name = "pin-project-lite"
version = "0.2.6"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905"
checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
[[package]]
name = "pin-utils"
@ -2486,7 +2499,7 @@ version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3894e5d549cccbe44afecf72922f277f603cd4bb0219c8342631ef18fffbe004"
dependencies = [
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -2510,7 +2523,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
"version_check",
@ -2522,7 +2535,7 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"version_check",
]
@ -2550,18 +2563,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.26"
version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
dependencies = [
"unicode-xid 0.2.2",
]
[[package]]
name = "profiling"
version = "1.0.1"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3a66d5e88679f2720126c11ee29da07a08f094eac52306b066edd7d393752d6"
checksum = "87dfd5592a8eed7e74f56ad7b125f8234763b805c30f0c7c95c486920026a6ec"
[[package]]
name = "pty"
@ -2605,7 +2618,7 @@ version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
]
[[package]]
@ -2645,9 +2658,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"rand_chacha 0.3.0",
"rand_core 0.6.2",
"rand_hc 0.3.0",
"rand_chacha 0.3.1",
"rand_core 0.6.3",
"rand_hc 0.3.1",
]
[[package]]
@ -2662,12 +2675,12 @@ dependencies = [
[[package]]
name = "rand_chacha"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.2",
"rand_core 0.6.3",
]
[[package]]
@ -2681,11 +2694,11 @@ dependencies = [
[[package]]
name = "rand_core"
version = "0.6.2"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom 0.2.2",
"getrandom 0.2.3",
]
[[package]]
@ -2699,11 +2712,11 @@ dependencies = [
[[package]]
name = "rand_hc"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
"rand_core 0.6.2",
"rand_core 0.6.3",
]
[[package]]
@ -2732,9 +2745,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.2.8"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc"
checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee"
dependencies = [
"bitflags",
]
@ -2780,9 +2793,9 @@ checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157"
[[package]]
name = "reqwest"
version = "0.11.3"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2296f2fac53979e8ccbc4a1136b25dcefd37be9ed7e4a1f6b05a6029c84ff124"
checksum = "246e9f61b9bb77df069a947682be06e31ac43ea37862e244a69f177694ea6d22"
dependencies = [
"async-compression",
"base64 0.13.0",
@ -2938,13 +2951,14 @@ dependencies = [
[[package]]
name = "rustyline"
version = "8.0.0"
version = "8.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e1b597fcd1eeb1d6b25b493538e5aa19629eb08932184b85fef931ba87e893"
checksum = "fbd4eaf7a7738f76c98e4f0395253ae853be3eb018f7b0bb57fe1b6c17e31874"
dependencies = [
"bitflags",
"cfg-if 1.0.0",
"fs2",
"clipboard-win",
"fd-lock",
"libc",
"log",
"memchr",
@ -3044,7 +3058,7 @@ version = "1.0.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
dependencies = [
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -3067,7 +3081,7 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5"
dependencies = [
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -3128,9 +3142,9 @@ checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
[[package]]
name = "signal-hook-registry"
version = "1.3.0"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
dependencies = [
"libc",
]
@ -3256,6 +3270,12 @@ dependencies = [
"lock_api",
]
[[package]]
name = "str-buf"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a"
[[package]]
name = "string_cache"
version = "0.8.1"
@ -3277,7 +3297,7 @@ checksum = "f24c8e5e19d22a726626f1a5e16fe15b132dcf21d10177fa5a45ce7962996b97"
dependencies = [
"phf_generator",
"phf_shared",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
]
@ -3288,7 +3308,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f584cc881e9e5f1fd6bf827b0444aa94c30d8fe6378cf241071b5f5700b2871f"
dependencies = [
"pmutil",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"swc_macros_common",
"syn 1.0.65",
@ -3328,7 +3348,7 @@ version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a893fda61ad72583351e97313439b9cdd200ffb6b2ae75f363e03a39df935086"
dependencies = [
"ahash 0.7.2",
"ahash 0.7.4",
"anyhow",
"crc",
"fxhash",
@ -3412,7 +3432,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51af418026cb4ea588e2b15fa206c44e09a3184b718e12a0919729c7c3ad20d3"
dependencies = [
"pmutil",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"swc_macros_common",
"syn 1.0.65",
@ -3649,7 +3669,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c8f200a2eaed938e7c1a685faaa66e6d42fa9e17da5f62572d3cbc335898f5e"
dependencies = [
"pmutil",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -3661,7 +3681,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08ed2e930f5a1a4071fe62c90fd3a296f6030e5d94bfe13993244423caf59a78"
dependencies = [
"pmutil",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -3684,7 +3704,7 @@ checksum = "e3b2825fee79f10d0166e8e650e79c7a862fb991db275743083f07555d7641f0"
dependencies = [
"Inflector",
"pmutil",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"swc_macros_common",
"syn 1.0.65",
@ -3707,7 +3727,7 @@ version = "1.0.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663"
dependencies = [
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"unicode-xid 0.2.2",
]
@ -3718,7 +3738,7 @@ version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
dependencies = [
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
"unicode-xid 0.2.2",
@ -3795,20 +3815,20 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.24"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.24"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d"
dependencies = [
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -3880,7 +3900,7 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c49e3df43841dafb86046472506755d8501c5615673955f6aa17181125d13c37"
dependencies = [
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
]
@ -4127,9 +4147,9 @@ dependencies = [
[[package]]
name = "twoway"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b40075910de3a912adbd80b5d8bad6ad10a23eeb1f5bf9d4006839e899ba5bc"
checksum = "c57ffb460d7c24cd6eda43694110189030a3d1dfe418416d9468fd1c1d290b47"
dependencies = [
"memchr",
"unchecked-index",
@ -4173,9 +4193,9 @@ dependencies = [
[[package]]
name = "unicode-normalization"
version = "0.1.17"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef"
checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"
dependencies = [
"tinyvec",
]
@ -4241,15 +4261,15 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"getrandom 0.2.2",
"getrandom 0.2.3",
"serde",
]
[[package]]
name = "vcpkg"
version = "0.2.12"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbdbff6266a24120518560b5dc983096efb98462e51d0d68169895b237be3e5d"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "vec_map"
@ -4317,7 +4337,7 @@ dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
"wasm-bindgen-shared",
@ -4351,7 +4371,7 @@ version = "0.2.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96eb45c1b2ee33545a813a92dbb53856418bf7eb54ab34f7f7ff1448a5b3735d"
dependencies = [
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
"wasm-bindgen-backend",
@ -4544,7 +4564,7 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16"
dependencies = [
"proc-macro2 1.0.26",
"proc-macro2 1.0.27",
"quote 1.0.9",
"syn 1.0.65",
"synstructure",

View file

@ -9,6 +9,7 @@ import {
assertThrowsAsync,
deferred,
delay,
fail,
unitTest,
} from "./test_util.ts";
@ -631,3 +632,33 @@ unitTest(
await promise;
},
);
unitTest({ perms: { net: true } }, async function httpServerWebSocket() {
const promise = (async () => {
const listener = Deno.listen({ port: 4501 });
for await (const conn of listener) {
const httpConn = Deno.serveHttp(conn);
const { request, respondWith } = (await httpConn.nextRequest())!;
const {
response,
websocket,
} = await Deno.upgradeWebSocket(request);
websocket.onerror = () => fail();
websocket.onmessage = (m) => {
websocket.send(m.data);
websocket.close();
};
await respondWith(response);
break;
}
})();
const def = deferred();
const ws = new WebSocket("ws://localhost:4501");
ws.onmessage = (m) => assertEquals(m.data, "foo");
ws.onerror = () => fail();
ws.onclose = () => def.resolve();
ws.onopen = () => ws.send("foo");
await def;
await promise;
});

View file

@ -437,6 +437,7 @@
window.__bootstrap.fetch ??= {};
window.__bootstrap.fetch.Response = Response;
window.__bootstrap.fetch.newInnerResponse = newInnerResponse;
window.__bootstrap.fetch.toInnerResponse = toInnerResponse;
window.__bootstrap.fetch.fromInnerResponse = fromInnerResponse;
window.__bootstrap.fetch.redirectStatus = redirectStatus;

View file

@ -2,21 +2,34 @@
"use strict";
((window) => {
const webidl = window.__bootstrap.webidl;
const { InnerBody } = window.__bootstrap.fetchBody;
const { Response, fromInnerRequest, toInnerResponse, newInnerRequest } =
window.__bootstrap.fetch;
const { setEventTargetData } = window.__bootstrap.eventTarget;
const {
Response,
fromInnerRequest,
toInnerResponse,
newInnerRequest,
newInnerResponse,
fromInnerResponse,
} = window.__bootstrap.fetch;
const core = window.Deno.core;
const { BadResource, Interrupted } = core;
const { ReadableStream } = window.__bootstrap.streams;
const abortSignal = window.__bootstrap.abortSignal;
const { WebSocket, _rid, _readyState, _eventLoop, _protocol } =
window.__bootstrap.webSocket;
const {
Symbol,
Uint8Array,
ArrayPrototypeIncludes,
ArrayPrototypePush,
Promise,
StringPrototypeIncludes,
StringPrototypeSplit,
Symbol,
SymbolAsyncIterator,
TypeError,
TypedArrayPrototypeSubarray,
TypeError,
Uint8Array,
} = window.__bootstrap.primordials;
function serveHttp(conn) {
@ -65,7 +78,7 @@
if (nextRequest === null) return null;
const [
requestBodyRid,
requestRid,
responseSenderRid,
method,
headersList,
@ -74,8 +87,8 @@
/** @type {ReadableStream<Uint8Array> | undefined} */
let body = null;
if (typeof requestBodyRid === "number") {
body = createRequestBodyStream(requestBodyRid);
if (typeof requestRid === "number") {
body = createRequestBodyStream(requestRid);
}
const innerRequest = newInnerRequest(
@ -87,7 +100,11 @@
const signal = abortSignal.newSignal();
const request = fromInnerRequest(innerRequest, signal, "immutable");
const respondWith = createRespondWith(this, responseSenderRid);
const respondWith = createRespondWith(
this,
responseSenderRid,
requestRid,
);
return { request, respondWith };
}
@ -118,7 +135,7 @@
);
}
function createRespondWith(httpConn, responseSenderRid) {
function createRespondWith(httpConn, responseSenderRid, requestRid) {
return async function respondWith(resp) {
if (resp instanceof Promise) {
resp = await resp;
@ -222,10 +239,51 @@
} catch { /* pass */ }
}
}
const ws = resp[_ws];
if (ws) {
if (typeof requestRid !== "number") {
throw new TypeError(
"This request can not be upgraded to a websocket connection.",
);
}
const wsRid = await core.opAsync(
"op_http_upgrade_websocket",
requestRid,
);
ws[_rid] = wsRid;
ws[_protocol] = resp.headers.get("sec-websocket-protocol");
if (ws[_readyState] === WebSocket.CLOSING) {
await core.opAsync("op_ws_close", { rid: wsRid });
ws[_readyState] = WebSocket.CLOSED;
const errEvent = new ErrorEvent("error");
ws.dispatchEvent(errEvent);
const event = new CloseEvent("close");
ws.dispatchEvent(event);
try {
core.close(wsRid);
} catch (err) {
// Ignore error if the socket has already been closed.
if (!(err instanceof Deno.errors.BadResource)) throw err;
}
} else {
ws[_readyState] = WebSocket.OPEN;
const event = new Event("open");
ws.dispatchEvent(event);
ws[_eventLoop]();
}
}
};
}
function createRequestBodyStream(requestBodyRid) {
function createRequestBodyStream(requestRid) {
return new ReadableStream({
type: "bytes",
async pull(controller) {
@ -234,7 +292,7 @@
// stream.
const chunk = new Uint8Array(16 * 1024 + 256);
const read = await readRequest(
requestBodyRid,
requestRid,
chunk,
);
if (read > 0) {
@ -243,23 +301,79 @@
} else {
// We have reached the end of the body, so we close the stream.
controller.close();
core.close(requestBodyRid);
core.close(requestRid);
}
} catch (err) {
// There was an error while reading a chunk of the body, so we
// error.
controller.error(err);
controller.close();
core.close(requestBodyRid);
core.close(requestRid);
}
},
cancel() {
core.close(requestBodyRid);
core.close(requestRid);
},
});
}
const _ws = Symbol("[[associated_ws]]");
function upgradeWebSocket(request, options = {}) {
if (request.headers.get("upgrade") !== "websocket") {
throw new TypeError(
"Invalid Header: 'upgrade' header must be 'websocket'",
);
}
if (request.headers.get("connection") !== "Upgrade") {
throw new TypeError(
"Invalid Header: 'connection' header must be 'Upgrade'",
);
}
const websocketKey = request.headers.get("sec-websocket-key");
if (websocketKey === null) {
throw new TypeError(
"Invalid Header: 'sec-websocket-key' header must be set",
);
}
const accept = core.opSync("op_http_websocket_accept_header", websocketKey);
const r = newInnerResponse(101);
r.headerList = [
["upgrade", "websocket"],
["connection", "Upgrade"],
["sec-websocket-accept", accept],
];
const protocolsStr = request.headers.get("sec-websocket-protocol") || "";
const protocols = StringPrototypeSplit(protocolsStr, ", ");
if (protocols && options.protocol) {
if (ArrayPrototypeIncludes(protocols, options.protocol)) {
ArrayPrototypePush(r.headerList, [
"sec-websocket-protocol",
options.protocol,
]);
} else {
throw new TypeError(
`Protocol '${options.protocol}' not in the request's protocol list (non negotiable)`,
);
}
}
const response = fromInnerResponse(r, "immutable");
const websocket = webidl.createBranded(WebSocket);
setEventTargetData(websocket);
response[_ws] = websocket;
return { response, websocket };
}
window.__bootstrap.http = {
serveHttp,
upgradeWebSocket,
};
})(this);

View file

@ -15,12 +15,15 @@ path = "lib.rs"
[dependencies]
deno_core = { version = "0.92.0", path = "../../core" }
deno_websocket = { version = "0.15.0", path = "../websocket" }
base64 = "0.13.0"
bytes = "1"
log = "0.4.14"
lazy_static = "1.4.0"
http = "0.2.3"
hyper = { version = "0.14.9", features = ["server", "stream", "http1", "http2", "runtime"] }
ring = "0.16.20"
rustls = "0.19.0"
serde = { version = "1.0.125", features = ["derive"] }
tokio = { version = "1.8.0", features = ["full"] }

View file

@ -259,4 +259,18 @@ declare namespace Deno {
* then the underlying HttpConn resource is closed automatically.
*/
export function serveHttp(conn: Conn): HttpConn;
export interface WebSocketUpgrade {
response: Response;
websocket: WebSocket;
}
export interface UpgradeWebSocketOptions {
protocol?: string;
}
export function upgradeWebSocket(
request: Request,
options?: UpgradeWebSocketOptions,
): WebSocketUpgrade;
}

View file

@ -2,7 +2,6 @@
use crate::io::TcpStreamResource;
use crate::io::TlsStreamResource;
use crate::ops_tls::TlsStream;
use deno_core::error::bad_resource_id;
use deno_core::error::null_opbuf;
use deno_core::error::type_error;
@ -25,7 +24,6 @@ use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
use hyper::body::HttpBody;
use hyper::http;
use hyper::server::conn::Connection;
use hyper::server::conn::Http;
use hyper::service::Service as HyperService;
use hyper::Body;
@ -42,7 +40,6 @@ use std::rc::Rc;
use std::task::Context;
use std::task::Poll;
use tokio::io::AsyncReadExt;
use tokio::net::TcpStream;
use tokio::sync::oneshot;
use tokio_util::io::StreamReader;
@ -54,6 +51,14 @@ pub fn init() -> Vec<OpPair> {
("op_http_response", op_async(op_http_response)),
("op_http_response_write", op_async(op_http_response_write)),
("op_http_response_close", op_async(op_http_response_close)),
(
"op_http_websocket_accept_header",
op_sync(op_http_websocket_accept_header),
),
(
"op_http_upgrade_websocket",
op_async(op_http_upgrade_websocket),
),
]
}
@ -97,13 +102,15 @@ impl HyperService<Request<Body>> for Service {
}
}
enum ConnType {
Tcp(Rc<RefCell<Connection<TcpStream, Service, LocalExecutor>>>),
Tls(Rc<RefCell<Connection<TlsStream, Service, LocalExecutor>>>),
type ConnFuture = Pin<Box<dyn Future<Output = hyper::Result<()>>>>;
struct Conn {
scheme: &'static str,
conn: Rc<RefCell<ConnFuture>>,
}
struct ConnResource {
hyper_connection: ConnType,
hyper_connection: Conn,
deno_service: Service,
addr: SocketAddr,
cancel: CancelHandle,
@ -112,11 +119,12 @@ struct ConnResource {
impl ConnResource {
// TODO(ry) impl Future for ConnResource?
fn poll(&self, cx: &mut Context<'_>) -> Poll<Result<(), AnyError>> {
match &self.hyper_connection {
ConnType::Tcp(c) => c.borrow_mut().poll_unpin(cx),
ConnType::Tls(c) => c.borrow_mut().poll_unpin(cx),
}
.map_err(AnyError::from)
self
.hyper_connection
.conn
.borrow_mut()
.poll_unpin(cx)
.map_err(AnyError::from)
}
}
@ -134,7 +142,7 @@ impl Resource for ConnResource {
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct NextRequestResponse(
// request_body_rid:
// request_rid:
Option<ResourceId>,
// response_sender_rid:
ResourceId,
@ -207,12 +215,7 @@ async fn op_http_request_next(
}
let url = {
let scheme = {
match conn_resource.hyper_connection {
ConnType::Tcp(_) => "http",
ConnType::Tls(_) => "https",
}
};
let scheme = &conn_resource.hyper_connection.scheme;
let host: Cow<str> = if let Some(host) = req.uri().host() {
Cow::Borrowed(host)
} else if let Some(host) = req.headers().get("HOST") {
@ -224,24 +227,35 @@ async fn op_http_request_next(
format!("{}://{}{}", scheme, host, path)
};
let is_websocket_request = req
.headers()
.get(hyper::header::CONNECTION)
.and_then(|v| {
v.to_str().ok().map(|s| "Upgrade".eq_ignore_ascii_case(s))
})
.unwrap_or(false)
&& req
.headers()
.get(hyper::header::UPGRADE)
.and_then(|v| {
v.to_str().ok().map(|s| "websocket".eq_ignore_ascii_case(s))
})
.unwrap_or(false);
let has_body = if let Some(exact_size) = req.size_hint().exact() {
exact_size > 0
} else {
true
};
let maybe_request_body_rid = if has_body {
let stream: BytesStream = Box::pin(req.into_body().map(|r| {
r.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))
}));
let stream_reader = StreamReader::new(stream);
let maybe_request_rid = if is_websocket_request || has_body {
let mut state = state.borrow_mut();
let request_body_rid = state.resource_table.add(RequestBodyResource {
let request_rid = state.resource_table.add(RequestResource {
conn_rid,
reader: AsyncRefCell::new(stream_reader),
inner: AsyncRefCell::new(RequestOrStreamReader::Request(Some(req))),
cancel: CancelHandle::default(),
});
Some(request_body_rid)
Some(request_rid)
} else {
None
};
@ -254,7 +268,7 @@ async fn op_http_request_next(
});
Poll::Ready(Ok(Some(NextRequestResponse(
maybe_request_body_rid,
maybe_request_rid,
response_sender_rid,
method,
headers,
@ -303,9 +317,14 @@ fn op_http_start(
let addr = tcp_stream.local_addr()?;
let hyper_connection = Http::new()
.with_executor(LocalExecutor)
.serve_connection(tcp_stream, deno_service.clone());
.serve_connection(tcp_stream, deno_service.clone())
.with_upgrades();
let conn = Pin::new(Box::new(hyper_connection));
let conn_resource = ConnResource {
hyper_connection: ConnType::Tcp(Rc::new(RefCell::new(hyper_connection))),
hyper_connection: Conn {
conn: Rc::new(RefCell::new(conn)),
scheme: "http",
},
deno_service,
addr,
cancel: CancelHandle::default(),
@ -326,9 +345,14 @@ fn op_http_start(
let hyper_connection = Http::new()
.with_executor(LocalExecutor)
.serve_connection(tls_stream, deno_service.clone());
.serve_connection(tls_stream, deno_service.clone())
.with_upgrades();
let conn = Pin::new(Box::new(hyper_connection));
let conn_resource = ConnResource {
hyper_connection: ConnType::Tls(Rc::new(RefCell::new(hyper_connection))),
hyper_connection: Conn {
conn: Rc::new(RefCell::new(conn)),
scheme: "https",
},
deno_service,
addr,
cancel: CancelHandle::default(),
@ -367,10 +391,12 @@ async fn op_http_response(
.ok()
.expect("multiple op_http_respond ongoing");
let conn_rid = response_sender.conn_rid;
let conn_resource = state
.borrow()
.resource_table
.get::<ConnResource>(response_sender.conn_rid)
.get::<ConnResource>(conn_rid)
.ok_or_else(bad_resource_id)?;
let mut builder = Response::builder().status(status);
@ -393,7 +419,7 @@ async fn op_http_response(
let response_body_rid =
state.borrow_mut().resource_table.add(ResponseBodyResource {
body: AsyncRefCell::new(sender),
conn_rid: response_sender.conn_rid,
conn_rid,
});
Some(response_body_rid)
@ -407,7 +433,10 @@ async fn op_http_response(
}
poll_fn(|cx| match conn_resource.poll(cx) {
Poll::Ready(x) => Poll::Ready(x),
Poll::Ready(x) => {
state.borrow_mut().resource_table.close(conn_rid);
Poll::Ready(x)
}
Poll::Pending => Poll::Ready(Ok(())),
})
.await?;
@ -455,7 +484,7 @@ async fn op_http_request_read(
let resource = state
.borrow()
.resource_table
.get::<RequestBodyResource>(rid as u32)
.get::<RequestResource>(rid as u32)
.ok_or_else(bad_resource_id)?;
let conn_resource = state
@ -464,8 +493,26 @@ async fn op_http_request_read(
.get::<ConnResource>(resource.conn_rid)
.ok_or_else(bad_resource_id)?;
let mut reader = RcRef::map(&resource, |r| &r.reader).borrow_mut().await;
let mut inner = RcRef::map(resource.clone(), |r| &r.inner)
.borrow_mut()
.await;
if let RequestOrStreamReader::Request(req) = &mut *inner {
let req = req.take().unwrap();
let stream: BytesStream = Box::pin(req.into_body().map(|r| {
r.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))
}));
let reader = StreamReader::new(stream);
*inner = RequestOrStreamReader::StreamReader(reader);
};
let reader = match &mut *inner {
RequestOrStreamReader::StreamReader(reader) => reader,
_ => unreachable!(),
};
let cancel = RcRef::map(resource, |r| &r.cancel);
let mut read_fut = reader.read(&mut data).try_or_cancel(cancel).boxed_local();
poll_fn(|cx| {
@ -521,18 +568,77 @@ async fn op_http_response_write(
Ok(())
}
fn op_http_websocket_accept_header(
_: &mut OpState,
key: String,
_: (),
) -> Result<String, AnyError> {
let digest = ring::digest::digest(
&ring::digest::SHA1_FOR_LEGACY_USE_ONLY,
format!("{}258EAFA5-E914-47DA-95CA-C5AB0DC85B11", key).as_bytes(),
);
Ok(base64::encode(digest))
}
async fn op_http_upgrade_websocket(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
_: (),
) -> Result<ResourceId, AnyError> {
let req_resource = state
.borrow_mut()
.resource_table
.take::<RequestResource>(rid)
.ok_or_else(bad_resource_id)?;
let mut inner = RcRef::map(&req_resource, |r| &r.inner).borrow_mut().await;
if let RequestOrStreamReader::Request(req) = inner.as_mut() {
let upgraded = hyper::upgrade::on(req.as_mut().unwrap()).await?;
let stream =
deno_websocket::tokio_tungstenite::WebSocketStream::from_raw_socket(
upgraded,
deno_websocket::tokio_tungstenite::tungstenite::protocol::Role::Server,
None,
)
.await;
let (ws_tx, ws_rx) = stream.split();
let rid =
state
.borrow_mut()
.resource_table
.add(deno_websocket::WsStreamResource {
stream: deno_websocket::WebSocketStreamType::Server {
rx: AsyncRefCell::new(ws_rx),
tx: AsyncRefCell::new(ws_tx),
},
cancel: Default::default(),
});
Ok(rid)
} else {
Err(bad_resource_id())
}
}
type BytesStream =
Pin<Box<dyn Stream<Item = std::io::Result<bytes::Bytes>> + Unpin>>;
struct RequestBodyResource {
enum RequestOrStreamReader {
Request(Option<Request<hyper::Body>>),
StreamReader(StreamReader<BytesStream, bytes::Bytes>),
}
struct RequestResource {
conn_rid: ResourceId,
reader: AsyncRefCell<StreamReader<BytesStream, bytes::Bytes>>,
inner: AsyncRefCell<RequestOrStreamReader>,
cancel: CancelHandle,
}
impl Resource for RequestBodyResource {
impl Resource for RequestResource {
fn name(&self) -> Cow<str> {
"requestBody".into()
"request".into()
}
fn close(self: Rc<Self>) {

View file

@ -124,6 +124,7 @@
const _protocol = Symbol("[[protocol]]");
const _binaryType = Symbol("[[binaryType]]");
const _bufferedAmount = Symbol("[[bufferedAmount]]");
const _eventLoop = Symbol("[[eventLoop]]");
class WebSocket extends EventTarget {
[_rid];
@ -294,7 +295,7 @@
const event = new Event("open");
this.dispatchEvent(event);
this.#eventLoop();
this[_eventLoop]();
}
},
(err) => {
@ -427,7 +428,7 @@
}
}
async #eventLoop() {
async [_eventLoop]() {
while (this[_readyState] === OPEN) {
const { kind, value } = await core.opAsync(
"op_ws_next_event",
@ -518,5 +519,11 @@
webidl.configurePrototype(WebSocket);
window.__bootstrap.webSocket = { WebSocket };
window.__bootstrap.webSocket = {
WebSocket,
_rid,
_readyState,
_eventLoop,
_protocol,
};
})(this);

View file

@ -20,5 +20,6 @@ serde = { version = "1.0.125", features = ["derive"] }
tokio = { version = "1.8.0", features = ["full"] }
tokio-rustls = "0.22.0"
tokio-tungstenite = { version = "0.14.0", features = ["rustls-tls"] }
hyper = { version = "0.14.9" }
webpki = "0.21.4"
webpki-roots = "0.21.1"

View file

@ -64,13 +64,81 @@ impl WebSocketPermissions for NoWebSocketPermissions {
}
type WsStream = WebSocketStream<MaybeTlsStream<TcpStream>>;
struct WsStreamResource {
tx: AsyncRefCell<SplitSink<WsStream, Message>>,
rx: AsyncRefCell<SplitStream<WsStream>>,
pub enum WebSocketStreamType {
Client {
tx: AsyncRefCell<SplitSink<WsStream, Message>>,
rx: AsyncRefCell<SplitStream<WsStream>>,
},
Server {
tx: AsyncRefCell<
SplitSink<WebSocketStream<hyper::upgrade::Upgraded>, Message>,
>,
rx: AsyncRefCell<SplitStream<WebSocketStream<hyper::upgrade::Upgraded>>>,
},
}
pub struct WsStreamResource {
pub stream: WebSocketStreamType,
// When a `WsStreamResource` resource is closed, all pending 'read' ops are
// canceled, while 'write' ops are allowed to complete. Therefore only
// 'read' futures are attached to this cancel handle.
cancel: CancelHandle,
pub cancel: CancelHandle,
}
impl WsStreamResource {
async fn send(self: &Rc<Self>, message: Message) -> Result<(), AnyError> {
match self.stream {
WebSocketStreamType::Client { .. } => {
let mut tx = RcRef::map(self, |r| match &r.stream {
WebSocketStreamType::Client { tx, .. } => tx,
WebSocketStreamType::Server { .. } => unreachable!(),
})
.borrow_mut()
.await;
tx.send(message).await?;
}
WebSocketStreamType::Server { .. } => {
let mut tx = RcRef::map(self, |r| match &r.stream {
WebSocketStreamType::Client { .. } => unreachable!(),
WebSocketStreamType::Server { tx, .. } => tx,
})
.borrow_mut()
.await;
tx.send(message).await?;
}
}
Ok(())
}
async fn next_message(
self: &Rc<Self>,
cancel: RcRef<CancelHandle>,
) -> Result<
Option<Result<Message, tokio_tungstenite::tungstenite::Error>>,
AnyError,
> {
match &self.stream {
WebSocketStreamType::Client { .. } => {
let mut rx = RcRef::map(self, |r| match &r.stream {
WebSocketStreamType::Client { rx, .. } => rx,
WebSocketStreamType::Server { .. } => unreachable!(),
})
.borrow_mut()
.await;
rx.next().or_cancel(cancel).await.map_err(AnyError::from)
}
WebSocketStreamType::Server { .. } => {
let mut rx = RcRef::map(self, |r| match &r.stream {
WebSocketStreamType::Client { .. } => unreachable!(),
WebSocketStreamType::Server { rx, .. } => rx,
})
.borrow_mut()
.await;
rx.next().or_cancel(cancel).await.map_err(AnyError::from)
}
}
}
}
impl Resource for WsStreamResource {
@ -79,8 +147,6 @@ impl Resource for WsStreamResource {
}
}
impl WsStreamResource {}
// This op is needed because creating a WS instance in JavaScript is a sync
// operation and should throw error when permissions are not fulfilled,
// but actual op that connects WS is async.
@ -184,8 +250,10 @@ where
let (ws_tx, ws_rx) = stream.split();
let resource = WsStreamResource {
rx: AsyncRefCell::new(ws_rx),
tx: AsyncRefCell::new(ws_tx),
stream: WebSocketStreamType::Client {
rx: AsyncRefCell::new(ws_rx),
tx: AsyncRefCell::new(ws_tx),
},
cancel: Default::default(),
};
let mut state = state.borrow_mut();
@ -227,15 +295,13 @@ pub async fn op_ws_send(
"pong" => Message::Pong(vec![]),
_ => unreachable!(),
};
let rid = args.rid;
let resource = state
.borrow_mut()
.resource_table
.get::<WsStreamResource>(rid)
.get::<WsStreamResource>(args.rid)
.ok_or_else(bad_resource_id)?;
let mut tx = RcRef::map(&resource, |r| &r.tx).borrow_mut().await;
tx.send(msg).await?;
resource.send(msg).await?;
Ok(())
}
@ -266,8 +332,7 @@ pub async fn op_ws_close(
.resource_table
.get::<WsStreamResource>(rid)
.ok_or_else(bad_resource_id)?;
let mut tx = RcRef::map(&resource, |r| &r.tx).borrow_mut().await;
tx.send(msg).await?;
resource.send(msg).await?;
Ok(())
}
@ -294,9 +359,8 @@ pub async fn op_ws_next_event(
.get::<WsStreamResource>(rid)
.ok_or_else(bad_resource_id)?;
let mut rx = RcRef::map(&resource, |r| &r.rx).borrow_mut().await;
let cancel = RcRef::map(resource, |r| &r.cancel);
let val = rx.next().or_cancel(cancel).await?;
let cancel = RcRef::map(&resource, |r| &r.cancel);
let val = resource.next_message(cancel).await?;
let res = match val {
Some(Ok(Message::Text(text))) => NextEventResponse::String(text),
Some(Ok(Message::Binary(data))) => NextEventResponse::Binary(data.into()),

View file

@ -128,6 +128,7 @@
serveHttp: __bootstrap.http.serveHttp,
startTls: __bootstrap.tls.startTls,
umask: __bootstrap.fs.umask,
upgradeWebSocket: __bootstrap.http.upgradeWebSocket,
futime: __bootstrap.fs.futime,
futimeSync: __bootstrap.fs.futimeSync,
utime: __bootstrap.fs.utime,