diff options
Diffstat (limited to 'web/atward')
-rw-r--r-- | web/atward/.gitignore | 3 | ||||
-rw-r--r-- | web/atward/Cargo.lock | 881 | ||||
-rw-r--r-- | web/atward/Cargo.toml | 9 | ||||
-rw-r--r-- | web/atward/build.rs | 55 | ||||
-rw-r--r-- | web/atward/default.nix | 8 | ||||
-rw-r--r-- | web/atward/indexHtml/default.nix | 99 | ||||
-rw-r--r-- | web/atward/src/main.rs | 200 | ||||
-rw-r--r-- | web/atward/src/opensearch.xml | 8 | ||||
-rw-r--r-- | web/atward/src/tests.rs | 187 |
9 files changed, 1450 insertions, 0 deletions
diff --git a/web/atward/.gitignore b/web/atward/.gitignore new file mode 100644 index 000000000000..29e65519ba35 --- /dev/null +++ b/web/atward/.gitignore @@ -0,0 +1,3 @@ +result +/target +**/*.rs.bk diff --git a/web/atward/Cargo.lock b/web/atward/Cargo.lock new file mode 100644 index 000000000000..8b0ef04f5e81 --- /dev/null +++ b/web/atward/Cargo.lock @@ -0,0 +1,881 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ascii" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" + +[[package]] +name = "atward" +version = "0.1.0" +dependencies = [ + "regex", + "rouille", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] +name = "brotli" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "buf_redux" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f" +dependencies = [ + "memchr", + "safemem", +] + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "cc" +version = "1.0.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f8e7c90afad890484a21653d08b6e209ae34770fb5ee298f9c699fcc1e5c856" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "windows-targets", +] + +[[package]] +name = "chunked_transfer" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cca491388666e04d7248af3f60f0c40cfb0991c72205595d7c396e3510207d1a" + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "deflate" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f" +dependencies = [ + "adler32", + "gzip-header", +] + +[[package]] +name = "deranged" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "errno" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "filetime" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.3.5", + "windows-sys", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "getrandom" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gzip-header" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95cc527b92e6029a62960ad99aa8a6660faa4555fe5f731aab13aa6a921795a2" +dependencies = [ + "crc32fast", +] + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "iana-time-zone" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "js-sys" +version = "0.3.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "linux-raw-sys" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "multipart" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00dec633863867f29cb39df64a397cdf4a6354708ddd7759f70c7fb51c5f9182" +dependencies = [ + "buf_redux", + "httparse", + "log", + "mime", + "mime_guess", + "quick-error", + "rand", + "safemem", + "tempfile", + "twoway", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rouille" +version = "3.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3716fbf57fc1084d7a706adf4e445298d123e4a44294c4e8213caf1b85fcc921" +dependencies = [ + "base64", + "brotli", + "chrono", + "deflate", + "filetime", + "multipart", + "percent-encoding", + "rand", + "serde", + "serde_derive", + "serde_json", + "sha1_smol", + "threadpool", + "time", + "tiny_http", + "url", +] + +[[package]] +name = "rustix" +version = "0.38.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + +[[package]] +name = "serde" +version = "1.0.192" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.192" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall 0.4.1", + "rustix", + "windows-sys", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "time" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +dependencies = [ + "deranged", + "libc", + "num_threads", + "powerfmt", + "serde", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "tiny_http" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389915df6413a2e74fb181895f933386023c71110878cd0825588928e64cdc82" +dependencies = [ + "ascii", + "chunked_transfer", + "httpdate", + "log", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "twoway" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" +dependencies = [ + "memchr", +] + +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[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.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/web/atward/Cargo.toml b/web/atward/Cargo.toml new file mode 100644 index 000000000000..2ecd10f96f68 --- /dev/null +++ b/web/atward/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "atward" +version = "0.1.0" +authors = ["Vincent Ambo <mail@tazj.in>"] +edition = "2018" + +[dependencies] +regex = "1.5" +rouille = "3.5" diff --git a/web/atward/build.rs b/web/atward/build.rs new file mode 100644 index 000000000000..90a2f35cd1a9 --- /dev/null +++ b/web/atward/build.rs @@ -0,0 +1,55 @@ +//! Build script that can be used outside of Nix builds to inject the +//! ATWARD_INDEX_HTML variable when building in development mode. +//! +//! Note that this script assumes that atward is in a checkout of the +//! TVL depot. + +use std::process::Command; + +static ATWARD_INDEX_HTML: &str = "ATWARD_INDEX_HTML"; +static ERROR_MESSAGE: &str = r#"Failed to build index page. + +When building during development, atward expects to be in a checkout +of the TVL depot. This is required to automatically build the index +page that is needed at compile time. + +As atward can not automatically detect the location of the page, +you must set the `ATWARD_INDEX_HTML` environment variable to the +right path. + +The expected page is build using the files in //web/atward/indexHtml +in the depot."#; + +fn main() { + // Do nothing if the variable is already set (e.g. via Nix) + if let Ok(_) = std::env::var(ATWARD_INDEX_HTML) { + return; + } + + // Otherwise ask Nix to build it and inject the result. + let output = Command::new("nix-build") + .arg("-A") + .arg("web.atward.indexHtml") + // ... assuming atward is at //web/atward ... + .arg("../..") + .output() + .expect(ERROR_MESSAGE); + + if !output.status.success() { + eprintln!( + "{}\nNix output: {}", + ERROR_MESSAGE, + String::from_utf8_lossy(&output.stderr) + ); + return; + } + + let out_path = String::from_utf8(output.stdout) + .expect("Nix returned invalid output after building index page"); + + // Return an instruction to Cargo that will set the environment + // variable during rustc calls. + // + // https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-envvarvalue + println!("cargo:rustc-env={}={}", ATWARD_INDEX_HTML, out_path.trim()); +} diff --git a/web/atward/default.nix b/web/atward/default.nix new file mode 100644 index 000000000000..f3ed04345c32 --- /dev/null +++ b/web/atward/default.nix @@ -0,0 +1,8 @@ +{ depot, ... }: + +depot.third_party.naersk.buildPackage { + src = ./.; + override = x: { + ATWARD_INDEX_HTML = depot.web.atward.indexHtml; + }; +} diff --git a/web/atward/indexHtml/default.nix b/web/atward/indexHtml/default.nix new file mode 100644 index 000000000000..3af808b89831 --- /dev/null +++ b/web/atward/indexHtml/default.nix @@ -0,0 +1,99 @@ +{ depot, ... }: + +depot.web.tvl.template { + title = "atward"; + content = '' + atward + ====== + + ---------- + + **atward** is [TVL's](https://tvl.fyi/) search + service. It can be configured as a browser search engine for easy + access to TVL bugs, code reviews, code paths and more. + + ### Setting up atward + + To configure atward, add a search engine to your browser with the + following search string: `https://at.tvl.fyi/?q=%s` + Consider setting a shortcut, for example **t** or **tvl**. + You can now quickly access TVL resources by typing something + like <kbd>t b/42</kbd> in your URL bar to get to the bug with ID + 42. + + + ### Supported queries + + The following query types are supported in atward: + + * <kbd>b/42</kbd> - access bugs with ID 42 + * <kbd>cl/3087</kbd> - access changelist with ID 3087 + * <kbd>//web/atward</kbd> - open the **//web/atward** path in TVLs monorepo + * <kbd>r/3002</kbd> - access revision 3002 in cgit + + When given a short host name (e.g. <kbd>todo</kbd> or + <kbd>cl</kbd>), atward will redirect to the appropriate `tvl.fyi` + domain. + + ### Configuration + + Some behaviour of atward can be configured by adding query + parameters to the search string: + + * <kbd>cs=true</kbd> - use Sourcegraph instead of cgit to view code + + + In some browsers (like Firefox) users can not edit query + parameters for search engines. As an alternative configuration can + be supplied via cookies with the same names as the configuration + parameters. + + The form below can set this configuration: + <form class="cheddar-callout cheddar-todo"> + <input type="checkbox" + id="cs-setting" + name="cs-setting" + onchange="saveSetting(this, 'cs');"> + <label for="cs-setting">Use Sourcegraph instead of cgit</label> + </form> + + <noscript> + <p class="cheddar-callout cheddar-warning"> + The form above only works with Javascript enabled. Only a few + lines of Javascript are used, and they are licensed under a + free-software license (MIT). + </p> + </noscript> + + ### Source code + + atward's source code lives at + [//web/atward](https://at.tvl.fyi/?q=%2F%2Fweb%2Fatward). + ''; + extraHead = '' + <script> + /* Initialise the state of all settings. */ + function loadSettings() { + loadSetting(document.getElementById('cs-setting'), 'cs'); + } + + /* Initialise the state of a setting from a cookie. */ + function loadSetting(checkbox, name) { + if (document.cookie.split(';').some(function(cookie) { + return cookie.indexOf(`''${name}=true`) >= 0; + })) { + checkbox.checked = true; + } + } + + /* Persist the state of a checkbox in a cookie */ + function saveSetting(checkbox, name) { + console.log(`setting atward parameter '''''${name}' to ''${checkbox.checked.toString()}`); + document.cookie = `''${name}=''${checkbox.checked.toString()};`; + } + + document.addEventListener('DOMContentLoaded', loadSettings); + </script> + <link rel="search" type="application/opensearchdescription+xml" title="TVL Search" href="https://at.tvl.fyi/opensearch.xml"> + ''; +} diff --git a/web/atward/src/main.rs b/web/atward/src/main.rs new file mode 100644 index 000000000000..eb2603a226c6 --- /dev/null +++ b/web/atward/src/main.rs @@ -0,0 +1,200 @@ +//! Atward implements TVL's redirection service, living at +//! atward.tvl.fyi +//! +//! This service is designed to be added as a search engine to web +//! browsers and attempts to send users to useful locations based on +//! their search query (falling back to another search engine). +use regex::Regex; +use rouille::input::cookies; +use rouille::{Request, Response}; + +#[cfg(test)] +mod tests; + +/// A query handler supported by atward. It consists of a pattern on +/// which to match and trigger the query, and a function to execute +/// that returns the target URL. +struct Handler { + /// Regular expression on which to match the query string. + pattern: Regex, + + /// Function to construct the target URL. If the pattern matches, + /// this is invoked with the captured matches and the entire URI. + /// + /// Returning `None` causes atward to fall through to the next + /// query (and eventually to the default search engine). + target: for<'s> fn(&Query, regex::Captures<'s>) -> Option<String>, +} + +/// An Atward query supplied by a user. +#[derive(Debug, PartialEq)] +struct Query { + /// Query string itself. + query: String, + + /// Should Sourcegraph be used instead of cgit? + cs: bool, +} + +/// Helper function for setting a parameter based on a query +/// parameter. +fn query_setting(req: &Request, config: &mut bool, param: &str) { + match req.get_param(param) { + Some(s) if s == "true" => *config = true, + Some(s) if s == "false" => *config = false, + _ => {} + } +} + +impl Query { + fn from_request(req: &Request) -> Option<Query> { + // First extract the actual search query ... + let mut query = match req.get_param("q") { + Some(query) => Query { query, cs: false }, + None => return None, + }; + + // ... then apply settings to it. Settings in query parameters + // take precedence over cookies. + for cookie in cookies(req) { + match cookie { + ("cs", "true") => { + query.cs = true; + } + _ => {} + } + } + + query_setting(req, &mut query.cs, "cs"); + + Some(query) + } +} + +#[cfg(test)] +impl From<&str> for Query { + fn from(query: &str) -> Query { + Query { + query: query.to_string(), + cs: false, + } + } +} + +/// Create a URL to a file (and, optionally, specific line) in cgit. +fn cgit_url(path: &str) -> String { + if path.ends_with(".md") { + format!("https://code.tvl.fyi/about/{}", path) + } else { + format!("https://code.tvl.fyi/tree/{}", path) + } +} + +/// Create a URL to a path in Sourcegraph. +fn sourcegraph_path_url(path: &str) -> String { + format!("https://cs.tvl.fyi/depot/-/tree/{}", path) +} +/// Definition of all supported query handlers in atward. +fn handlers() -> Vec<Handler> { + vec![ + // Bug IDs (e.g. b/123) + Handler { + pattern: Regex::new("^b/(?P<bug>\\d+)$").unwrap(), + target: |_, captures| Some(format!("https://b.tvl.fyi/{}", &captures["bug"])), + }, + // Changelists (e.g. cl/42) + Handler { + pattern: Regex::new("^cl/(?P<cl>\\d+)$").unwrap(), + target: |_, captures| Some(format!("https://cl.tvl.fyi/{}", &captures["cl"])), + }, + // Non-parameterised short hostnames should redirect to $host.tvl.fyi + Handler { + pattern: Regex::new("^(?P<host>b|cl|cs|code|at|todo)$").unwrap(), + target: |_, captures| Some(format!("https://{}.tvl.fyi/", &captures["host"])), + }, + // Depot revisions (e.g. r/3002) + Handler { + pattern: Regex::new("^r/(?P<rev>\\d+)$").unwrap(), + target: |_, captures| { + Some(format!( + "https://code.tvl.fyi/commit/?id=refs/r/{}", + &captures["rev"] + )) + }, + }, + // Depot paths (e.g. //web/atward or //ops/nixos/whitby/default.nix) + // TODO(tazjin): Add support for specifying lines in a query parameter + Handler { + pattern: Regex::new("^//(?P<path>[a-zA-Z].*)?$").unwrap(), + target: |query, captures| { + // Pass an empty string if the path is missing, to + // redirect to the depot root. + let path = captures.name("path").map(|m| m.as_str()).unwrap_or(""); + + if query.cs { + Some(sourcegraph_path_url(path)) + } else { + Some(cgit_url(path)) + } + }, + }, + ] +} + +/// Attempt to match against all known query types, and return the +/// destination URL if one is found. +fn dispatch(handlers: &[Handler], query: &Query) -> Option<String> { + for handler in handlers { + if let Some(captures) = handler.pattern.captures(&query.query) { + if let Some(destination) = (handler.target)(query, captures) { + return Some(destination); + } + } + } + + None +} + +/// Return the opensearch.xml file which is required for adding atward +/// as a search engine in Firefox. +fn opensearch() -> Response { + Response::text(include_str!("opensearch.xml")) + .with_unique_header("Content-Type", "application/opensearchdescription+xml") +} + +/// Render the atward index page which gives users some information +/// about how to use the service. +fn index() -> Response { + Response::html(include_str!(env!("ATWARD_INDEX_HTML"))) +} + +/// Render the fallback page which informs users that their query is +/// unsupported. +fn fallback() -> Response { + Response::text("error for emphasis that i am angery and the query whimchst i angery atward") + .with_status_code(404) +} + +fn main() { + let queries = handlers(); + let address = std::env::var("ATWARD_LISTEN_ADDRESS") + .expect("ATWARD_LISTEN_ADDRESS environment variable must be set"); + + rouille::start_server(&address, move |request| { + rouille::log(&request, std::io::stderr(), || { + if request.url() == "/opensearch.xml" { + return opensearch(); + } + + let query = match Query::from_request(&request) { + Some(q) => q, + None => return index(), + }; + + match dispatch(&queries, &query) { + None => fallback(), + Some(destination) => Response::redirect_303(destination), + } + }) + }); +} diff --git a/web/atward/src/opensearch.xml b/web/atward/src/opensearch.xml new file mode 100644 index 000000000000..6033987f5b4b --- /dev/null +++ b/web/atward/src/opensearch.xml @@ -0,0 +1,8 @@ +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>TVL</ShortName> + <Description>The Virus Lounge Search</Description> + <InputEncoding>UTF-8</InputEncoding> + <Url type="text/html" template="https://at.tvl.fyi/"> + <Param name="q" value="{searchTerms}"/> + </Url> +</OpenSearchDescription> diff --git a/web/atward/src/tests.rs b/web/atward/src/tests.rs new file mode 100644 index 000000000000..a23f96ee9a74 --- /dev/null +++ b/web/atward/src/tests.rs @@ -0,0 +1,187 @@ +use super::*; + +#[test] +fn bug_query() { + assert_eq!( + dispatch(&handlers(), &"b/42".into()), + Some("https://b.tvl.fyi/42".to_string()) + ); + + assert_eq!( + dispatch(&handlers(), &"something only mentioning b/42".into()), + None, + ); + assert_eq!(dispatch(&handlers(), &"b/invalid".into()), None,); +} + +#[test] +fn cl_query() { + assert_eq!( + dispatch(&handlers(), &"cl/42".into()), + Some("https://cl.tvl.fyi/42".to_string()) + ); + + assert_eq!( + dispatch(&handlers(), &"something only mentioning cl/42".into()), + None, + ); + assert_eq!(dispatch(&handlers(), &"cl/invalid".into()), None,); +} + +#[test] +fn depot_path_cgit_query() { + assert_eq!( + dispatch(&handlers(), &"//web/atward/default.nix".into()), + Some("https://code.tvl.fyi/tree/web/atward/default.nix".to_string()), + ); + + assert_eq!( + dispatch(&handlers(), &"//nix/readTree/README.md".into()), + Some("https://code.tvl.fyi/about/nix/readTree/README.md".to_string()), + ); + + assert_eq!(dispatch(&handlers(), &"/not/a/depot/path".into()), None); +} + +#[test] +fn depot_path_sourcegraph_query() { + assert_eq!( + dispatch( + &handlers(), + &Query { + query: "//web/atward/default.nix".to_string(), + cs: true, + } + ), + Some("https://cs.tvl.fyi/depot/-/tree/web/atward/default.nix".to_string()), + ); + + assert_eq!( + dispatch( + &handlers(), + &Query { + query: "/not/a/depot/path".to_string(), + cs: true, + } + ), + None + ); +} + +#[test] +fn depot_root_cgit_query() { + assert_eq!( + dispatch( + &handlers(), + &Query { + query: "//".to_string(), + cs: false, + } + ), + Some("https://code.tvl.fyi/tree/".to_string()), + ); +} + +#[test] +fn plain_host_queries() { + assert_eq!( + dispatch(&handlers(), &"cs".into()), + Some("https://cs.tvl.fyi/".to_string()), + ); + + assert_eq!( + dispatch(&handlers(), &"cl".into()), + Some("https://cl.tvl.fyi/".to_string()), + ); + + assert_eq!( + dispatch(&handlers(), &"b".into()), + Some("https://b.tvl.fyi/".to_string()), + ); + + assert_eq!( + dispatch(&handlers(), &"todo".into()), + Some("https://todo.tvl.fyi/".to_string()), + ); +} + +#[test] +fn request_to_query() { + assert_eq!( + Query::from_request(&Request::fake_http("GET", "/?q=b%2F42", vec![], vec![])) + .expect("request should parse to a query"), + Query { + query: "b/42".to_string(), + cs: false, + }, + ); + + assert_eq!( + Query::from_request(&Request::fake_http("GET", "/", vec![], vec![])), + None + ); +} + +#[test] +fn settings_from_cookie() { + assert_eq!( + Query::from_request(&Request::fake_http( + "GET", + "/?q=b%2F42", + vec![("Cookie".to_string(), "cs=true;".to_string())], + vec![] + )) + .expect("request should parse to a query"), + Query { + query: "b/42".to_string(), + cs: true, + }, + ); +} + +#[test] +fn settings_from_query_parameter() { + assert_eq!( + Query::from_request(&Request::fake_http( + "GET", + "/?q=b%2F42&cs=true", + vec![], + vec![] + )) + .expect("request should parse to a query"), + Query { + query: "b/42".to_string(), + cs: true, + }, + ); + + // Query parameter should override cookie + assert_eq!( + Query::from_request(&Request::fake_http( + "GET", + "/?q=b%2F42&cs=false", + vec![("Cookie".to_string(), "cs=true;".to_string())], + vec![] + )) + .expect("request should parse to a query"), + Query { + query: "b/42".to_string(), + cs: false, + }, + ); +} + +#[test] +fn depot_revision_query() { + assert_eq!( + dispatch(&handlers(), &"r/3002".into()), + Some("https://code.tvl.fyi/commit/?id=refs/r/3002".to_string()) + ); + + assert_eq!( + dispatch(&handlers(), &"something only mentioning r/3002".into()), + None, + ); + + assert_eq!(dispatch(&handlers(), &"r/invalid".into()), None,); +} |