From 9b5c9f41a94d768156d514f61f989c8e48ae38c3 Mon Sep 17 00:00:00 2001 From: Ruslan Pislari Date: Wed, 20 Nov 2024 19:26:58 +0200 Subject: [PATCH 1/3] fix: process http body chunks --- Cargo.lock | 808 +++++++++++------- crates/http-service/src/executor/mod.rs | 12 +- crates/http-service/src/executor/wasi_http.rs | 60 +- crates/http-service/src/lib.rs | 32 +- crates/secret/Cargo.toml | 1 - src/main.rs | 10 +- 6 files changed, 554 insertions(+), 369 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 00bddc1..a13d574 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,18 +19,18 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ - "gimli 0.29.0", + "gimli 0.31.1", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "ahash" @@ -76,9 +76,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -91,55 +91,55 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", @@ -154,23 +154,23 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ - "addr2line 0.22.0", - "cc", + "addr2line 0.24.2", "cfg-if", "libc", "miniz_oxide", - "object 0.36.3", + "object 0.36.5", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -211,9 +211,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" dependencies = [ "memchr", ] @@ -226,18 +226,18 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.16.3" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" +checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" +checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote", @@ -252,9 +252,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "bytesize" @@ -334,9 +334,9 @@ dependencies = [ [[package]] name = "cap-fs-ext" -version = "3.2.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb23061fc1c4ead4e45ca713080fe768e6234e959f5a5c399c39eb41aa34e56e" +checksum = "e16619ada836f12897a72011fe99b03f0025b87a8dbbea4f3c9f89b458a23bf3" dependencies = [ "cap-primitives", "cap-std", @@ -346,9 +346,9 @@ dependencies = [ [[package]] name = "cap-net-ext" -version = "3.2.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83ae11f116bcbafc5327c6af250341db96b5930046732e1905f7dc65887e0e1" +checksum = "710b0eb776410a22c89a98f2f80b2187c2ac3a8206b99f3412332e63c9b09de0" dependencies = [ "cap-primitives", "cap-std", @@ -358,9 +358,9 @@ dependencies = [ [[package]] name = "cap-primitives" -version = "3.2.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d00bd8d26c4270d950eaaa837387964a2089a1c3c349a690a1fa03221d29531" +checksum = "82fa6c3f9773feab88d844aa50035a33fb6e7e7426105d2f4bb7aadc42a5f89a" dependencies = [ "ambient-authority", "fs-set-times", @@ -375,9 +375,9 @@ dependencies = [ [[package]] name = "cap-rand" -version = "3.2.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbcb16a619d8b8211ed61f42bd290d2a1ac71277a69cf8417ec0996fa92f5211" +checksum = "53774d49369892b70184f8312e50c1b87edccb376691de4485b0ff554b27c36c" dependencies = [ "ambient-authority", "rand", @@ -385,9 +385,9 @@ dependencies = [ [[package]] name = "cap-std" -version = "3.2.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19eb8e3d71996828751c1ed3908a439639752ac6bdc874e41469ef7fc15fbd7f" +checksum = "7f71b70818556b4fe2a10c7c30baac3f5f45e973f49fc2673d7c75c39d0baf5b" dependencies = [ "cap-primitives", "io-extras", @@ -397,9 +397,9 @@ dependencies = [ [[package]] name = "cap-time-ext" -version = "3.2.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61142dc51e25b7acc970ca578ce2c3695eac22bbba46c1073f5f583e78957725" +checksum = "69dd48afa2363f746c93f961c211f6f099fb594a3446b8097bc5f79db51b6816" dependencies = [ "ambient-authority", "cap-primitives", @@ -411,12 +411,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.10" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -457,9 +458,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.15" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d8838454fda655dafd3accb2b6e2bea645b9e4078abe84a22ceb947235c5cc" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -467,9 +468,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -479,9 +480,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -491,9 +492,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "cli" @@ -508,7 +509,7 @@ dependencies = [ "http-backend", "http-body-util", "http-service", - "hyper 1.4.1", + "hyper 1.5.1", "hyper-tls", "hyper-util", "pretty_env_logger", @@ -524,9 +525,9 @@ dependencies = [ [[package]] name = "clickhouse" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbbda6a46e0d129d51a808b75e92c209d45313d506dc1734811ca51b4d671f9d" +checksum = "2135bb9638e8c8c1e3d794f242099e57987059ba52e7e3de597e1d99b2c4a5a3" dependencies = [ "bstr", "bytes", @@ -535,7 +536,7 @@ dependencies = [ "futures", "futures-channel", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.1", "hyper-util", "lz4_flex", "replace_with", @@ -561,9 +562,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "colored" @@ -593,18 +594,18 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpp_demangle" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8227005286ec39567949b33df9896bcadfa6051bccca2488129f108ca23119" +checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" dependencies = [ "cfg-if", ] [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] @@ -848,6 +849,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "dyn-stack" version = "0.10.0" @@ -866,20 +878,20 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] [[package]] name = "enum-as-inner" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "syn", @@ -922,9 +934,9 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fastrand" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "fd-lock" @@ -980,9 +992,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -995,9 +1007,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1005,15 +1017,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1022,15 +1034,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -1039,21 +1051,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1241,15 +1253,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "h2" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" dependencies = [ "atomic-waker", "bytes", @@ -1296,6 +1308,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" + [[package]] name = "heck" version = "0.4.1" @@ -1314,6 +1332,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "hex" version = "0.4.3" @@ -1351,7 +1375,7 @@ dependencies = [ "claims", "http 1.1.0", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.1", "hyper-util", "log", "mock-http-connector", @@ -1415,7 +1439,7 @@ dependencies = [ "http 1.1.0", "http-backend", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.1", "hyper-util", "nanoid", "once_cell", @@ -1441,9 +1465,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1459,9 +1483,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.30" +version = "0.14.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" dependencies = [ "bytes", "futures-channel", @@ -1481,9 +1505,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" dependencies = [ "bytes", "futures-channel", @@ -1508,7 +1532,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.1", "hyper-util", "native-tls", "tokio", @@ -1518,29 +1542,28 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.7" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", "http-body 1.0.1", - "hyper 1.4.1", + "hyper 1.5.1", "pin-project-lite", "socket2", "tokio", - "tower", "tower-service", "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1559,6 +1582,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "id-arena" version = "2.2.1" @@ -1567,30 +1708,41 @@ checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", ] [[package]] name = "indexmap" -version = "2.3.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.1", "serde", ] [[package]] name = "io-extras" -version = "0.18.2" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9f046b9af244f13b3bd939f55d16830ac3a201e8a9ba9661bfcb03e2be72b9b" +checksum = "7d45fd7584f9b67ac37bc041212d06bfac0700b36456b05890d36a3b626260eb" dependencies = [ "io-lifetimes", "windows-sys 0.52.0", @@ -1604,17 +1756,17 @@ checksum = "5a611371471e98973dbcab4e0ec66c31a10bc356eeb4d54a0e05eac8158fe38c" [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is-terminal" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi", + "hermit-abi 0.4.0", "libc", "windows-sys 0.52.0", ] @@ -1645,9 +1797,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "7a73e9fe3c49d7afb2ace819fa181a287ce54a0983eda4e0eb05c22f82ffe534" [[package]] name = "ittapi" @@ -1680,9 +1832,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -1701,9 +1853,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" [[package]] name = "libloading" @@ -1717,9 +1869,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" @@ -1737,6 +1889,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "lock_api" version = "0.4.12" @@ -1800,9 +1958,9 @@ dependencies = [ [[package]] name = "memmap2" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" dependencies = [ "libc", "stable_deref_trait", @@ -1828,11 +1986,11 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -1841,7 +1999,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "wasi", "windows-sys 0.52.0", @@ -1855,7 +2013,7 @@ checksum = "6cdff31167a91cebfab4eb65b63dc050583f5a24b09d825f570b415f4247caf6" dependencies = [ "colored", "httparse", - "hyper 0.14.30", + "hyper 0.14.31", "itertools 0.10.5", "paste", "serde", @@ -1960,7 +2118,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] @@ -1978,24 +2136,24 @@ dependencies = [ [[package]] name = "object" -version = "0.36.3" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -2025,9 +2183,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -2111,18 +2269,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", @@ -2131,9 +2289,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -2143,9 +2301,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "ppv-lite86" @@ -2168,9 +2326,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -2223,18 +2381,18 @@ checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" [[package]] name = "psm" -version = "0.1.21" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" dependencies = [ "cc", ] [[package]] name = "pulp" -version = "0.18.21" +version = "0.18.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec8d02258294f59e4e223b41ad7e81c874aa6b15bc4ced9ba3965826da0eed5" +checksum = "a0a01a0dc67cf4558d279f0c25b0962bd08fc6dec0137699eae304103e882fe6" dependencies = [ "bytemuck", "libm", @@ -2251,7 +2409,7 @@ dependencies = [ "crossbeam-utils", "libc", "once_cell", - "raw-cpuid 11.1.0", + "raw-cpuid 11.2.0", "wasi", "web-sys", "winapi", @@ -2259,9 +2417,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -2317,9 +2475,9 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.1.0" +version = "11.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb9ee317cfe3fbd54b36a511efc1edd42e216903c9cd575e686dd68a2ba90d8d" +checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" dependencies = [ "bitflags 2.6.0", ] @@ -2361,18 +2519,18 @@ checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430" [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", @@ -2394,14 +2552,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", ] [[package]] @@ -2415,13 +2573,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -2432,9 +2590,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "replace_with" @@ -2509,18 +2667,18 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags 2.6.0", "errno", @@ -2547,15 +2705,15 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -2570,9 +2728,9 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safetensors" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7725d4d98fa515472f43a6e2bbf956c48e06b89bb50593a040e5945160214450" +checksum = "44560c11236a6130a46ce36c836a62936dc81ebf8c36a37947423571be0e55b6" dependencies = [ "serde", "serde_json", @@ -2589,11 +2747,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2610,11 +2768,10 @@ checksum = "0cd08a21f852bd2fe42e3b2a6c76a0db6a95a5b5bd29c0521dd0b30fa1712ec8" [[package]] name = "sealed" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a8caec23b7800fb97971a1c6ae365b6239aaeddfb934d6265f8505e795699d" +checksum = "22f968c5ea23d555e670b449c1c5e7b2fc399fdaec1d304a17cd48e288abc107" dependencies = [ - "heck 0.4.1", "proc-macro2", "quote", "syn", @@ -2627,7 +2784,6 @@ dependencies = [ "anyhow", "async-trait", "reactor", - "runtime", "tracing", "wasmtime", ] @@ -2647,9 +2803,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", @@ -2669,18 +2825,18 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" [[package]] name = "serde" -version = "1.0.207" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5665e14a49a4ea1b91029ba7d3bca9f299e1f7cfa194388ccc20f14743e784f2" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.207" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aea2634c86b0e8ef2cfdc0c340baede54ec27b1e46febd7f80dffb2aa44a00e" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", @@ -2700,9 +2856,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.124" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -2721,9 +2877,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -2759,9 +2915,9 @@ dependencies = [ [[package]] name = "shellflip" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d72636b96dd0a44f4d16aa4c710cef8b8c98a0cb86075995c7529697352a6b95" +checksum = "964660222a47f2903556eee15c697eba1bf7d3c6499b6dd8a2401929e8aa2702" dependencies = [ "anyhow", "async-trait", @@ -2778,6 +2934,12 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -2829,9 +2991,9 @@ dependencies = [ [[package]] name = "spdx" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47317bbaf63785b53861e1ae2d11b80d6b624211d42cb20efcd210ee6f8a14bc" +checksum = "bae30cc7bfe3656d60ee99bf6836f472b0c53dddcbf335e253329abb16e535a2" dependencies = [ "smallvec", ] @@ -2874,9 +3036,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.74" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -2938,9 +3100,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.12.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -2993,18 +3155,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", @@ -3022,25 +3184,20 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.8.0" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.39.2" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -3088,9 +3245,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -3099,9 +3256,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -3135,9 +3292,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "serde", @@ -3146,32 +3303,11 @@ dependencies = [ "winnow", ] -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -3274,38 +3410,23 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "untrusted" @@ -3321,15 +3442,27 @@ checksum = "b5c61fea9e6205d0d14c7e6efe252f15ed404da4cbdbe4ecd1de0a4d7241829f" [[package]] name = "url" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -3338,9 +3471,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom", ] @@ -3416,9 +3549,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -3427,9 +3560,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", @@ -3442,9 +3575,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3452,9 +3585,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", @@ -3465,9 +3598,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasm-encoder" @@ -3490,11 +3623,12 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.215.0" +version = "0.220.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb56df3e06b8e6b77e37d2969a50ba51281029a9aeb3855e76b7f49b6418847" +checksum = "ebf48234b389415b226a4daef6562933d38c7b28a8b8f64c5c4130dad1561ab7" dependencies = [ "leb128", + "wasmparser 0.220.0", ] [[package]] @@ -3537,6 +3671,16 @@ dependencies = [ "semver", ] +[[package]] +name = "wasmparser" +version = "0.220.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e246c2772ce3ebc83f89a2d4487ac5794cad6c309b2071818a88c7db7c36d87b" +dependencies = [ + "bitflags 2.6.0", + "indexmap", +] + [[package]] name = "wasmprinter" version = "0.202.0" @@ -3835,7 +3979,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.1", "rustls", "tokio", "tokio-rustls", @@ -3900,24 +4044,24 @@ dependencies = [ [[package]] name = "wast" -version = "215.0.0" +version = "220.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff1d00d893593249e60720be04a7c1f42f1c4dc3806a2869f4e66ab61eb54cb" +checksum = "4e708c8de08751fd66e70961a32bae9d71901f14a70871e181cb8461a3bb3165" dependencies = [ "bumpalo", "leb128", "memchr", "unicode-width", - "wasm-encoder 0.215.0", + "wasm-encoder 0.220.0", ] [[package]] name = "wat" -version = "1.215.0" +version = "1.220.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670bf4d9c8cf76ae242d70ded47c546525b6dafaa6871f9bcb065344bf2b4e3d" +checksum = "de4f1d7d59614ba690541360102b995c4eb1b9ed373701d5102cc1a968b1c5a3" dependencies = [ - "wast 215.0.0", + "wast 220.0.0", ] [[package]] @@ -3931,9 +4075,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -3941,9 +4085,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.3" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" dependencies = [ "rustls-pki-types", ] @@ -4197,9 +4341,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -4281,6 +4425,18 @@ dependencies = [ "wast 35.0.2", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "yoke" version = "0.7.4" @@ -4353,6 +4509,28 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zip" version = "0.6.6" diff --git a/crates/http-service/src/executor/mod.rs b/crates/http-service/src/executor/mod.rs index b5f556d..8df05b1 100644 --- a/crates/http-service/src/executor/mod.rs +++ b/crates/http-service/src/executor/mod.rs @@ -8,11 +8,10 @@ use anyhow::{anyhow, bail, Context, Result}; use async_trait::async_trait; use bytesize::ByteSize; use dictionary::Dictionary; -use http::{HeaderMap, HeaderValue, Method, Response}; +use http::{HeaderMap, HeaderValue, Method}; use http_backend::Backend; -use http_body_util::combinators::BoxBody; use http_body_util::{BodyExt, Full}; -use hyper::body::{Body, Bytes}; +use hyper::body::{Body}; use reactor::gcore::fastedge; use runtime::store::StoreBuilder; use runtime::{App, InstancePre, WasmEngine}; @@ -20,6 +19,7 @@ use secret::{Secret, SecretStrategy}; use smol_str::SmolStr; pub use wasi_http::WasiHttpExecutorImpl; use wasmtime_wasi::StdoutStream; +use wasmtime_wasi_http::body::HyperOutgoingBody; pub(crate) static X_REAL_IP: &str = "x-real-ip"; pub(crate) static TRACEPARENT: &str = "traceparent"; @@ -30,7 +30,7 @@ pub trait HttpExecutor { async fn execute( &self, req: hyper::Request, - ) -> Result<(Response>, Duration, ByteSize)> + ) -> Result<(hyper::Response, Duration, ByteSize)> where B: BodyExt + Send, ::Data: Send; @@ -65,7 +65,7 @@ where async fn execute( &self, req: hyper::Request, - ) -> Result<(Response>, Duration, ByteSize)> + ) -> Result<(hyper::Response, Duration, ByteSize)> where B: BodyExt + Send, ::Data: Send, @@ -101,7 +101,7 @@ where async fn execute_impl( &self, req: hyper::Request, - ) -> Result<(Response>, ByteSize)> + ) -> Result<(hyper::Response, ByteSize)> where B: BodyExt + Send, ::Data: Send, diff --git a/crates/http-service/src/executor/wasi_http.rs b/crates/http-service/src/executor/wasi_http.rs index b13bc15..d89050f 100644 --- a/crates/http-service/src/executor/wasi_http.rs +++ b/crates/http-service/src/executor/wasi_http.rs @@ -8,16 +8,15 @@ use async_trait::async_trait; use bytesize::ByteSize; use dictionary::Dictionary; use http::uri::Scheme; -use http::{header, HeaderMap, Response, Uri}; +use http::{header, HeaderMap, Uri}; use http_backend::Backend; -use http_body_util::combinators::BoxBody; use http_body_util::{BodyExt, Full}; -use hyper::body::{Body, Bytes}; +use hyper::body::{Body}; use runtime::store::StoreBuilder; use runtime::InstancePre; use secret::{Secret, SecretStrategy}; use smol_str::ToSmolStr; -use tracing::error; +use wasmtime_wasi_http::body::HyperOutgoingBody; use wasmtime_wasi_http::WasiHttpView; /// Execute context used by ['HttpService'] @@ -39,7 +38,7 @@ where async fn execute( &self, req: hyper::Request, - ) -> anyhow::Result<(Response>, Duration, ByteSize)> + ) -> anyhow::Result<(hyper::Response, Duration, ByteSize)> where B: BodyExt + Send, ::Data: Send, @@ -75,7 +74,7 @@ where async fn execute_impl( &self, req: hyper::Request, - ) -> anyhow::Result<(Response>, ByteSize)> + ) -> anyhow::Result<(hyper::Response, ByteSize)> where B: BodyExt, { @@ -98,6 +97,7 @@ where parts.uri = Uri::from_parts(uparts)?; } + //FIXME send streamed request body let body = body .collect() .await @@ -147,24 +147,27 @@ where let mut store = store_builder.build(state).context("store build")?; let instance_pre = self.instance_pre.clone(); - let task = tokio::task::spawn(async move { - let request = hyper::Request::from_parts(parts, body); - let req = store - .data_mut() - .new_incoming_request(request) - .context("new incoming request")?; - let out = store - .data_mut() - .new_response_outparam(sender) - .context("new response outparam")?; - - let (proxy, _inst) = wasmtime_wasi_http::proxy::Proxy::instantiate_pre( - &mut store, - instance_pre.as_ref(), - ) + let request = hyper::Request::from_parts(parts, body); + let req = store + .data_mut() + .new_incoming_request(request) + .context("new incoming request")?; + let out = store + .data_mut() + .new_response_outparam(sender) + .context("new response outparam")?; + + let (proxy, _inst) = wasmtime_wasi_http::proxy::Proxy::instantiate_pre( + &mut store, + instance_pre.as_ref(), + ) .await?; - let duration = Duration::from_millis(store.data().timeout); + let duration = Duration::from_millis(store.data().timeout); + + let task = tokio::task::spawn(async move { + + tokio::time::sleep(Duration::from_millis(100)).await; if let Err(e) = tokio::time::timeout( duration, proxy @@ -173,7 +176,7 @@ where ) .await? { - error!(cause=?e, "incoming handler"); + tracing::warn!(cause=?e, "incoming handler"); return Err(e); }; let used = ByteSize::b(store.memory_used() as u64); @@ -182,11 +185,18 @@ where match receiver.await { Ok(Ok(resp)) => { + println!("############################################## receiver response: {:?}", resp); + let used = ByteSize::b(0 as u64); + Ok((resp ,used)) + }, + /*Ok(Ok(resp)) => { + tracing::info!("############################################## resp"); let (parts, body) = resp.into_parts(); let body = body.map_err(anyhow::Error::msg).boxed(); - let used = task.await.context("task await")?.context("byte size")?; + //let used = task.await.context("task await")?.context("byte size")?; + let used = ByteSize::b(0 as u64); Ok((Response::from_parts(parts, body), used)) - } + }*/ Ok(Err(e)) => Err(e.into()), Err(_) => { let e = match task.await { diff --git a/crates/http-service/src/lib.rs b/crates/http-service/src/lib.rs index 7661363..89cf3ee 100644 --- a/crates/http-service/src/lib.rs +++ b/crates/http-service/src/lib.rs @@ -8,8 +8,7 @@ use crate::executor::HttpExecutor; use anyhow::{bail, Result}; use bytes::Bytes; use http::header::{ACCESS_CONTROL_ALLOW_ORIGIN, CACHE_CONTROL}; -use http::{HeaderMap, HeaderName, HeaderValue, Request, Response, StatusCode}; -use http_body_util::combinators::BoxBody; +use http::{HeaderMap, HeaderName, HeaderValue, StatusCode}; use http_body_util::{BodyExt, Empty, Full}; use hyper::body::Body; use hyper::server::conn::http1; @@ -34,6 +33,7 @@ use tokio::time::error::Elapsed; use tracing::Instrument; use wasi_common::I32Exit; use wasmtime::Trap; +pub use wasmtime_wasi_http::body::HyperOutgoingBody; pub mod executor; pub mod state; @@ -185,7 +185,7 @@ where .await } }); - if let Err(error) = http1::Builder::new().serve_connection(io, service).await { + if let Err(error) = http1::Builder::new().keep_alive(true).serve_connection(io, service).await { tracing::warn!(cause=?error, "Error serving connection"); } } @@ -194,8 +194,8 @@ where async fn handle_request( &self, request_id: &str, - mut request: Request, - ) -> Result>> + mut request: hyper::Request, + ) -> Result> where B: BodyExt + Send, ::Data: Send, @@ -425,7 +425,7 @@ where None, ); - let builder = Response::builder().status(status_code); + let builder = hyper::Response::builder().status(status_code); let res_headers = app_res_headers(cfg); let builder = res_headers .iter() @@ -438,7 +438,7 @@ where } } -fn remote_traceparent(req: &Request) -> String { +fn remote_traceparent(req: &hyper::Request) -> String { req.headers() .get(TRACEPARENT) .and_then(|v| v.to_str().ok()) @@ -447,8 +447,8 @@ fn remote_traceparent(req: &Request) -> String { } /// Creates an HTTP 500 response. -fn internal_fastedge_error(msg: &'static str) -> Result>> { - Ok(Response::builder().status(FASTEDGE_INTERNAL_ERROR).body( +fn internal_fastedge_error(msg: &'static str) -> Result> { + Ok(hyper::Response::builder().status(FASTEDGE_INTERNAL_ERROR).body( Full::new(Bytes::from(format!("fastedge: {}", msg))) .map_err(|never| match never {}) .boxed(), @@ -456,8 +456,8 @@ fn internal_fastedge_error(msg: &'static str) -> Result Result>> { - Ok(Response::builder().status(StatusCode::NOT_FOUND).body( +fn not_found() -> Result> { + Ok(hyper::Response::builder().status(StatusCode::NOT_FOUND).body( Full::new(Bytes::from("fastedge: Unknown app")) .map_err(|never| match never {}) .boxed(), @@ -465,15 +465,15 @@ fn not_found() -> Result>> { } /// Creates an HTTP 429 response. -fn too_many_requests() -> Result>> { - Ok(Response::builder() +fn too_many_requests() -> Result> { + Ok(hyper::Response::builder() .status(StatusCode::TOO_MANY_REQUESTS) .body(Empty::new().map_err(|never| match never {}).boxed())?) } /// Creates an HTTP 406 response. -fn not_acceptable() -> Result>> { - Ok(Response::builder() +fn not_acceptable() -> Result> { + Ok(hyper::Response::builder() .status(StatusCode::NOT_ACCEPTABLE) .body(Empty::new().map_err(|never| match never {}).boxed())?) } @@ -481,7 +481,7 @@ fn not_acceptable() -> Result>> { /// borrows the request and returns the apps name /// app name can be either as sub-domain in a format '.' (from `Server_name` header) /// or '/' (from URL) -fn app_name_from_request(req: &Request) -> Result { +fn app_name_from_request(req: &hyper::Request) -> Result { match req.headers().get("server_name") { None => {} Some(h) => { diff --git a/crates/secret/Cargo.toml b/crates/secret/Cargo.toml index 9295b54..5eee760 100644 --- a/crates/secret/Cargo.toml +++ b/crates/secret/Cargo.toml @@ -8,7 +8,6 @@ description = "secret host function" [dependencies] reactor = { path = "../reactor" } -runtime = { path = "../runtime" } anyhow = {workspace = true} tracing = {workspace = true} async-trait = {workspace = true} diff --git a/src/main.rs b/src/main.rs index 1383668..676bed7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,16 +6,14 @@ use async_trait::async_trait; use bytesize::{ByteSize, MB}; use clap::{Args, Parser, Subcommand}; use dictionary::Dictionary; -use http::{Request, Response}; use http_backend::{Backend, BackendStrategy}; -use http_body_util::combinators::BoxBody; use http_body_util::BodyExt; use http_service::executor::{ ExecutorFactory, HttpExecutor, HttpExecutorImpl, WasiHttpExecutorImpl, }; use http_service::state::HttpState; -use http_service::{ContextHeaders, HttpConfig, HttpService}; -use hyper::body::{Body, Bytes}; +use http_service::{ContextHeaders, HttpConfig, HttpService, HyperOutgoingBody}; +use hyper::body::{Body}; use hyper_tls::HttpsConnector; use hyper_util::client::legacy::connect::HttpConnector; use runtime::app::Status; @@ -235,8 +233,8 @@ enum CliExecutor { impl HttpExecutor for CliExecutor { async fn execute( &self, - req: Request, - ) -> anyhow::Result<(Response>, Duration, ByteSize)> + req: hyper::Request, + ) -> anyhow::Result<(hyper::Response, Duration, ByteSize)> where B: BodyExt + Send, ::Data: Send, From 0aa2fd9ba54adcda0cf0892f264ed72ece74ea53 Mon Sep 17 00:00:00 2001 From: Ruslan Pislari Date: Fri, 22 Nov 2024 16:07:13 +0200 Subject: [PATCH 2/3] fix: adding on_response handler to process the end of body chunks --- crates/http-service/src/executor/http.rs | 182 +++++++++++ crates/http-service/src/executor/mod.rs | 201 +------------ crates/http-service/src/executor/wasi_http.rs | 113 +++---- crates/http-service/src/lib.rs | 283 +++++++++++------- src/main.rs | 16 +- 5 files changed, 420 insertions(+), 375 deletions(-) create mode 100644 crates/http-service/src/executor/http.rs diff --git a/crates/http-service/src/executor/http.rs b/crates/http-service/src/executor/http.rs new file mode 100644 index 0000000..a0bb5d8 --- /dev/null +++ b/crates/http-service/src/executor/http.rs @@ -0,0 +1,182 @@ +use crate::executor; +use crate::executor::HttpExecutor; +use crate::state::HttpState; +use anyhow::{anyhow, bail, Context}; +use async_trait::async_trait; +use bytesize::ByteSize; +use dictionary::Dictionary; +use http::{Method, Request, Response, StatusCode}; +use http_backend::Backend; +use http_body_util::{BodyExt, Full}; +use hyper::body::Body; +use reactor::gcore::fastedge; +use runtime::{store::StoreBuilder, InstancePre}; +use secret::{Secret, SecretStrategy}; +use std::time::{Duration, Instant}; +use wasmtime_wasi::StdoutStream; +use wasmtime_wasi_http::body::HyperOutgoingBody; + +/// Execute context used by ['HttpService'] +#[derive(Clone)] +pub struct HttpExecutorImpl { + instance_pre: InstancePre>, + store_builder: StoreBuilder, + backend: Backend, + dictionary: Dictionary, + secret: Secret, +} + +#[async_trait] +impl HttpExecutor for HttpExecutorImpl +where + C: Clone + Send + Sync + 'static, + T: SecretStrategy + Clone + Send + Sync, +{ + async fn execute( + &self, + req: Request, + on_response: R, + ) -> anyhow::Result> + where + R: FnOnce(StatusCode, ByteSize, Duration) + Send + 'static, + B: BodyExt + Send, + ::Data: Send, + { + tracing::trace!("start execute"); + let start_ = Instant::now(); + + let (parts, body) = req.into_parts(); + let method = to_fastedge_http_method(&parts.method)?; + + let headers = parts + .headers + .iter() + .filter_map(|(name, value)| { + value + .to_str() + .map(|v| (name.to_string(), v.to_string())) + .ok() + }) + .collect::>(); + + let body = body + .collect() + .await + .map_err(|_| anyhow!("body read error"))? + .to_bytes(); + let body = if body.is_empty() { + None + } else { + Some(body.to_vec()) + }; + + let request = fastedge::http::Request { + method, + uri: parts.uri.to_string(), + headers, + body, + }; + + let properties = executor::get_properties(&parts.headers); + + let store_builder = self.store_builder.to_owned().with_properties(properties); + let wasi_nn = self.store_builder.make_wasi_nn_ctx()?; + let mut http_backend = self.backend.to_owned(); + + http_backend + .propagate_headers(parts.headers.clone()) + .context("propagate headers")?; + + let propagate_header_names = http_backend.propagate_header_names(); + let backend_uri = http_backend.uri(); + let state = HttpState { + wasi_nn, + http_backend, + uri: backend_uri, + propagate_headers: parts.headers, + propagate_header_names, + dictionary: self.dictionary.clone(), + secret: self.secret.clone(), + }; + + let mut store = store_builder.build(state)?; + + let instance = self.instance_pre.instantiate_async(&mut store).await?; + let func = instance + .exports(&mut store) + .instance("gcore:fastedge/http-handler") + .ok_or_else(|| anyhow!("gcore:fastedge/http-handler instance not found"))? + .typed_func::<(fastedge::http::Request,), (fastedge::http::Response,)>("process")?; + let duration = Duration::from_millis(store.data().timeout); + let func = tokio::time::timeout(duration, func.call_async(&mut store, (request,))); + let (resp,) = match func.await? { + Ok(res) => res, + Err(error) => { + // log to application logger error + if let Some(ref logger) = store.data().logger { + if let Err(e) = logger.stream().write(error.to_string().into()) { + tracing::debug!(cause=?e, "write error: {}", error) + } + } + return Err(error); + } + }; + let status_code = ::http::StatusCode::try_from(resp.status)?; + let builder = ::http::Response::builder().status(status_code); + let builder = if let Some(headers) = resp.headers { + headers + .iter() + .fold(builder, |builder, (k, v)| builder.header(k, v)) + } else { + builder + }; + + let elapsed = Instant::now().duration_since(start_); + on_response( + status_code, + ByteSize::b(store.memory_used() as u64), + elapsed, + ); + + let body = resp + .body + .map(|b| Full::from(b).map_err(|never| match never {}).boxed()) + .unwrap_or_default(); + builder.body(body).map_err(anyhow::Error::msg) + } +} + +impl HttpExecutorImpl +where + C: Clone + Send + Sync + 'static, + T: SecretStrategy + Clone + Send, +{ + pub fn new( + instance_pre: InstancePre>, + store_builder: StoreBuilder, + backend: Backend, + dictionary: Dictionary, + secret: Secret, + ) -> Self { + Self { + instance_pre, + store_builder, + backend, + dictionary, + secret, + } + } +} + +fn to_fastedge_http_method(method: &Method) -> anyhow::Result { + Ok(match method { + &Method::GET => fastedge::http::Method::Get, + &Method::POST => fastedge::http::Method::Post, + &Method::PUT => fastedge::http::Method::Put, + &Method::DELETE => fastedge::http::Method::Delete, + &Method::HEAD => fastedge::http::Method::Head, + &Method::PATCH => fastedge::http::Method::Patch, + &Method::OPTIONS => fastedge::http::Method::Options, + method => bail!("unsupported method: {}", method), + }) +} diff --git a/crates/http-service/src/executor/mod.rs b/crates/http-service/src/executor/mod.rs index 8df05b1..ed46490 100644 --- a/crates/http-service/src/executor/mod.rs +++ b/crates/http-service/src/executor/mod.rs @@ -1,37 +1,35 @@ +mod http; mod wasi_http; use std::collections::HashMap; -use std::time::{Duration, Instant}; +use std::time::Duration; -use crate::state::HttpState; -use anyhow::{anyhow, bail, Context, Result}; +use ::http::{HeaderMap, HeaderValue, StatusCode}; +use anyhow::Result; use async_trait::async_trait; use bytesize::ByteSize; -use dictionary::Dictionary; -use http::{HeaderMap, HeaderValue, Method}; -use http_backend::Backend; -use http_body_util::{BodyExt, Full}; -use hyper::body::{Body}; -use reactor::gcore::fastedge; -use runtime::store::StoreBuilder; -use runtime::{App, InstancePre, WasmEngine}; -use secret::{Secret, SecretStrategy}; +use http_body_util::BodyExt; +use hyper::body::Body; +use runtime::{App, WasmEngine}; use smol_str::SmolStr; -pub use wasi_http::WasiHttpExecutorImpl; -use wasmtime_wasi::StdoutStream; use wasmtime_wasi_http::body::HyperOutgoingBody; +pub use http::HttpExecutorImpl; +pub use wasi_http::WasiHttpExecutorImpl; + pub(crate) static X_REAL_IP: &str = "x-real-ip"; pub(crate) static TRACEPARENT: &str = "traceparent"; pub(crate) static X_CDN_REQUESTOR: &str = "x-cdn-requestor"; #[async_trait] pub trait HttpExecutor { - async fn execute( + async fn execute( &self, req: hyper::Request, - ) -> Result<(hyper::Response, Duration, ByteSize)> + on_response: R, + ) -> Result> where + R: FnOnce(StatusCode, ByteSize, Duration) + Send + 'static, B: BodyExt + Send, ::Data: Send; } @@ -46,177 +44,6 @@ pub trait ExecutorFactory { ) -> Result; } -/// Execute context used by ['HttpService'] -#[derive(Clone)] -pub struct HttpExecutorImpl { - instance_pre: InstancePre>, - store_builder: StoreBuilder, - backend: Backend, - dictionary: Dictionary, - secret: Secret, -} - -#[async_trait] -impl HttpExecutor for HttpExecutorImpl -where - C: Clone + Send + Sync + 'static, - T: SecretStrategy + Clone + Send + Sync, -{ - async fn execute( - &self, - req: hyper::Request, - ) -> Result<(hyper::Response, Duration, ByteSize)> - where - B: BodyExt + Send, - ::Data: Send, - { - let start_ = Instant::now(); - let response = self.execute_impl(req).await; - let elapsed = Instant::now().duration_since(start_); - response.map(|(r, used)| (r, elapsed, used)) - } -} - -impl HttpExecutorImpl -where - C: Clone + Send + Sync + 'static, - T: SecretStrategy + Clone + Send, -{ - pub fn new( - instance_pre: InstancePre>, - store_builder: StoreBuilder, - backend: Backend, - dictionary: Dictionary, - secret: Secret, - ) -> Self { - Self { - instance_pre, - store_builder, - backend, - dictionary, - secret, - } - } - - async fn execute_impl( - &self, - req: hyper::Request, - ) -> Result<(hyper::Response, ByteSize)> - where - B: BodyExt + Send, - ::Data: Send, - { - let (parts, body) = req.into_parts(); - let method = to_fastedge_http_method(&parts.method)?; - - let headers = parts - .headers - .iter() - .filter_map(|(name, value)| { - value - .to_str() - .map(|v| (name.to_string(), v.to_string())) - .ok() - }) - .collect::>(); - - let body = body - .collect() - .await - .map_err(|_| anyhow!("body read error"))? - .to_bytes(); - let body = if body.is_empty() { - None - } else { - Some(body.to_vec()) - }; - - let request = fastedge::http::Request { - method, - uri: parts.uri.to_string(), - headers, - body, - }; - - let properties = get_properties(&parts.headers); - - let store_builder = self.store_builder.to_owned().with_properties(properties); - let wasi_nn = self.store_builder.make_wasi_nn_ctx()?; - let mut http_backend = self.backend.to_owned(); - - http_backend - .propagate_headers(parts.headers.clone()) - .context("propagate headers")?; - - let propagate_header_names = http_backend.propagate_header_names(); - let backend_uri = http_backend.uri(); - let state = HttpState { - wasi_nn, - http_backend, - uri: backend_uri, - propagate_headers: parts.headers, - propagate_header_names, - dictionary: self.dictionary.clone(), - secret: self.secret.clone(), - }; - - let mut store = store_builder.build(state)?; - - let instance = self.instance_pre.instantiate_async(&mut store).await?; - let func = instance - .exports(&mut store) - .instance("gcore:fastedge/http-handler") - .ok_or_else(|| anyhow!("gcore:fastedge/http-handler instance not found"))? - .typed_func::<(fastedge::http::Request,), (fastedge::http::Response,)>("process")?; - let duration = Duration::from_millis(store.data().timeout); - let func = tokio::time::timeout(duration, func.call_async(&mut store, (request,))); - let (resp,) = match func.await? { - Ok(res) => res, - Err(error) => { - // log to application logger error - if let Some(ref logger) = store.data().logger { - if let Err(e) = logger.stream().write(error.to_string().into()) { - tracing::debug!(cause=?e, "write error: {}", error) - } - } - return Err(error); - } - }; - let builder = - ::http::Response::builder().status(::http::StatusCode::try_from(resp.status)?); - let builder = if let Some(headers) = resp.headers { - headers - .iter() - .fold(builder, |builder, (k, v)| builder.header(k, v)) - } else { - builder - }; - let used = ByteSize::b(store.memory_used() as u64); - - let body = resp - .body - .map(|b| Full::from(b).map_err(|never| match never {}).boxed()) - .unwrap_or_default(); - builder - .body(body) - .map(|r| (r, used)) - .map_err(anyhow::Error::msg) - } -} - -fn to_fastedge_http_method(method: &Method) -> Result { - Ok(match method { - &Method::GET => fastedge::http::Method::Get, - &Method::POST => fastedge::http::Method::Post, - &Method::PUT => fastedge::http::Method::Put, - &Method::DELETE => fastedge::http::Method::Delete, - &Method::HEAD => fastedge::http::Method::Head, - &Method::PATCH => fastedge::http::Method::Patch, - &Method::OPTIONS => fastedge::http::Method::Options, - method => bail!("unsupported method: {}", method), - }) -} - pub(crate) fn get_properties(headers: &HeaderMap) -> HashMap { let mut properties = HashMap::new(); if let Some(client_ip) = headers.get(X_REAL_IP).and_then(|v| v.to_str().ok()) { diff --git a/crates/http-service/src/executor/wasi_http.rs b/crates/http-service/src/executor/wasi_http.rs index d89050f..20aeac7 100644 --- a/crates/http-service/src/executor/wasi_http.rs +++ b/crates/http-service/src/executor/wasi_http.rs @@ -1,23 +1,19 @@ use std::time::{Duration, Instant}; -use crate::executor; use crate::executor::HttpExecutor; use crate::state::HttpState; +use ::http::{header, uri::Scheme, HeaderMap, Request, Response, StatusCode, Uri}; use anyhow::{anyhow, bail, Context}; use async_trait::async_trait; use bytesize::ByteSize; use dictionary::Dictionary; -use http::uri::Scheme; -use http::{header, HeaderMap, Uri}; use http_backend::Backend; use http_body_util::{BodyExt, Full}; -use hyper::body::{Body}; -use runtime::store::StoreBuilder; -use runtime::InstancePre; +use hyper::body::Body; +use runtime::{store::StoreBuilder, InstancePre}; use secret::{Secret, SecretStrategy}; use smol_str::ToSmolStr; -use wasmtime_wasi_http::body::HyperOutgoingBody; -use wasmtime_wasi_http::WasiHttpView; +use wasmtime_wasi_http::{body::HyperOutgoingBody, WasiHttpView}; /// Execute context used by ['HttpService'] #[derive(Clone)] @@ -35,49 +31,19 @@ where C: Clone + Send + Sync + 'static, T: SecretStrategy + Clone + Send + Sync + 'static, { - async fn execute( + async fn execute( &self, - req: hyper::Request, - ) -> anyhow::Result<(hyper::Response, Duration, ByteSize)> + req: Request, + on_response: R, + ) -> anyhow::Result> where + R: FnOnce(StatusCode, ByteSize, Duration) + Send + 'static, B: BodyExt + Send, ::Data: Send, { + tracing::trace!("start execute"); let start_ = Instant::now(); - let response = self.execute_impl(req).await; - let elapsed = Instant::now().duration_since(start_); - response.map(|(r, used)| (r, elapsed, used)) - } -} -impl WasiHttpExecutorImpl -where - C: Clone + Send + Sync + 'static, - T: SecretStrategy + Clone + Send + 'static, -{ - pub fn new( - instance_pre: InstancePre>, - store_builder: StoreBuilder, - backend: Backend, - dictionary: Dictionary, - secret: Secret, - ) -> Self { - Self { - instance_pre, - store_builder, - backend, - dictionary, - secret, - } - } - - async fn execute_impl( - &self, - req: hyper::Request, - ) -> anyhow::Result<(hyper::Response, ByteSize)> - where - B: BodyExt, - { let (sender, receiver) = tokio::sync::oneshot::channel(); let (mut parts, body) = req.into_parts(); @@ -106,7 +72,7 @@ where let body = Full::new(body).map_err(|never| match never {}); let body = body.boxed(); - let properties = executor::get_properties(&parts.headers); + let properties = crate::executor::get_properties(&parts.headers); let store_builder = self.store_builder.to_owned().with_properties(properties); let wasi_nn = self .store_builder @@ -157,17 +123,13 @@ where .new_response_outparam(sender) .context("new response outparam")?; - let (proxy, _inst) = wasmtime_wasi_http::proxy::Proxy::instantiate_pre( - &mut store, - instance_pre.as_ref(), - ) - .await?; + let (proxy, _inst) = + wasmtime_wasi_http::proxy::Proxy::instantiate_pre(&mut store, instance_pre.as_ref()) + .await?; let duration = Duration::from_millis(store.data().timeout); - - let task = tokio::task::spawn(async move { - tokio::time::sleep(Duration::from_millis(100)).await; + let task = tokio::task::spawn(async move { if let Err(e) = tokio::time::timeout( duration, proxy @@ -179,24 +141,17 @@ where tracing::warn!(cause=?e, "incoming handler"); return Err(e); }; - let used = ByteSize::b(store.memory_used() as u64); - Ok(used) + let elapsed = Instant::now().duration_since(start_); + on_response( + StatusCode::default(), + ByteSize::b(store.memory_used() as u64), + elapsed, + ); + Ok(()) }); match receiver.await { - Ok(Ok(resp)) => { - println!("############################################## receiver response: {:?}", resp); - let used = ByteSize::b(0 as u64); - Ok((resp ,used)) - }, - /*Ok(Ok(resp)) => { - tracing::info!("############################################## resp"); - let (parts, body) = resp.into_parts(); - let body = body.map_err(anyhow::Error::msg).boxed(); - //let used = task.await.context("task await")?.context("byte size")?; - let used = ByteSize::b(0 as u64); - Ok((Response::from_parts(parts, body), used)) - }*/ + Ok(Ok(response)) => Ok(response), Ok(Err(e)) => Err(e.into()), Err(_) => { let e = match task.await { @@ -211,6 +166,28 @@ where } } +impl WasiHttpExecutorImpl +where + C: Clone + Send + Sync + 'static, + T: SecretStrategy + Clone + Send + 'static, +{ + pub fn new( + instance_pre: InstancePre>, + store_builder: StoreBuilder, + backend: Backend, + dictionary: Dictionary, + secret: Secret, + ) -> Self { + Self { + instance_pre, + store_builder, + backend, + dictionary, + secret, + } + } +} + fn be_base_domain(server_name: &str) -> String { let base_domain = match server_name.find('.') { None => server_name, diff --git a/crates/http-service/src/lib.rs b/crates/http-service/src/lib.rs index 89cf3ee..4e59b5a 100644 --- a/crates/http-service/src/lib.rs +++ b/crates/http-service/src/lib.rs @@ -5,34 +5,33 @@ use std::time::Duration; pub use crate::executor::ExecutorFactory; use crate::executor::HttpExecutor; -use anyhow::{bail, Result}; +use anyhow::{bail, Error, Result}; use bytes::Bytes; -use http::header::{ACCESS_CONTROL_ALLOW_ORIGIN, CACHE_CONTROL}; -use http::{HeaderMap, HeaderName, HeaderValue, StatusCode}; +use bytesize::ByteSize; +use http::{ + header::{ACCESS_CONTROL_ALLOW_ORIGIN, CACHE_CONTROL}, + HeaderMap, HeaderName, HeaderValue, StatusCode, +}; use http_body_util::{BodyExt, Empty, Full}; -use hyper::body::Body; -use hyper::server::conn::http1; -use hyper::service::service_fn; -use hyper_util::client::legacy::connect::Connect; -use hyper_util::rt::TokioIo; -use runtime::app::Status; -use runtime::service::Service; +use hyper::{body::Body, server::conn::http1, service::service_fn}; +use hyper_util::{client::legacy::connect::Connect, rt::TokioIo}; #[cfg(feature = "metrics")] use runtime::util::metrics; #[cfg(feature = "stats")] use runtime::util::stats::StatRow; -use runtime::util::stats::StatsWriter; -use runtime::{App, AppResult, ContextT, Router, WasmEngine, WasmEngineBuilder}; +use runtime::{ + app::Status, service::Service, util::stats::StatsWriter, App, AppResult, ContextT, Router, + WasmEngine, WasmEngineBuilder, +}; use secret::SecretStrategy; use shellflip::ShutdownHandle; use smol_str::SmolStr; use state::HttpState; -use tokio::io::{AsyncRead, AsyncWrite}; -use tokio::net::TcpListener; -use tokio::time::error::Elapsed; -use tracing::Instrument; -use wasi_common::I32Exit; -use wasmtime::Trap; +use tokio::{ + io::{AsyncRead, AsyncWrite}, + net::TcpListener, + time::error::Elapsed, +}; pub use wasmtime_wasi_http::body::HyperOutgoingBody; pub mod executor; @@ -73,6 +72,7 @@ where + Router + ContextHeaders + ExecutorFactory> + + Clone + Sync + Send + 'static, @@ -110,13 +110,13 @@ where loop { match listener.accept().await { Ok((stream, _)) => { - tracing::trace!("new http connection"); + tracing::debug!(remote=?stream.peer_addr(), "new http connection"); let connection = self_.clone(); if let Some(cancel) = config.cancel.upgrade() { tokio::spawn(connection.serve(stream, cancel)); backoff = 1; } else { - tracing::debug!("weak cancel handler"); + tracing::trace!("weak cancel handler"); backoff *= 2; } } @@ -164,7 +164,8 @@ where + ExecutorFactory> + Sync + Send - + 'static, + + 'static + + Clone, T::BackendConnector: Clone + Send + Sync + 'static, T::Executor: HttpExecutor + Send + Sync, U: SecretStrategy, @@ -173,6 +174,7 @@ where where S: AsyncRead + AsyncWrite + Unpin, { + use tracing::Instrument; let io = TokioIo::new(stream); let service = service_fn(move |req| { @@ -181,18 +183,22 @@ where async move { self_ .handle_request(&request_id, req) - .instrument(tracing::info_span!("http_handler", request_id)) + .instrument(tracing::debug_span!("http", request_id)) .await } }); - if let Err(error) = http1::Builder::new().keep_alive(true).serve_connection(io, service).await { + if let Err(error) = http1::Builder::new() + .keep_alive(true) + .serve_connection(io, service) + .await + { tracing::warn!(cause=?error, "Error serving connection"); } } /// handle HTTP request. async fn handle_request( - &self, + self: Arc, request_id: &str, mut request: hyper::Request, ) -> Result> @@ -280,116 +286,90 @@ where } }; + /* + Channel to receive http status code for asynchronious response processing of WASI-HTTP. + */ + let (status_code_tx, mut status_code_rx) = tokio::sync::oneshot::channel(); let start_ = std::time::Instant::now(); - let response = match executor.execute(request).await { - Ok((mut response, time_elapsed, memory_used)) => { + let response_handler = { + let app_name = app_name.to_string(); + #[cfg(feature = "stats")] + let billing_plan = cfg.plan.to_string(); + #[cfg(feature = "stats")] + let request_id = request_id.to_string(); + #[cfg(feature = "stats")] + let context = self.context.clone(); + + move |status_code: StatusCode, mem_used: ByteSize, time_elapsed: Duration| { + tracing::trace!(?status_code, ?mem_used, ?time_elapsed, "response handler"); + /* + Used by WASI-HTTP to send status code prior response processing. + If there is no status code then default value is returned. + For synchronious HTTP processing the status_code parameter is set and no value in the channel. + */ + let status_code = status_code_rx.try_recv().unwrap_or_else(|error| { + tracing::trace!(cause=?error, "unknown status code"); + status_code + }); tracing::info!( "'{}' completed with status code: '{}' in {:.0?} using {} of WebAssembly heap", app_name, - response.status(), + status_code, time_elapsed, - memory_used + mem_used ); - #[cfg(feature = "stats")] { let stat_row = StatRow { app_id: cfg.app_id, client_id: cfg.client_id, timestamp: timestamp as u32, - app_name: app_name.to_string(), - status_code: response.status().as_u16() as u32, + app_name, + status_code: status_code.as_u16() as u32, fail_reason: 0, // TODO: use AppResult - billing_plan: cfg.plan.to_string(), + billing_plan, time_elapsed: time_elapsed.as_micros() as u64, - memory_used: memory_used.as_u64(), - request_id: request_id.to_string(), + memory_used: mem_used.as_u64(), + request_id, ..Default::default() }; - self.context.write_stats(stat_row); + context.write_stats(stat_row); } #[cfg(feature = "metrics")] metrics::metrics( AppResult::SUCCESS, &["http"], Some(time_elapsed.as_micros() as u64), - Some(memory_used.as_u64()), + Some(mem_used.as_u64()), ); + } + }; + + let response = match executor.execute(request, response_handler).await { + Ok(mut response) => { + /* + Status code sender is closed if response handler processing was done. + */ + if !status_code_tx.is_closed() { + if let Err(error) = status_code_tx.send(response.status()) { + tracing::warn!(cause=?error, "sending status code") + } + tracing::info!( + "'{}' returned status code: '{}'", + app_name, + response.status(), + ); + } response.headers_mut().extend(app_res_headers(cfg)); response } Err(error) => { tracing::warn!(cause=?error, "execute"); - let root_cause = error.root_cause(); let time_elapsed = std::time::Instant::now().duration_since(start_); - let (status_code, fail_reason, msg) = - if let Some(exit) = root_cause.downcast_ref::() { - if exit.0 == 0 { - ( - StatusCode::OK.as_u16(), - AppResult::SUCCESS, - Empty::new().map_err(|never| match never {}).boxed(), - ) - } else { - ( - FASTEDGE_EXECUTION_PANIC, - AppResult::OTHER, - Full::new(Bytes::from("fastedge: App failed")) - .map_err(|never| match never {}) - .boxed(), - ) - } - } else if let Some(trap) = root_cause.downcast_ref::() { - match trap { - Trap::Interrupt => ( - FASTEDGE_EXECUTION_TIMEOUT, - AppResult::TIMEOUT, - Full::new(Bytes::from("fastedge: Execution timeout")) - .map_err(|never| match never {}) - .boxed(), - ), - Trap::UnreachableCodeReached => ( - FASTEDGE_OUT_OF_MEMORY, - AppResult::OOM, - Full::new(Bytes::from("fastedge: Out of memory")) - .map_err(|never| match never {}) - .boxed(), - ), - _ => ( - FASTEDGE_EXECUTION_PANIC, - AppResult::OTHER, - Full::new(Bytes::from("fastedge: App failed")) - .map_err(|never| match never {}) - .boxed(), - ), - } - } else if let Some(_elapsed) = root_cause.downcast_ref::() { - ( - FASTEDGE_EXECUTION_TIMEOUT, - AppResult::TIMEOUT, - Full::new(Bytes::from("fastedge: Execution timeout")) - .map_err(|never| match never {}) - .boxed(), - ) - } else if root_cause.to_string().ends_with("deadline has elapsed") { - ( - FASTEDGE_EXECUTION_TIMEOUT, - AppResult::TIMEOUT, - Full::new(Bytes::from("fastedge: Execution timeout")) - .map_err(|never| match never {}) - .boxed(), - ) - } else { - ( - FASTEDGE_INTERNAL_ERROR, - AppResult::OTHER, - Full::new(Bytes::from("fastedge: Execute error")) - .map_err(|never| match never {}) - .boxed(), - ) - }; + + let (status_code, fail_reason, msg) = map_err(error); tracing::info!( "'{}' failed with status code: '{}' in {:.0?}", app_name, @@ -438,6 +418,77 @@ where } } +fn map_err(error: Error) -> (u16, AppResult, HyperOutgoingBody) { + let root_cause = error.root_cause(); + let (status_code, fail_reason, msg) = + if let Some(exit) = root_cause.downcast_ref::() { + if exit.0 == 0 { + ( + StatusCode::OK.as_u16(), + AppResult::SUCCESS, + Empty::new().map_err(|never| match never {}).boxed(), + ) + } else { + ( + FASTEDGE_EXECUTION_PANIC, + AppResult::OTHER, + Full::new(Bytes::from("fastedge: App failed")) + .map_err(|never| match never {}) + .boxed(), + ) + } + } else if let Some(trap) = root_cause.downcast_ref::() { + match trap { + wasmtime::Trap::Interrupt => ( + FASTEDGE_EXECUTION_TIMEOUT, + AppResult::TIMEOUT, + Full::new(Bytes::from("fastedge: Execution timeout")) + .map_err(|never| match never {}) + .boxed(), + ), + wasmtime::Trap::UnreachableCodeReached => ( + FASTEDGE_OUT_OF_MEMORY, + AppResult::OOM, + Full::new(Bytes::from("fastedge: Out of memory")) + .map_err(|never| match never {}) + .boxed(), + ), + _ => ( + FASTEDGE_EXECUTION_PANIC, + AppResult::OTHER, + Full::new(Bytes::from("fastedge: App failed")) + .map_err(|never| match never {}) + .boxed(), + ), + } + } else if let Some(_elapsed) = root_cause.downcast_ref::() { + ( + FASTEDGE_EXECUTION_TIMEOUT, + AppResult::TIMEOUT, + Full::new(Bytes::from("fastedge: Execution timeout")) + .map_err(|never| match never {}) + .boxed(), + ) + } else if root_cause.to_string().ends_with("deadline has elapsed") { + ( + FASTEDGE_EXECUTION_TIMEOUT, + AppResult::TIMEOUT, + Full::new(Bytes::from("fastedge: Execution timeout")) + .map_err(|never| match never {}) + .boxed(), + ) + } else { + ( + FASTEDGE_INTERNAL_ERROR, + AppResult::OTHER, + Full::new(Bytes::from("fastedge: Execute error")) + .map_err(|never| match never {}) + .boxed(), + ) + }; + (status_code, fail_reason, msg) +} + fn remote_traceparent(req: &hyper::Request) -> String { req.headers() .get(TRACEPARENT) @@ -448,20 +499,24 @@ fn remote_traceparent(req: &hyper::Request) -> String { /// Creates an HTTP 500 response. fn internal_fastedge_error(msg: &'static str) -> Result> { - Ok(hyper::Response::builder().status(FASTEDGE_INTERNAL_ERROR).body( - Full::new(Bytes::from(format!("fastedge: {}", msg))) - .map_err(|never| match never {}) - .boxed(), - )?) + Ok(hyper::Response::builder() + .status(FASTEDGE_INTERNAL_ERROR) + .body( + Full::new(Bytes::from(format!("fastedge: {}", msg))) + .map_err(|never| match never {}) + .boxed(), + )?) } /// Creates an HTTP 404 response. fn not_found() -> Result> { - Ok(hyper::Response::builder().status(StatusCode::NOT_FOUND).body( - Full::new(Bytes::from("fastedge: Unknown app")) - .map_err(|never| match never {}) - .boxed(), - )?) + Ok(hyper::Response::builder() + .status(StatusCode::NOT_FOUND) + .body( + Full::new(Bytes::from("fastedge: Unknown app")) + .map_err(|never| match never {}) + .boxed(), + )?) } /// Creates an HTTP 429 response. @@ -572,7 +627,7 @@ mod tests { use wasmtime::{Engine, Module}; use super::*; - use crate::executor::HttpExecutorImpl; + use crate::executor::http::HttpExecutorImpl; use runtime::util::stats::StatRow; use secret::Secret; diff --git a/src/main.rs b/src/main.rs index 676bed7..3064978 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ use async_trait::async_trait; use bytesize::{ByteSize, MB}; use clap::{Args, Parser, Subcommand}; use dictionary::Dictionary; +use http::{Request, Response, StatusCode}; use http_backend::{Backend, BackendStrategy}; use http_body_util::BodyExt; use http_service::executor::{ @@ -13,7 +14,7 @@ use http_service::executor::{ }; use http_service::state::HttpState; use http_service::{ContextHeaders, HttpConfig, HttpService, HyperOutgoingBody}; -use hyper::body::{Body}; +use hyper::body::Body; use hyper_tls::HttpsConnector; use hyper_util::client::legacy::connect::HttpConnector; use runtime::app::Status; @@ -81,6 +82,7 @@ struct HttpRunArgs { } /// Test tool execution context +#[derive(Clone)] struct CliContext { headers: HashMap, engine: Engine, @@ -231,17 +233,19 @@ enum CliExecutor { #[async_trait] impl HttpExecutor for CliExecutor { - async fn execute( + async fn execute( &self, - req: hyper::Request, - ) -> anyhow::Result<(hyper::Response, Duration, ByteSize)> + req: Request, + on_response: R, + ) -> anyhow::Result> where + R: FnOnce(StatusCode, ByteSize, Duration) + Send + 'static, B: BodyExt + Send, ::Data: Send, { match self { - CliExecutor::Http(ref executor) => executor.execute(req).await, - CliExecutor::Wasi(ref executor) => executor.execute(req).await, + CliExecutor::Http(ref executor) => executor.execute(req, on_response).await, + CliExecutor::Wasi(ref executor) => executor.execute(req, on_response).await, } } } From a459c03eeacd5a69eaa0507addcfb3e5fe5da7a2 Mon Sep 17 00:00:00 2001 From: Ruslan Pislari Date: Fri, 22 Nov 2024 16:43:28 +0200 Subject: [PATCH 3/3] fix: moving unit test to http sub-module --- crates/http-service/src/executor/http.rs | 424 ++++++++++++++++++++++- crates/http-service/src/lib.rs | 413 +--------------------- 2 files changed, 427 insertions(+), 410 deletions(-) diff --git a/crates/http-service/src/executor/http.rs b/crates/http-service/src/executor/http.rs index a0bb5d8..d2f62a2 100644 --- a/crates/http-service/src/executor/http.rs +++ b/crates/http-service/src/executor/http.rs @@ -1,4 +1,3 @@ -use crate::executor; use crate::executor::HttpExecutor; use crate::state::HttpState; use anyhow::{anyhow, bail, Context}; @@ -77,7 +76,7 @@ where body, }; - let properties = executor::get_properties(&parts.headers); + let properties = crate::executor::get_properties(&parts.headers); let store_builder = self.store_builder.to_owned().with_properties(properties); let wasi_nn = self.store_builder.make_wasi_nn_ctx()?; @@ -180,3 +179,424 @@ fn to_fastedge_http_method(method: &Method) -> anyhow::Result bail!("unsupported method: {}", method), }) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::executor::http::HttpExecutorImpl; + use crate::{ + ContextHeaders, ExecutorFactory, HttpService, FASTEDGE_EXECUTION_TIMEOUT, + FASTEDGE_OUT_OF_MEMORY, + }; + use bytes::Bytes; + use claims::*; + use dictionary::Dictionary; + use http_backend::{Backend, BackendStrategy, FastEdgeConnector}; + use http_body_util::Empty; + use runtime::app::Status; + use runtime::logger::{Logger, NullAppender}; + use runtime::service::ServiceBuilder; + use runtime::util::stats::{StatRow, StatsWriter}; + use runtime::{ + componentize_if_necessary, App, ContextT, PreCompiledLoader, Router, WasiVersion, + WasmConfig, WasmEngine, + }; + use secret::Secret; + use smol_str::{SmolStr, ToSmolStr}; + use std::collections::HashMap; + use wasmtime::component::Component; + use wasmtime::{Engine, Module}; + + #[derive(Clone)] + struct TestContext { + geo: HashMap, + app: Option, + engine: Engine, + } + + impl ContextT for TestContext { + type BackendConnector = FastEdgeConnector; + + fn make_logger(&self, _app_name: SmolStr, _wrk: &App) -> Logger { + Logger::new(NullAppender) + } + + fn backend(&self) -> Backend { + let backend = Backend::::builder(BackendStrategy::FastEdge).build( + FastEdgeConnector::new(assert_ok!("http://localhost:8080/".parse())), + ); + backend + } + + fn loader(&self) -> &dyn PreCompiledLoader { + self + } + + fn engine_ref(&self) -> &Engine { + &self.engine + } + } + + static DUMMY_SAMPLE: &[u8] = include_bytes!("../fixtures/dummy.wasm"); + static ALLOC_SAMPLE: &[u8] = include_bytes!("../fixtures/alloc.wasm"); + + impl PreCompiledLoader for TestContext { + fn load_component(&self, id: u64) -> anyhow::Result { + let bytes = if id == 100 { + ALLOC_SAMPLE + } else { + DUMMY_SAMPLE + }; + let wasm_sample = componentize_if_necessary(bytes)?; + Component::new(&self.engine, wasm_sample) + } + + fn load_module(&self, _id: u64) -> anyhow::Result { + Module::new(&self.engine, DUMMY_SAMPLE) + } + } + + impl StatsWriter for TestContext { + fn write_stats(&self, _stat: StatRow) {} + } + + impl Router for TestContext { + async fn lookup_by_name(&self, _name: &str) -> Option { + self.app.clone() + } + + async fn lookup_by_id(&self, _id: u64) -> Option<(SmolStr, App)> { + todo!() + } + } + + impl ContextHeaders for TestContext { + fn append_headers(&self) -> impl Iterator { + self.geo.iter().map(|(k, v)| (k.to_owned(), v.to_owned())) + } + } + + #[derive(Clone)] + struct TestSecret; + + impl SecretStrategy for TestSecret { + fn get(&self, _key: String) -> anyhow::Result>> { + Ok(Some(b"secret".to_vec())) + } + } + + impl ExecutorFactory> for TestContext { + type Executor = HttpExecutorImpl; + + fn get_executor( + &self, + name: SmolStr, + cfg: &App, + engine: &WasmEngine>, + ) -> anyhow::Result { + let mut dictionary = Dictionary::new(); + for (k, v) in cfg.env.iter() { + dictionary.insert(k.to_string(), v.to_string()); + } + let secret = Secret::new(TestSecret); + + let env = cfg.env.iter().collect::>(); + + let logger = self.make_logger(name.clone(), cfg); + + let version = WasiVersion::Preview2; + let store_builder = engine + .store_builder(version) + .set_env(&env) + .max_memory_size(cfg.mem_limit) + .max_epoch_ticks(cfg.max_duration) + .logger(logger); + + let component = self.loader().load_component(cfg.binary_id)?; + let instance_pre = engine.component_instantiate_pre(&component)?; + tracing::info!("Added '{}' to cache", name); + Ok(HttpExecutorImpl::new( + instance_pre, + store_builder, + self.backend(), + dictionary, + secret, + )) + } + } + + fn default_test_app(status: Status) -> Option { + Some(App { + binary_id: 0, + max_duration: 10, + mem_limit: 1400000, + env: Default::default(), + rsp_headers: HashMap::from([ + ("RES_HEADER_01".to_smolstr(), "01".to_smolstr()), + ("RES_HEADER_02".to_smolstr(), "02".to_smolstr()), + ]), + log: Default::default(), + app_id: 12345, + client_id: 23456, + plan: "test_plan".to_smolstr(), + status, + debug_until: None, + secrets: vec![], + }) + } + + fn make_engine() -> Engine { + let config = WasmConfig::default(); + let engine = assert_ok!(Engine::new(&config)); + engine + } + + fn load_geo_info() -> HashMap { + let mut ret = HashMap::new(); + ret.insert("PoP-Lat".to_smolstr(), "47.00420".to_smolstr()); + ret.insert("PoP-Long".to_smolstr(), "28.85740".to_smolstr()); + ret.insert("PoP-Reg".to_smolstr(), "CU".to_smolstr()); + ret.insert("PoP-City".to_smolstr(), "Bucharest".to_smolstr()); + ret.insert("PoP-Continent".to_smolstr(), "EU".to_smolstr()); + ret.insert("PoP-Country-Code".to_smolstr(), "RO".to_smolstr()); + ret.insert("PoP-Country-Name".to_smolstr(), "Romania".to_smolstr()); + ret + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn test_success() { + let req = assert_ok!(http::Request::builder() + .method("GET") + .uri("http://www.rust-lang.org/") + .header("server_name", "success.test.com") + .body( + Empty::::new() + .map_err(|never| match never {}) + .boxed() + )); + + let context = TestContext { + geo: load_geo_info(), + app: default_test_app(Status::Enabled), + engine: make_engine(), + }; + + let http_service: HttpService = + assert_ok!(ServiceBuilder::new(context).build()); + + let res = assert_ok!(http_service.handle_request("1", req).await); + assert_eq!(StatusCode::OK, res.status()); + let headers = res.headers(); + assert_eq!(4, headers.len()); + assert_eq!( + "*", + assert_some!(headers.get("access-control-allow-origin")) + ); + assert_eq!("no-store", assert_some!(headers.get("cache-control"))); + assert_eq!("01", assert_some!(headers.get("RES_HEADER_01"))); + assert_eq!("02", assert_some!(headers.get("RES_HEADER_02"))); + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn test_timeout() { + let req = assert_ok!(http::Request::builder() + .method("GET") + .uri("http://www.rust-lang.org/") + .header("server_name", "timeout.test.com") + .body( + Empty::::new() + .map_err(|never| match never {}) + .boxed() + )); + + let app = Some(App { + binary_id: 1, + max_duration: 0, + mem_limit: 10000000, + env: Default::default(), + rsp_headers: HashMap::from([("RES_HEADER_03".to_smolstr(), "03".to_smolstr())]), + log: Default::default(), + app_id: 12345, + client_id: 23456, + plan: "test_plan".to_smolstr(), + status: Status::Enabled, + debug_until: None, + secrets: vec![], + }); + + let context = TestContext { + geo: load_geo_info(), + app, + engine: make_engine(), + }; + + let http_service: HttpService = + assert_ok!(ServiceBuilder::new(context).build()); + + let res = assert_ok!(http_service.handle_request("2", req).await); + assert_eq!(FASTEDGE_EXECUTION_TIMEOUT, res.status()); + let headers = res.headers(); + assert_eq!(3, headers.len()); + assert_eq!( + "*", + assert_some!(headers.get("access-control-allow-origin")) + ); + assert_eq!("no-store", assert_some!(headers.get("cache-control"))); + assert_eq!("03", assert_some!(headers.get("RES_HEADER_03"))); + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn test_insufficient_memory() { + let req = assert_ok!(http::Request::builder() + .method("GET") + .uri("http://www.rust-lang.org/?size=200000") + .header("server_name", "insufficient_memory.test.com") + .body( + Empty::::new() + .map_err(|never| match never {}) + .boxed() + )); + + let app = Some(App { + binary_id: 100, + max_duration: 10, + mem_limit: 1500000, + env: Default::default(), + rsp_headers: HashMap::from([("RES_HEADER_03".to_smolstr(), "03".to_smolstr())]), + log: Default::default(), + app_id: 12345, + client_id: 23456, + plan: "test_plan".to_smolstr(), + status: Status::Enabled, + debug_until: None, + secrets: vec![], + }); + + let context = TestContext { + geo: load_geo_info(), + app, + engine: make_engine(), + }; + + let http_service: HttpService = + assert_ok!(ServiceBuilder::new(context).build()); + + let res = assert_ok!(http_service.handle_request("3", req).await); + assert_eq!(FASTEDGE_OUT_OF_MEMORY, res.status()); + let headers = res.headers(); + assert_eq!(3, headers.len()); + assert_eq!( + "*", + assert_some!(headers.get("access-control-allow-origin")) + ); + assert_eq!("no-store", assert_some!(headers.get("cache-control"))); + assert_eq!("03", assert_some!(headers.get("RES_HEADER_03"))); + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn draft_app() { + let req = assert_ok!(http::Request::builder() + .method("GET") + .uri("http://www.rust-lang.org/") + .header("server_name", "draft.test.com") + .body( + Empty::::new() + .map_err(|never| match never {}) + .boxed() + )); + + let context = TestContext { + geo: load_geo_info(), + app: default_test_app(Status::Draft), + engine: make_engine(), + }; + + let http_service: HttpService = + assert_ok!(ServiceBuilder::new(context).build()); + let res = assert_ok!(http_service.handle_request("4", req).await); + assert_eq!(StatusCode::NOT_FOUND, res.status()); + assert_eq!(0, res.headers().len()); + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn disabled_app() { + let req = assert_ok!(http::Request::builder() + .method("GET") + .uri("http://www.rust-lang.org/") + .header("server_name", "draft.test.com") + .body( + Empty::::new() + .map_err(|never| match never {}) + .boxed() + )); + + let context = TestContext { + geo: load_geo_info(), + app: default_test_app(Status::Disabled), + engine: make_engine(), + }; + + let http_service: HttpService = + assert_ok!(ServiceBuilder::new(context).build()); + let res = assert_ok!(http_service.handle_request("5", req).await); + assert_eq!(StatusCode::NOT_FOUND, res.status()); + assert_eq!(0, res.headers().len()); + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn rate_limit_app() { + let req = assert_ok!(http::Request::builder() + .method("GET") + .uri("http://www.rust-lang.org/") + .header("server_name", "draft.test.com") + .body( + Empty::::new() + .map_err(|never| match never {}) + .boxed() + )); + + let context = TestContext { + geo: load_geo_info(), + app: default_test_app(Status::RateLimited), + engine: make_engine(), + }; + + let http_service: HttpService = + assert_ok!(ServiceBuilder::new(context).build()); + let res = assert_ok!(http_service.handle_request("6", req).await); + assert_eq!(StatusCode::TOO_MANY_REQUESTS, res.status()); + assert_eq!(0, res.headers().len()); + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn suspended_app() { + let req = assert_ok!(http::Request::builder() + .method("GET") + .uri("http://www.rust-lang.org/") + .header("server_name", "draft.test.com") + .body( + Empty::::new() + .map_err(|never| match never {}) + .boxed() + )); + + let context = TestContext { + geo: load_geo_info(), + app: default_test_app(Status::Suspended), + engine: make_engine(), + }; + + let http_service: HttpService = + assert_ok!(ServiceBuilder::new(context).build()); + let res = assert_ok!(http_service.handle_request("7", req).await); + assert_eq!(StatusCode::NOT_ACCEPTABLE, res.status()); + assert_eq!(0, res.headers().len()); + } +} diff --git a/crates/http-service/src/lib.rs b/crates/http-service/src/lib.rs index 4e59b5a..fb71bce 100644 --- a/crates/http-service/src/lib.rs +++ b/crates/http-service/src/lib.rs @@ -198,7 +198,7 @@ where /// handle HTTP request. async fn handle_request( - self: Arc, + &self, request_id: &str, mut request: hyper::Request, ) -> Result> @@ -614,22 +614,12 @@ fn app_req_headers(geo: impl Iterator) -> HeaderMap { #[cfg(test)] mod tests { - use claims::*; - use dictionary::Dictionary; - use http_backend::{Backend, BackendStrategy, FastEdgeConnector}; - use runtime::logger::{Logger, NullAppender}; - use runtime::service::ServiceBuilder; - use runtime::{componentize_if_necessary, PreCompiledLoader, WasiVersion, WasmConfig}; - use smol_str::ToSmolStr; - use std::collections::HashMap; use test_case::test_case; - use wasmtime::component::Component; - use wasmtime::{Engine, Module}; - use super::*; - use crate::executor::http::HttpExecutorImpl; - use runtime::util::stats::StatRow; - use secret::Secret; + use crate::app_name_from_request; + use bytes::Bytes; + use claims::assert_ok; + use http_body_util::{BodyExt, Empty}; #[test_case("app.server.com", "server.com", "app"; "get app name from server_name header")] fn test_app_name_from_request(server_name: &str, uri: &str, expected: &str) { @@ -646,397 +636,4 @@ mod tests { let app_name = assert_ok!(app_name_from_request(&req)); assert_eq!(expected, app_name); } - - #[derive(Clone)] - struct TestContext { - geo: HashMap, - app: Option, - engine: Engine, - } - - impl ContextT for TestContext { - type BackendConnector = FastEdgeConnector; - - fn make_logger(&self, _app_name: SmolStr, _wrk: &App) -> Logger { - Logger::new(NullAppender) - } - - fn backend(&self) -> Backend { - let backend = Backend::::builder(BackendStrategy::FastEdge).build( - FastEdgeConnector::new(assert_ok!("http://localhost:8080/".parse())), - ); - backend - } - - fn loader(&self) -> &dyn PreCompiledLoader { - self - } - - fn engine_ref(&self) -> &Engine { - &self.engine - } - } - - static DUMMY_SAMPLE: &[u8] = include_bytes!("fixtures/dummy.wasm"); - static ALLOC_SAMPLE: &[u8] = include_bytes!("fixtures/alloc.wasm"); - - impl PreCompiledLoader for TestContext { - fn load_component(&self, id: u64) -> Result { - let bytes = if id == 100 { - ALLOC_SAMPLE - } else { - DUMMY_SAMPLE - }; - let wasm_sample = componentize_if_necessary(bytes)?; - Component::new(&self.engine, wasm_sample) - } - - fn load_module(&self, _id: u64) -> Result { - Module::new(&self.engine, DUMMY_SAMPLE) - } - } - - impl StatsWriter for TestContext { - fn write_stats(&self, _stat: StatRow) {} - } - - impl Router for TestContext { - async fn lookup_by_name(&self, _name: &str) -> Option { - self.app.clone() - } - - async fn lookup_by_id(&self, _id: u64) -> Option<(SmolStr, App)> { - todo!() - } - } - - impl ContextHeaders for TestContext { - fn append_headers(&self) -> impl Iterator { - self.geo.iter().map(|(k, v)| (k.to_owned(), v.to_owned())) - } - } - - #[derive(Clone)] - struct TestSecret; - - impl SecretStrategy for TestSecret { - fn get(&self, _key: String) -> Result>> { - Ok(Some(b"secret".to_vec())) - } - } - - impl ExecutorFactory> for TestContext { - type Executor = HttpExecutorImpl; - - fn get_executor( - &self, - name: SmolStr, - cfg: &App, - engine: &WasmEngine>, - ) -> Result { - let mut dictionary = Dictionary::new(); - for (k, v) in cfg.env.iter() { - dictionary.insert(k.to_string(), v.to_string()); - } - let secret = Secret::new(TestSecret); - - let env = cfg.env.iter().collect::>(); - - let logger = self.make_logger(name.clone(), cfg); - - let version = WasiVersion::Preview2; - let store_builder = engine - .store_builder(version) - .set_env(&env) - .max_memory_size(cfg.mem_limit) - .max_epoch_ticks(cfg.max_duration) - .logger(logger); - - let component = self.loader().load_component(cfg.binary_id)?; - let instance_pre = engine.component_instantiate_pre(&component)?; - tracing::info!("Added '{}' to cache", name); - Ok(HttpExecutorImpl::new( - instance_pre, - store_builder, - self.backend(), - dictionary, - secret, - )) - } - } - - fn default_test_app(status: Status) -> Option { - Some(App { - binary_id: 0, - max_duration: 10, - mem_limit: 1400000, - env: Default::default(), - rsp_headers: HashMap::from([ - ("RES_HEADER_01".to_smolstr(), "01".to_smolstr()), - ("RES_HEADER_02".to_smolstr(), "02".to_smolstr()), - ]), - log: Default::default(), - app_id: 12345, - client_id: 23456, - plan: "test_plan".to_smolstr(), - status, - debug_until: None, - secrets: vec![], - }) - } - - fn make_engine() -> Engine { - let config = WasmConfig::default(); - let engine = assert_ok!(Engine::new(&config)); - engine - } - - fn load_geo_info() -> HashMap { - let mut ret = HashMap::new(); - ret.insert("PoP-Lat".to_smolstr(), "47.00420".to_smolstr()); - ret.insert("PoP-Long".to_smolstr(), "28.85740".to_smolstr()); - ret.insert("PoP-Reg".to_smolstr(), "CU".to_smolstr()); - ret.insert("PoP-City".to_smolstr(), "Bucharest".to_smolstr()); - ret.insert("PoP-Continent".to_smolstr(), "EU".to_smolstr()); - ret.insert("PoP-Country-Code".to_smolstr(), "RO".to_smolstr()); - ret.insert("PoP-Country-Name".to_smolstr(), "Romania".to_smolstr()); - ret - } - - #[tokio::test] - #[tracing_test::traced_test] - async fn test_success() { - let req = assert_ok!(http::Request::builder() - .method("GET") - .uri("http://www.rust-lang.org/") - .header("server_name", "success.test.com") - .body( - Empty::::new() - .map_err(|never| match never {}) - .boxed() - )); - - let context = TestContext { - geo: load_geo_info(), - app: default_test_app(Status::Enabled), - engine: make_engine(), - }; - - let http_service: HttpService = - assert_ok!(ServiceBuilder::new(context).build()); - - let res = assert_ok!(http_service.handle_request("1", req).await); - assert_eq!(StatusCode::OK, res.status()); - let headers = res.headers(); - assert_eq!(4, headers.len()); - assert_eq!( - "*", - assert_some!(headers.get("access-control-allow-origin")) - ); - assert_eq!("no-store", assert_some!(headers.get("cache-control"))); - assert_eq!("01", assert_some!(headers.get("RES_HEADER_01"))); - assert_eq!("02", assert_some!(headers.get("RES_HEADER_02"))); - } - - #[tokio::test] - #[tracing_test::traced_test] - async fn test_timeout() { - let req = assert_ok!(http::Request::builder() - .method("GET") - .uri("http://www.rust-lang.org/") - .header("server_name", "timeout.test.com") - .body( - Empty::::new() - .map_err(|never| match never {}) - .boxed() - )); - - let app = Some(App { - binary_id: 1, - max_duration: 0, - mem_limit: 10000000, - env: Default::default(), - rsp_headers: HashMap::from([("RES_HEADER_03".to_smolstr(), "03".to_smolstr())]), - log: Default::default(), - app_id: 12345, - client_id: 23456, - plan: "test_plan".to_smolstr(), - status: Status::Enabled, - debug_until: None, - secrets: vec![], - }); - - let context = TestContext { - geo: load_geo_info(), - app, - engine: make_engine(), - }; - - let http_service: HttpService = - assert_ok!(ServiceBuilder::new(context).build()); - - let res = assert_ok!(http_service.handle_request("2", req).await); - assert_eq!(FASTEDGE_EXECUTION_TIMEOUT, res.status()); - let headers = res.headers(); - assert_eq!(3, headers.len()); - assert_eq!( - "*", - assert_some!(headers.get("access-control-allow-origin")) - ); - assert_eq!("no-store", assert_some!(headers.get("cache-control"))); - assert_eq!("03", assert_some!(headers.get("RES_HEADER_03"))); - } - - #[tokio::test] - #[tracing_test::traced_test] - async fn test_insufficient_memory() { - let req = assert_ok!(http::Request::builder() - .method("GET") - .uri("http://www.rust-lang.org/?size=200000") - .header("server_name", "insufficient_memory.test.com") - .body( - Empty::::new() - .map_err(|never| match never {}) - .boxed() - )); - - let app = Some(App { - binary_id: 100, - max_duration: 10, - mem_limit: 1500000, - env: Default::default(), - rsp_headers: HashMap::from([("RES_HEADER_03".to_smolstr(), "03".to_smolstr())]), - log: Default::default(), - app_id: 12345, - client_id: 23456, - plan: "test_plan".to_smolstr(), - status: Status::Enabled, - debug_until: None, - secrets: vec![], - }); - - let context = TestContext { - geo: load_geo_info(), - app, - engine: make_engine(), - }; - - let http_service: HttpService = - assert_ok!(ServiceBuilder::new(context).build()); - - let res = assert_ok!(http_service.handle_request("3", req).await); - assert_eq!(FASTEDGE_OUT_OF_MEMORY, res.status()); - let headers = res.headers(); - assert_eq!(3, headers.len()); - assert_eq!( - "*", - assert_some!(headers.get("access-control-allow-origin")) - ); - assert_eq!("no-store", assert_some!(headers.get("cache-control"))); - assert_eq!("03", assert_some!(headers.get("RES_HEADER_03"))); - } - - #[tokio::test] - #[tracing_test::traced_test] - async fn draft_app() { - let req = assert_ok!(http::Request::builder() - .method("GET") - .uri("http://www.rust-lang.org/") - .header("server_name", "draft.test.com") - .body( - Empty::::new() - .map_err(|never| match never {}) - .boxed() - )); - - let context = TestContext { - geo: load_geo_info(), - app: default_test_app(Status::Draft), - engine: make_engine(), - }; - - let http_service: HttpService = - assert_ok!(ServiceBuilder::new(context).build()); - let res = assert_ok!(http_service.handle_request("4", req).await); - assert_eq!(StatusCode::NOT_FOUND, res.status()); - assert_eq!(0, res.headers().len()); - } - - #[tokio::test] - #[tracing_test::traced_test] - async fn disabled_app() { - let req = assert_ok!(http::Request::builder() - .method("GET") - .uri("http://www.rust-lang.org/") - .header("server_name", "draft.test.com") - .body( - Empty::::new() - .map_err(|never| match never {}) - .boxed() - )); - - let context = TestContext { - geo: load_geo_info(), - app: default_test_app(Status::Disabled), - engine: make_engine(), - }; - - let http_service: HttpService = - assert_ok!(ServiceBuilder::new(context).build()); - let res = assert_ok!(http_service.handle_request("5", req).await); - assert_eq!(StatusCode::NOT_FOUND, res.status()); - assert_eq!(0, res.headers().len()); - } - - #[tokio::test] - #[tracing_test::traced_test] - async fn rate_limit_app() { - let req = assert_ok!(http::Request::builder() - .method("GET") - .uri("http://www.rust-lang.org/") - .header("server_name", "draft.test.com") - .body( - Empty::::new() - .map_err(|never| match never {}) - .boxed() - )); - - let context = TestContext { - geo: load_geo_info(), - app: default_test_app(Status::RateLimited), - engine: make_engine(), - }; - - let http_service: HttpService = - assert_ok!(ServiceBuilder::new(context).build()); - let res = assert_ok!(http_service.handle_request("6", req).await); - assert_eq!(StatusCode::TOO_MANY_REQUESTS, res.status()); - assert_eq!(0, res.headers().len()); - } - - #[tokio::test] - #[tracing_test::traced_test] - async fn suspended_app() { - let req = assert_ok!(http::Request::builder() - .method("GET") - .uri("http://www.rust-lang.org/") - .header("server_name", "draft.test.com") - .body( - Empty::::new() - .map_err(|never| match never {}) - .boxed() - )); - - let context = TestContext { - geo: load_geo_info(), - app: default_test_app(Status::Suspended), - engine: make_engine(), - }; - - let http_service: HttpService = - assert_ok!(ServiceBuilder::new(context).build()); - let res = assert_ok!(http_service.handle_request("7", req).await); - assert_eq!(StatusCode::NOT_ACCEPTABLE, res.status()); - assert_eq!(0, res.headers().len()); - } }