[[package]]
name = "base64"
-version = "0.21.3"
+version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53"
+checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+
+[[package]]
+name = "base64"
+version = "0.21.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2"
[[package]]
name = "bit-set"
[[package]]
name = "bumpalo"
-version = "3.13.0"
+version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
+checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
[[package]]
name = "byte-tools"
[[package]]
name = "bytes"
-version = "1.4.0"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
+checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cc"
[[package]]
name = "chrono"
-version = "0.4.26"
+version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
+checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
- "time",
"wasm-bindgen",
- "winapi",
+ "windows-targets",
]
[[package]]
[[package]]
name = "ctrlc"
-version = "3.4.0"
+version = "3.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a011bbe2c35ce9c1f143b7af6f94f29a167beb4cd1d29e6740ce836f723120e"
+checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf"
dependencies = [
- "nix",
+ "nix 0.27.1",
"windows-sys",
]
[[package]]
name = "dashmap"
-version = "5.5.1"
+version = "5.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edd72493923899c6f10c641bdbdeddc7183d6396641d99c1a0d1597f37f92e28"
+checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
dependencies = [
"cfg-if",
"hashbrown 0.14.0",
[[package]]
name = "errno"
-version = "0.3.2"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
+checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd"
dependencies = [
"errno-dragonfly",
"libc",
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.32",
+ "syn 2.0.37",
]
[[package]]
"cfg-if",
"js-sys",
"libc",
- "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasi",
"wasm-bindgen",
]
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
+[[package]]
+name = "headers"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270"
+dependencies = [
+ "base64 0.21.4",
+ "bytes",
+ "headers-core",
+ "http",
+ "httpdate",
+ "mime",
+ "sha1",
+]
+
+[[package]]
+name = "headers-core"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
+dependencies = [
+ "http",
+]
+
[[package]]
name = "heck"
version = "0.3.3"
[[package]]
name = "hermit-abi"
-version = "0.3.2"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
+checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
[[package]]
name = "home"
"pin-project-lite",
]
-[[package]]
-name = "http-body"
-version = "1.0.0-rc.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "951dfc2e32ac02d67c90c0d65bd27009a635dc9b381a2cc7d284ab01e3a0150d"
-dependencies = [
- "bytes",
- "http",
-]
-
-[[package]]
-name = "http-body-util"
-version = "0.1.0-rc.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08ef12f041acdd397010e5fb6433270c147d3b8b2d0a840cd7fff8e531dca5c8"
-dependencies = [
- "bytes",
- "futures-util",
- "http",
- "http-body 1.0.0-rc.2",
- "pin-project-lite",
-]
-
[[package]]
name = "httparse"
version = "1.8.0"
"futures-util",
"h2",
"http",
- "http-body 0.4.5",
+ "http-body",
"httparse",
"httpdate",
"itoa",
"want",
]
-[[package]]
-name = "hyper"
-version = "1.0.0-rc.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b75264b2003a3913f118d35c586e535293b3e22e41f074930762929d071e092"
-dependencies = [
- "bytes",
- "futures-channel",
- "futures-core",
- "futures-util",
- "h2",
- "http",
- "http-body 1.0.0-rc.2",
- "httparse",
- "httpdate",
- "itoa",
- "pin-project-lite",
- "tokio",
- "tracing",
- "want",
-]
-
[[package]]
name = "hyper-tls"
version = "0.5.0"
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
dependencies = [
"bytes",
- "hyper 0.14.27",
+ "hyper",
"native-tls",
"tokio",
"tokio-native-tls",
[[package]]
name = "libc"
-version = "0.2.147"
+version = "0.2.148"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
+checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
[[package]]
name = "libffi"
[[package]]
name = "linux-raw-sys"
-version = "0.4.5"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
+checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128"
[[package]]
name = "lock_api"
[[package]]
name = "memchr"
-version = "2.5.0"
+version = "2.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
[[package]]
name = "mime"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+[[package]]
+name = "mime_guess"
+version = "2.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
+dependencies = [
+ "mime",
+ "unicase",
+]
+
[[package]]
name = "miniz_oxide"
version = "0.7.1"
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [
"libc",
- "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasi",
"windows-sys",
]
"syn 1.0.109",
]
+[[package]]
+name = "multer"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2"
+dependencies = [
+ "bytes",
+ "encoding_rs",
+ "futures-util",
+ "http",
+ "httparse",
+ "log",
+ "memchr",
+ "mime",
+ "spin 0.9.8",
+ "version_check",
+]
+
[[package]]
name = "native-tls"
version = "0.2.11"
[[package]]
name = "nix"
-version = "0.26.3"
+version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abbbc55ad7b13aac85f9401c796dcda1b864e07fcad40ad47792eaa8932ea502"
+checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
+dependencies = [
+ "bitflags 1.3.2",
+ "cfg-if",
+ "libc",
+]
+
+[[package]]
+name = "nix"
+version = "0.27.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
dependencies = [
"bitflags 2.4.0",
"cfg-if",
[[package]]
name = "object"
-version = "0.32.0"
+version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe"
+checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
dependencies = [
"memchr",
]
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.32",
+ "syn 2.0.37",
]
[[package]]
[[package]]
name = "openssl-sys"
-version = "0.9.92"
+version = "0.9.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db7e971c2c2bba161b2d2fdf37080177eff520b3bc044787c7f1f5f9e78d869b"
+checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d"
dependencies = [
"cc",
"libc",
"siphasher",
]
+[[package]]
+name = "pin-project"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.37",
+]
+
[[package]]
name = "pin-project-lite"
version = "0.2.13"
[[package]]
name = "proc-macro2"
-version = "1.0.66"
+version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
dependencies = [
"unicode-ident",
]
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1"
dependencies = [
- "base64 0.21.3",
+ "base64 0.21.4",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2",
"http",
- "http-body 0.4.5",
- "hyper 0.14.27",
+ "http-body",
+ "hyper",
"hyper-tls",
"ipnet",
"js-sys",
"cc",
"libc",
"once_cell",
- "spin",
+ "spin 0.5.2",
"untrusted",
"web-sys",
"winapi",
"getrandom",
"libc",
"once_cell",
- "spin",
+ "spin 0.5.2",
"untrusted",
"web-sys",
"winapi",
[[package]]
name = "rustix"
-version = "0.38.9"
+version = "0.38.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bfe0f2582b4931a45d1fa608f8a8722e8b3c7ac54dd6d5f3b3212791fedef49"
+checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f"
dependencies = [
"bitflags 2.4.0",
"errno",
"windows-sys",
]
+[[package]]
+name = "rustls"
+version = "0.20.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99"
+dependencies = [
+ "log",
+ "ring",
+ "sct",
+ "webpki",
+]
+
+[[package]]
+name = "rustls-pemfile"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2"
+dependencies = [
+ "base64 0.21.4",
+]
+
[[package]]
name = "rustversion"
version = "1.0.14"
"libc",
"log",
"memchr",
- "nix",
+ "nix 0.26.4",
"radix_trie",
"scopeguard",
"unicode-segmentation",
"windows-sys",
]
+[[package]]
+name = "scoped-tls"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
+
[[package]]
name = "scopeguard"
version = "1.2.0"
"getrandom",
"git-version",
"hostname",
- "http-body-util",
- "hyper 1.0.0-rc.3",
"indexmap",
"lazy_static",
"lexical",
"static_assertions",
"strum",
"strum_macros",
- "syn 2.0.32",
+ "syn 2.0.37",
"to-syn-value",
"to-syn-value_derive",
"tokio",
"walkdir",
+ "warp",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
+[[package]]
+name = "sct"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
[[package]]
name = "security-framework"
version = "2.9.2"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.32",
+ "syn 2.0.37",
]
[[package]]
name = "serde_json"
-version = "1.0.105"
+version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
+checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
dependencies = [
"itoa",
"ryu",
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.32",
+ "syn 2.0.37",
+]
+
+[[package]]
+name = "sha1"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.10.7",
]
[[package]]
[[package]]
name = "smallvec"
-version = "1.11.0"
+version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
+checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
[[package]]
name = "socket2"
[[package]]
name = "socket2"
-version = "0.5.3"
+version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877"
+checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e"
dependencies = [
"libc",
"windows-sys",
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+[[package]]
+name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+
[[package]]
name = "static_assertions"
version = "1.1.0"
[[package]]
name = "syn"
-version = "2.0.32"
+version = "2.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2"
+checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8"
dependencies = [
"proc-macro2",
"quote",
[[package]]
name = "thiserror"
-version = "1.0.47"
+version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
+checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.47"
+version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
+checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.32",
-]
-
-[[package]]
-name = "time"
-version = "0.1.45"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
-dependencies = [
- "libc",
- "wasi 0.10.0+wasi-snapshot-preview1",
- "winapi",
+ "syn 2.0.37",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfcc684f2ceaec3b4e8689657c9e0944b07bf5e34563e0bd758c4d42c05c82ed"
dependencies = [
- "syn 2.0.32",
+ "syn 2.0.37",
"to-syn-value_derive",
]
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.32",
+ "syn 2.0.37",
]
[[package]]
"parking_lot 0.12.1",
"pin-project-lite",
"signal-hook-registry",
- "socket2 0.5.3",
+ "socket2 0.5.4",
"tokio-macros",
"windows-sys",
]
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.32",
+ "syn 2.0.37",
]
[[package]]
"tokio",
]
+[[package]]
+name = "tokio-rustls"
+version = "0.23.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
+dependencies = [
+ "rustls",
+ "tokio",
+ "webpki",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-tungstenite"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd"
+dependencies = [
+ "futures-util",
+ "log",
+ "tokio",
+ "tungstenite",
+]
+
[[package]]
name = "tokio-util"
-version = "0.7.8"
+version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
+checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d"
dependencies = [
"bytes",
"futures-core",
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
dependencies = [
"cfg-if",
+ "log",
"pin-project-lite",
"tracing-core",
]
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
+[[package]]
+name = "tungstenite"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788"
+dependencies = [
+ "base64 0.13.1",
+ "byteorder",
+ "bytes",
+ "http",
+ "httparse",
+ "log",
+ "rand",
+ "sha1",
+ "thiserror",
+ "url",
+ "utf-8",
+]
+
[[package]]
name = "typenum"
-version = "1.16.0"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+
+[[package]]
+name = "unicase"
+version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
+dependencies = [
+ "version_check",
+]
[[package]]
name = "unicode-bidi"
[[package]]
name = "unicode-ident"
-version = "1.0.11"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
[[package]]
name = "unicode-width"
-version = "0.1.10"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "untrusted"
[[package]]
name = "url"
-version = "2.4.0"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
+checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
dependencies = [
"form_urlencoded",
"idna",
[[package]]
name = "walkdir"
-version = "2.3.3"
+version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
+checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
-name = "wasi"
-version = "0.10.0+wasi-snapshot-preview1"
+name = "warp"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
+checksum = "ba431ef570df1287f7f8b07e376491ad54f84d26ac473489427231e1718e1f69"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-util",
+ "headers",
+ "http",
+ "hyper",
+ "log",
+ "mime",
+ "mime_guess",
+ "multer",
+ "percent-encoding",
+ "pin-project",
+ "rustls-pemfile",
+ "scoped-tls",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "tokio",
+ "tokio-rustls",
+ "tokio-stream",
+ "tokio-tungstenite",
+ "tokio-util",
+ "tower-service",
+ "tracing",
+]
[[package]]
name = "wasi"
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.32",
+ "syn 2.0.37",
"wasm-bindgen-shared",
]
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.32",
+ "syn 2.0.37",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
"wasm-bindgen",
]
+[[package]]
+name = "webpki"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0e74f82d49d545ad128049b7e88f6576df2da6b02e9ce565c6f533be576957e"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
[[package]]
name = "winapi"
version = "0.3.9"
[[package]]
name = "winapi-util"
-version = "0.1.5"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
repl = ["dep:crossterm", "dep:ctrlc", "dep:rustyline"]
hostname = ["dep:hostname"]
tls = ["dep:native-tls"]
-http = ["dep:hyper", "dep:reqwest"]
+http = ["dep:warp", "dep:reqwest"]
rust_beta_channel = []
crypto-full = []
futures = "0.3"
libloading = "0.7"
derive_deref = "1.1.1"
-http-body-util = "0.1.0-rc.2"
bytes = "1"
dashu = "0.4.0"
num-order = { version = "1.2.0" }
ctrlc = { version = "3.2.2", optional = true }
rustyline = { version = "12.0.0", optional = true }
native-tls = { version = "0.2.4", optional = true }
-hyper = { version = "=1.0.0-rc.3", features = ["full"], optional = true }
+warp = { version = "=0.3.5", features = ["tls"], optional = true }
reqwest = { version = "0.11.18", features = ["blocking"], optional = true }
tokio = { version = "1.28.2", features = ["full"] }
Probabilistic predicates and random number generators.
* [`http/http_open`](src/lib/http/http_open.pl) Open a stream to
read answers from web servers. HTTPS is also supported.
-* [`http/http_server`](src/lib/http/http_server.pl) Runs a HTTP/1.1 and HTTP/2.0 web server. Uses [Hyper](https://hyper.rs) as a backend. Supports some query and form handling.
+* [`http/http_server`](src/lib/http/http_server.pl) Runs a HTTP/1.1 and HTTP/2.0 web server. Uses [Warp](https://github.com/seanmonstar/warp) as a backend. Supports some query and form handling.
* [`sgml`](src/lib/sgml.pl)
`load_html/3` and `load_xml/3` represent HTML and XML documents
as Prolog terms for convenient and efficient reasoning. Use
DeterministicLengthRundown,
#[strum_discriminants(strum(props(Arity = "7", Name = "$http_open")))]
HttpOpen,
- #[strum_discriminants(strum(props(Arity = "2", Name = "$http_listen")))]
+ #[strum_discriminants(strum(props(Arity = "5", Name = "$http_listen")))]
HttpListen,
#[strum_discriminants(strum(props(Arity = "7", Name = "$http_accept")))]
HttpAccept,
-use bytes::Bytes;
-use http_body_util::Full;
-use hyper::service::Service;
-use hyper::{body::Incoming as IncomingBody, Request, Response};
-use std::future::Future;
-use std::pin::Pin;
-use std::sync::{Arc, Condvar, Mutex};
+use std::sync::{Arc, Mutex, Condvar};
+use std::io::BufRead;
+
+use warp::http;
pub struct HttpListener {
pub incoming: std::sync::mpsc::Receiver<HttpRequest>,
}
-#[derive(Debug)]
pub struct HttpRequest {
- pub request: Request<IncomingBody>,
+ pub request_data: HttpRequestData,
pub response: HttpResponse,
}
-pub type HttpResponse = Arc<(Mutex<bool>, Mutex<Option<Response<Full<Bytes>>>>, Condvar)>;
-
-pub struct HttpService {
- pub tx: std::sync::mpsc::SyncSender<HttpRequest>,
-}
-
-impl Service<Request<IncomingBody>> for HttpService {
- type Response = Response<Full<Bytes>>;
- type Error = hyper::Error;
- type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
-
- fn call(&mut self, req: Request<IncomingBody>) -> Self::Future {
- // new connection!
- // we send the Request info to Prolog
- let response = Arc::new((Mutex::new(false), Mutex::new(None), Condvar::new()));
- let http_request = HttpRequest {
- request: req,
- response: Arc::clone(&response),
- };
- self.tx.send(http_request).unwrap();
+pub type HttpResponse = Arc<(Mutex<bool>, Mutex<Option<warp::reply::Response>>, Condvar)>;
- // we wait for the Response info from Prolog
- {
- let (ready, _response, cvar) = &*response;
- let mut ready = ready.lock().unwrap();
- while !*ready {
- ready = cvar.wait(ready).unwrap();
- }
- }
- {
- let (_, response, _) = &*response;
- let response = response.lock().unwrap().take();
- let res = response.expect("Data race error in HTTP Server");
- Box::pin(async move { Ok(res) })
- }
- }
+pub struct HttpRequestData {
+ pub method: http::Method,
+ pub headers: http::HeaderMap,
+ pub path: String,
+ pub query: String,
+ pub body: Box<dyn BufRead + Send>,
}
*/
/** This library provides an starting point to build HTTP server based applications.
-It is based on [Hyper](https://hyper.rs/), which allows for HTTP/1.0, HTTP/1.1 and HTTP/2. However,
-some advanced features that Hyper provides are still not accesible.
+It is based on [Warp](https://github.com/seanmonstar/warp), which allows for HTTP/1.0, HTTP/1.1 and HTTP/2. However,
+some advanced features that Warp provides are still not accesible.
## Usage
Some things that are still missing:
- Read forms in multipart format
- - HTTP Basic Auth
- Session handling via cookies
- HTML Templating (but you can use [Teruel](https://github.com/aarroyoc/teruel/), [Marquete](https://github.com/aarroyoc/marquete/) or [Djota](https://github.com/aarroyoc/djota) for that)
*/
:- module(http_server, [
http_listen/2,
+ http_listen/3,
http_headers/2,
http_status_code/2,
http_body/2,
http_redirect/2,
- http_query/3
+ http_query/3,
+ http_basic_auth/4
]).
:- meta_predicate http_listen(?, :).
+:- meta_predicate http_listen(?, :, ?).
+
+:- meta_predicate http_basic_auth(:, :, ?, ?).
:- use_module(library(charsio)).
:- use_module(library(crypto)).
%% http_listen(+Port, +Handlers).
%
+% Equivalent to `http_listen(Port, Handlers, [])`.
+http_listen(Port, Module:Handlers0) :-
+ must_be(integer, Port),
+ must_be(list, Handlers0),
+ maplist(module_qualification(Module), Handlers0, Handlers),
+ http_listen_(Port, Handlers, []).
+
+%% http_listen(+Port, +Handlers, +Options).
+%
% Listens for HTTP connections on port Port. Each handler on the list Handlers should be of the form: `HttpVerb(PathUnification, Predicate)`.
% For example: `get(user/User, get_info(User))` will match an HTTP request that is a GET, the path unifies with /user/User (where User is a variable)
-% and it will call `get_info` with three arguments: an `http_request` term, an `http_response` term and User.
-http_listen(Port, Module:Handlers0) :-
+% and it will call `get_info` with three arguments: an `http_request` term, an `http_response` term and User.
+%
+% The following options are supported:
+%
+% - `tls_key(+Key)` - a TLS key for HTTPS (string)
+% - `tls_cert(+Cert)` - a TLS cert for HTTPS (string)
+% - `content_length_limit(+Limit)` - maximum length (in bytes) for the incoming bodies. By default, 32KB.
+%
+% In order to have a HTTPS server (instead of plain HTTP), both `tls_key` and `tls_cert` options must be provided.
+http_listen(Port, Module:Handlers0, Options) :-
must_be(integer, Port),
must_be(list, Handlers0),
+ must_be(list, Options),
maplist(module_qualification(Module), Handlers0, Handlers),
- http_listen_(Port, Handlers).
+ http_listen_(Port, Handlers, Options).
module_qualification(M, H0, H) :-
H0 =.. [Method, Path, Goal],
H =.. [Method, Path, M:Goal].
-http_listen_(Port, Handlers) :-
+http_listen_(Port, Handlers, Options) :-
+ parse_options(Options, TLSKey, TLSCert, ContentLengthLimit),
phrase(format_("0.0.0.0:~d", [Port]), Addr),
- '$http_listen'(Addr, HttpListener),!,
+ '$http_listen'(Addr, HttpListener, TLSKey, TLSCert, ContentLengthLimit),!,
format("Listening at ~s\n", [Addr]),
http_loop(HttpListener, Handlers).
+parse_options(Options, TLSKey, TLSCert, ContentLengthLimit) :-
+ member_option_default(tls_key, Options, "", TLSKey),
+ member_option_default(tls_cert, Options, "", TLSCert),
+ member_option_default(content_length_limit, Options, 32768, ContentLengthLimit),
+ must_be(integer, ContentLengthLimit).
+
+member_option_default(Key, List, _Default, Value) :-
+ X =.. [Key, Value],
+ member(X, List).
+member_option_default(Key, List, Default, Default) :-
+ X =.. [Key, _],
+ \+ member(X, List).
+
+
http_loop(HttpListener, Handlers) :-
'$http_accept'(HttpListener, RequestMethod, RequestPath, RequestHeaders, RequestQuery, RequestStream, ResponseHandle),
current_time(Time),
)
; (
'$http_answer'(ResponseHandle, 404, [], ResponseStream),
- call_cleanup(format(ResponseStream, "Not Found"), close(ResponseStream)))
+ call_cleanup(format(ResponseStream, "Not Found", []), close(ResponseStream)))
),
http_loop(HttpListener, Handlers).
url_decode(Chars).
url_decode([]) --> [].
+
+%% http_basic_auth(+LoginPredicate, +Handler, +Request, -Response)
+%
+% Metapredicate that wraps an existing Handler with an HTTP Basic Auth flow.
+% Checks if a given user + password is authorized to execute that handler, returning 401
+% if it's not satisfied.
+%
+% `LoginPredicate` must be a predicate of arity 2 that takes a User and a Password.
+% `Handler` will have, in addition to the Request and Response arguments, a User argument
+% containing the User given in the authentication.
+%
+% Example:
+%
+% ```
+% main :-
+% http_listen(8800,[get('/', http_basic_auth(login, inside_handler("data")))]).
+%
+% login(User, Pass) :-
+% User = "aarroyoc",
+% Pass = "123456".
+%
+% inside_handler(Data, User, Request, Response) :-
+% http_body(Response, text(User)).
+% ```
+http_basic_auth(LoginPredicate, Handler, Request, Response) :-
+ http_headers(Request, Headers),
+ member("authorization"-AuthorizationStr, Headers),
+ append("Basic ", Coded, AuthorizationStr),
+ chars_base64(UserPass, Coded, []),
+ append(User, [':'|Password], UserPass),
+ (
+ call(LoginPredicate, User, Password) ->
+ call(Handler, User, Request, Response)
+ ; http_basic_auth_unauthorized_response(Response)
+ ).
+
+http_basic_auth(_LoginPredicate, _Handler, Request, Response) :-
+ http_headers(Request, Headers),
+ \+ member("authorization"-_, Headers),
+ http_basic_auth_unauthorized_response(Response).
+
+http_basic_auth_unauthorized_response(Response) :-
+ http_status_code(Response, 401),
+ http_headers(Response, ["www-authenticate"-"Basic realm=\"Scryer Prolog\", charset=\"UTF-8\""]),
+ http_body(Response, text("Unauthorized")).
+
if interruption {
self.machine_st.throw_interrupt_exception();
self.machine_st.backtrack();
+
+ #[cfg(not(target_arch = "wasm32"))]
+ let runtime = tokio::runtime::Runtime::new().unwrap();
+ #[cfg(target_arch = "wasm32")]
+ let runtime = tokio::runtime::Builder::new_current_thread()
+ .enable_all()
+ .build()
+ .unwrap();
+
+ let old_runtime = std::mem::replace(&mut self.runtime, runtime);
+ old_runtime.shutdown_background();
}
}
Err(_) => unreachable!(),
#[cfg(feature = "tls")]
use native_tls::TlsStream;
+#[cfg(feature = "http")]
+use warp::hyper;
+
#[derive(Debug, BitfieldSpecifier, Clone, Copy, PartialEq, Eq, Hash)]
#[bits = 1]
pub enum StreamType {
#[cfg(feature = "http")]
pub struct HttpWriteStream {
status_code: u16,
- headers: hyper::HeaderMap,
+ headers: mem::ManuallyDrop<hyper::HeaderMap>,
response: TypedArenaPtr<HttpResponse>,
- buffer: Vec<u8>,
+ buffer: mem::ManuallyDrop<Vec<u8>>,
}
#[cfg(feature = "http")]
#[inline]
fn flush(&mut self) -> std::io::Result<()> {
- let (ready, response, cvar) = &**self.response;
-
- let mut ready = ready.lock().unwrap();
- {
- let mut response = response.lock().unwrap();
-
- let bytes = bytes::Bytes::copy_from_slice(&self.buffer);
- let mut response_ = hyper::Response::builder().status(self.status_code);
- *response_.headers_mut().unwrap() = self.headers.clone();
- *response = Some(response_.body(http_body_util::Full::new(bytes)).unwrap());
- }
- *ready = true;
- cvar.notify_one();
+ Ok(())
+ }
+}
- Ok(())
+#[cfg(feature = "http")]
+impl HttpWriteStream {
+ fn drop(&mut self) {
+ let headers = unsafe { mem::ManuallyDrop::take(&mut self.headers) };
+ let buffer = unsafe { mem::ManuallyDrop::take(&mut self.buffer) };
+
+ let (ready, response, cvar) = &**self.response;
+
+ let mut ready = ready.lock().unwrap();
+ {
+ let mut response = response.lock().unwrap();
+
+ let mut response_ = warp::http::Response::builder()
+ .status(self.status_code);
+ *response_.headers_mut().unwrap() = headers;
+ *response = Some(response_.body(warp::hyper::Body::from(buffer)).unwrap());
+ }
+ *ready = true;
+ cvar.notify_one();
}
}
+
#[derive(Debug)]
pub struct StandardOutputStream {}
headers: hyper::HeaderMap,
arena: &mut Arena,
) -> Self {
- Stream::HttpWrite(arena_alloc!(
- StreamLayout::new(CharReader::new(HttpWriteStream {
- response,
- status_code,
- headers,
- buffer: Vec::new(),
- })),
- arena
- ))
+ Stream::HttpWrite(arena_alloc!(
+ StreamLayout::new(CharReader::new(HttpWriteStream {
+ response,
+ status_code,
+ headers: mem::ManuallyDrop::new(headers),
+ buffer: mem::ManuallyDrop::new(Vec::new()),
+ })),
+ arena
+ ))
}
#[inline]
Ok(())
}
#[cfg(feature = "http")]
- Stream::HttpWrite(ref mut http_stream) => {
+ Stream::HttpWrite(ref mut http_stream) => {
+ http_stream.inner_mut().drop();
unsafe {
http_stream.set_tag(ArenaHeaderTag::Dropped);
std::ptr::drop_in_place(&mut http_stream.inner_mut().buffer as *mut _);
use crate::heap_iter::*;
use crate::heap_print::*;
#[cfg(feature = "http")]
-use crate::http::{HttpListener, HttpResponse, HttpService};
+use crate::http::{HttpRequestData, HttpListener, HttpResponse, HttpRequest};
use crate::instructions::*;
use crate::machine;
use crate::machine::code_walker::*;
use std::cell::Cell;
use std::cmp::Ordering;
-use std::collections::BTreeSet;
+use std::collections::{BTreeSet};
use std::convert::TryFrom;
use std::env;
#[cfg(feature = "ffi")]
use std::ffi::CString;
use std::fs;
use std::hash::{BuildHasher, BuildHasherDefault};
-use std::io::{ErrorKind, Read, Write};
+use std::io::{ErrorKind, Read, BufRead, Write};
use std::iter::{once, FromIterator};
use std::mem;
use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs};
use std::ops::Sub;
use std::process;
use std::str::FromStr;
+use std::sync::{Mutex, Arc, Condvar};
use chrono::{offset::Local, DateTime};
#[cfg(not(target_arch = "wasm32"))]
use roxmltree;
use select;
-use bytes::Buf;
-use http_body_util::BodyExt;
#[cfg(feature = "http")]
-use hyper::header::{HeaderName, HeaderValue};
+use warp::hyper::header::{HeaderValue, HeaderName};
#[cfg(feature = "http")]
-use hyper::server::conn::http1;
+use warp::hyper::{HeaderMap, Method};
#[cfg(feature = "http")]
-use hyper::{HeaderMap, Method};
+use warp::{Buf, Filter};
#[cfg(feature = "http")]
use reqwest::Url;
+use futures::future;
#[cfg(feature = "repl")]
pub(crate) fn get_key() -> KeyEvent {
#[inline(always)]
pub(crate) fn http_listen(&mut self) -> CallResult {
let address_sink = self.deref_register(1);
- if let Some(address_str) = self.machine_st.value_to_str_like(address_sink) {
- let address_string = address_str.as_str();
- let addr: SocketAddr = match address_string
- .to_socket_addrs()
- .ok()
- .and_then(|mut s| s.next())
- {
- Some(addr) => addr,
+ let tls_key = self.deref_register(3);
+ let tls_cert = self.deref_register(4);
+ let content_length_limit = self.deref_register(5);
+ const CONTENT_LENGTH_LIMIT_DEFAULT: u64 = 32768;
+ let content_length_limit = match Number::try_from(content_length_limit) {
+ Ok(Number::Fixnum(n)) => if n.get_num() >= 0 {
+ n.get_num() as u64
+ } else {
+ CONTENT_LENGTH_LIMIT_DEFAULT
+ },
+ Ok(Number::Integer(n)) => {
+ let n: Result<u64, _> = (&*n).try_into();
+ match n {
+ Ok(u) => u,
+ Err(_) => CONTENT_LENGTH_LIMIT_DEFAULT,
+ }
+ }
+ _ => CONTENT_LENGTH_LIMIT_DEFAULT,
+ };
+
+ let ssl_server: Option<(String,String)> = {
+ match self.machine_st.value_to_str_like(tls_key) {
+ Some(key) => {
+ match self.machine_st.value_to_str_like(tls_cert) {
+ Some(cert) => {
+ let key_str = key.as_str();
+ let cert_str = cert.as_str();
+
+ if key_str.is_empty() || cert_str.is_empty() {
+ None
+ } else {
+ Some((key_str.to_string(), cert_str.to_string()))
+ }
+ }
+ None => None
+ }
+ }
+ None => None
+ }
+ };
+
+ if let Some(address_str) = self.machine_st.value_to_str_like(address_sink) {
+ let address_string = address_str.as_str();
+ let addr: SocketAddr = match address_string.to_socket_addrs().ok().and_then(|mut s| s.next()) {
+ Some(addr) => addr,
_ => {
self.machine_st.fail = true;
return Ok(());
}
};
- let (tx, rx) = std::sync::mpsc::sync_channel(1024);
-
- let _guard = self.runtime.enter();
- let listener = match self
- .runtime
- .block_on(async { tokio::net::TcpListener::bind(addr).await })
- {
- Ok(listener) => listener,
- Err(_) => {
- return Err(self.machine_st.open_permission_error(
- address_sink,
- atom!("http_listen"),
- 2,
- ));
- }
- };
-
- self.runtime.spawn(async move {
- loop {
- let tx = tx.clone();
- let (stream, _) = listener.accept().await.unwrap();
-
- tokio::task::spawn(async move {
- if let Err(err) = http1::Builder::new()
- .serve_connection(stream, HttpService { tx })
- .await
- {
- eprintln!("Error serving connection: {:?}", err);
- }
- });
- }
- });
- let http_listener = HttpListener { incoming: rx };
- let http_listener = arena_alloc!(http_listener, &mut self.machine_st.arena);
+ let (tx, rx) = std::sync::mpsc::sync_channel(1024);
+
+ fn get_reader(body: impl Buf + Send + 'static) -> Box<dyn BufRead + Send> {
+ Box::new(body.reader())
+ }
+
+ let serve = warp::body::aggregate()
+ .and(warp::header::optional::<u64>(warp::http::header::CONTENT_LENGTH.as_str()))
+ .and(warp::method())
+ .and(warp::header::headers_cloned())
+ .and(warp::path::full())
+ .and(warp::query::raw().or_else(|_| future::ready(Ok::<(String,), warp::Rejection>(("".to_string(),)))))
+ .map(move |body, content_length, method, headers: warp::http::HeaderMap, path: warp::filters::path::FullPath, query| {
+ if let Some(content_length) = content_length {
+ if content_length > content_length_limit {
+ return warp::http::Response::builder()
+ .status(413)
+ .body(warp::hyper::Body::empty())
+ .unwrap();
+ }
+ }
+
+ let http_request_data = HttpRequestData {
+ method,
+ headers,
+ path: path.as_str().to_string(),
+ query,
+ body: get_reader(body),
+ };
+ let response = Arc::new((Mutex::new(false), Mutex::new(None), Condvar::new()));
+ let http_request = HttpRequest { request_data: http_request_data, response: Arc::clone(&response) };
+ // we send the request to http_accept
+ tx.send(http_request).unwrap();
+
+ // we wait for the Response info from Prolog
+ {
+ let (ready, _response, cvar) = &*response;
+ let mut ready = ready.lock().unwrap();
+ while !*ready {
+ ready = cvar.wait(ready).unwrap();
+ }
+ }
+ {
+ let (_, response, _) = &*response;
+ let response = response.lock().unwrap().take();
+ response.expect("Data race error in HTTP server")
+ }
+ });
+
+ self.runtime.spawn(async move {
+ match ssl_server {
+ Some((key, cert)) => {
+ warp::serve(serve).tls().key(key).cert(cert).run(addr).await
+ }
+ None => {
+ warp::serve(serve).run(addr).await
+ }
+ }
+ });
+
+ let http_listener = HttpListener { incoming: rx };
+ let http_listener = arena_alloc!(http_listener, &mut self.machine_st.arena);
let addr = self.deref_register(2);
self.machine_st.bind(
addr.as_var().unwrap(),
#[cfg(feature = "http")]
#[inline(always)]
pub(crate) fn http_accept(&mut self) -> CallResult {
- let culprit = self.deref_register(1);
- let method = self.deref_register(2);
- let path = self.deref_register(3);
- let query = self.deref_register(5);
- let stream_addr = self.deref_register(6);
- let handle_addr = self.deref_register(7);
- read_heap_cell!(culprit,
- (HeapCellValueTag::Cons, cons_ptr) => {
- match_untyped_arena_ptr!(cons_ptr,
- (ArenaHeaderTag::HttpListener, http_listener) => {
- match http_listener.incoming.recv() {
- Ok(request) => {
- let method_atom = match *request.request.method() {
- Method::GET => atom!("get"),
- Method::POST => atom!("post"),
- Method::PUT => atom!("put"),
- Method::DELETE => atom!("delete"),
- Method::PATCH => atom!("patch"),
- Method::HEAD => atom!("head"),
- _ => unreachable!(),
- };
- let path_atom = AtomTable::build_with(&self.machine_st.atom_tbl, request.request.uri().path());
- let path_cell = atom_as_cstr_cell!(path_atom);
- let headers: Vec<HeapCellValue> = request.request.headers().iter().map(|(header_name, header_value)| {
- let h = self.machine_st.heap.len();
-
- let header_term = functor!(
- AtomTable::build_with(&self.machine_st.atom_tbl, header_name.as_str()),
- [cell(string_as_cstr_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, header_value.to_str().unwrap())))]
- );
-
- self.machine_st.heap.extend(header_term.into_iter());
- str_loc_as_cell!(h)
- }).collect();
-
- let headers_list = iter_to_heap_list(&mut self.machine_st.heap, headers.into_iter());
-
- let query_str = request.request.uri().query().unwrap_or("");
- let query_atom = AtomTable::build_with(&self.machine_st.atom_tbl, query_str);
- let query_cell = string_as_cstr_cell!(query_atom);
-
- let hyper_req = request.request;
- let buf = self.runtime.block_on(async {hyper_req.collect().await.unwrap().aggregate()});
- let reader = buf.reader();
-
- let mut stream = Stream::from_http_stream(
- path_atom,
- Box::new(reader),
- &mut self.machine_st.arena
- );
- *stream.options_mut() = StreamOptions::default();
- stream.options_mut().set_stream_type(StreamType::Binary);
- self.indices.streams.insert(stream);
- let stream = stream_as_cell!(stream);
-
- let handle = arena_alloc!(request.response, &mut self.machine_st.arena);
-
- self.machine_st.bind(method.as_var().unwrap(), atom_as_cell!(method_atom));
- self.machine_st.bind(path.as_var().unwrap(), path_cell);
- unify!(self.machine_st, heap_loc_as_cell!(headers_list), self.machine_st.registers[4]);
- self.machine_st.bind(query.as_var().unwrap(), query_cell);
- self.machine_st.bind(stream_addr.as_var().unwrap(), stream);
- self.machine_st.bind(handle_addr.as_var().unwrap(), typed_arena_ptr_as_cell!(handle));
- }
- Err(_) => {
- self.machine_st.fail = true;
+ let culprit = self.deref_register(1);
+ let method = self.deref_register(2);
+ let path = self.deref_register(3);
+ let query = self.deref_register(5);
+ let stream_addr = self.deref_register(6);
+ let handle_addr = self.deref_register(7);
+ read_heap_cell!(culprit,
+ (HeapCellValueTag::Cons, cons_ptr) => {
+ match_untyped_arena_ptr!(cons_ptr,
+ (ArenaHeaderTag::HttpListener, http_listener) => {
+ loop {
+ match http_listener.incoming.recv_timeout(std::time::Duration::from_millis(200)) {
+ Ok(request) => {
+ let method_atom = match request.request_data.method {
+ Method::GET => atom!("get"),
+ Method::POST => atom!("post"),
+ Method::PUT => atom!("put"),
+ Method::DELETE => atom!("delete"),
+ Method::PATCH => atom!("patch"),
+ Method::HEAD => atom!("head"),
+ Method::OPTIONS => atom!("options"),
+ Method::TRACE => atom!("trace"),
+ Method::CONNECT => atom!("connect"),
+ _ => atom!("unsupported_extension"),
+ };
+ let path_atom = AtomTable::build_with(&self.machine_st.atom_tbl, &request.request_data.path);
+ let path_cell = atom_as_cstr_cell!(path_atom);
+ let headers: Vec<HeapCellValue> = request.request_data.headers.iter().map(|(header_name, header_value)| {
+ let h = self.machine_st.heap.len();
+ let header_term = functor!(AtomTable::build_with(&self.machine_st.atom_tbl, header_name.as_str()), [cell(string_as_cstr_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, header_value.to_str().unwrap())))]);
+
+ self.machine_st.heap.extend(header_term.into_iter());
+ str_loc_as_cell!(h)
+ }).collect();
+
+ let headers_list = iter_to_heap_list(&mut self.machine_st.heap, headers.into_iter());
+
+ let query_str = request.request_data.query;
+ let query_atom = AtomTable::build_with(&self.machine_st.atom_tbl, &query_str);
+ let query_cell = string_as_cstr_cell!(query_atom);
+
+ let mut stream = Stream::from_http_stream(
+ path_atom,
+ request.request_data.body,
+ &mut self.machine_st.arena
+ );
+ *stream.options_mut() = StreamOptions::default();
+ stream.options_mut().set_stream_type(StreamType::Binary);
+ self.indices.streams.insert(stream);
+ let stream = stream_as_cell!(stream);
+
+ let handle = arena_alloc!(request.response, &mut self.machine_st.arena);
+
+ self.machine_st.bind(method.as_var().unwrap(), atom_as_cell!(method_atom));
+ self.machine_st.bind(path.as_var().unwrap(), path_cell);
+ unify!(self.machine_st, heap_loc_as_cell!(headers_list), self.machine_st.registers[4]);
+ self.machine_st.bind(query.as_var().unwrap(), query_cell);
+ self.machine_st.bind(stream_addr.as_var().unwrap(), stream);
+ self.machine_st.bind(handle_addr.as_var().unwrap(), typed_arena_ptr_as_cell!(handle));
+ break
+ }
+ Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {
+ let interrupted = machine::INTERRUPT.load(std::sync::atomic::Ordering::Relaxed);
+
+ match machine::INTERRUPT.compare_exchange(
+ interrupted,
+ false,
+ std::sync::atomic::Ordering::Relaxed,
+ std::sync::atomic::Ordering::Relaxed,
+ ) {
+ Ok(interruption) => {
+ if interruption {
+ self.machine_st.throw_interrupt_exception();
+ self.machine_st.backtrack();
+ let old_runtime = std::mem::replace(&mut self.runtime, tokio::runtime::Runtime::new().unwrap());
+ old_runtime.shutdown_background();
+ break
+ }
+ }
+ Err(_) => unreachable!(),
+ }
+
+ }
+ Err(_) => {
+ self.machine_st.fail = true;
+ }
+ }
}
}
- }
_ => {
unreachable!();
}