about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock452
-rw-r--r--Cargo.toml11
-rw-r--r--src/frontend/mod.rs8
-rw-r--r--src/indieauth.rs75
-rw-r--r--src/main.rs28
-rw-r--r--src/micropub/mod.rs105
6 files changed, 486 insertions, 193 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 5d955ec..7b4a593 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -282,9 +282,9 @@ version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -310,9 +310,9 @@ version = "0.1.53"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -334,6 +334,15 @@ dependencies = [
 
 [[package]]
 name = "autocfg"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
+dependencies = [
+ "autocfg 1.1.0",
+]
+
+[[package]]
+name = "autocfg"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
@@ -554,6 +563,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "cloudabi"
+version = "0.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
 name = "colored"
 version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -732,11 +750,11 @@ dependencies = [
  "dtoa-short",
  "itoa 0.4.8",
  "matches",
- "phf",
- "proc-macro2",
- "quote",
+ "phf 0.8.0",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
  "smallvec",
- "syn",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -745,8 +763,8 @@ version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e"
 dependencies = [
- "quote",
- "syn",
+ "quote 1.0.18",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -755,8 +773,8 @@ version = "0.1.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c"
 dependencies = [
- "quote",
- "syn",
+ "quote 1.0.18",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -812,10 +830,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
 dependencies = [
  "convert_case",
- "proc-macro2",
- "quote",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
  "rustc_version 0.4.0",
- "syn",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -903,7 +921,7 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "18a857bc01b5ae04874234f6b5d16b8b8fa86910aa5777479c2669b5df607fce"
 dependencies = [
- "html5ever",
+ "html5ever 0.25.2",
  "kuchiki",
  "regex 1.5.5",
 ]
@@ -1109,9 +1127,9 @@ version = "0.3.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -1307,16 +1325,30 @@ dependencies = [
 
 [[package]]
 name = "html5ever"
+version = "0.22.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c213fa6a618dc1da552f54f85cba74b05d8e883c92ec4e89067736938084c26e"
+dependencies = [
+ "log 0.4.17",
+ "mac",
+ "markup5ever 0.7.5",
+ "proc-macro2 0.4.30",
+ "quote 0.6.13",
+ "syn 0.15.44",
+]
+
+[[package]]
+name = "html5ever"
 version = "0.25.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148"
 dependencies = [
  "log 0.4.17",
  "mac",
- "markup5ever",
- "proc-macro2",
- "quote",
- "syn",
+ "markup5ever 0.10.1",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -1448,11 +1480,9 @@ checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac"
 dependencies = [
  "http",
  "hyper",
- "log 0.4.17",
  "rustls",
  "tokio",
  "tokio-rustls",
- "webpki-roots",
 ]
 
 [[package]]
@@ -1484,7 +1514,7 @@ version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
 dependencies = [
- "autocfg",
+ "autocfg 1.1.0",
  "hashbrown",
 ]
 
@@ -1595,7 +1625,6 @@ dependencies = [
  "http-types",
  "httpmock",
  "hyper",
- "hyper-rustls",
  "kittybox-templates",
  "kittybox-util",
  "lazy_static",
@@ -1604,6 +1633,7 @@ dependencies = [
  "markdown",
  "markup",
  "mediatype",
+ "microformats",
  "mockito",
  "newbase60",
  "prometheus",
@@ -1653,7 +1683,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1ea8e9c6e031377cff82ee3001dc8026cdf431ed4e2e6b51f98ab8c73484a358"
 dependencies = [
  "cssparser",
- "html5ever",
+ "html5ever 0.25.2",
  "matches",
  "selectors",
 ]
@@ -1684,10 +1714,10 @@ dependencies = [
  "pico-args",
  "regex 1.5.5",
  "regex-syntax 0.6.25",
- "string_cache",
+ "string_cache 0.8.4",
  "term",
  "tiny-keccak",
- "unicode-xid",
+ "unicode-xid 0.2.3",
 ]
 
 [[package]]
@@ -1756,7 +1786,7 @@ version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
 dependencies = [
- "autocfg",
+ "autocfg 1.1.0",
  "scopeguard",
 ]
 
@@ -1812,9 +1842,25 @@ version = "0.12.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5948a1826d7a5ba7c550ff109894bca69b6db05ea72215f2e7d1a929b755f932"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "syn 1.0.92",
+]
+
+[[package]]
+name = "markup5ever"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "897636f9850c3eef4905a5540683ed53dc9393860f0846cab2c2ddf9939862ff"
+dependencies = [
+ "phf 0.7.24",
+ "phf_codegen 0.7.24",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "string_cache 0.7.5",
+ "string_cache_codegen 0.4.4",
+ "tendril",
 ]
 
 [[package]]
@@ -1824,10 +1870,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd"
 dependencies = [
  "log 0.4.17",
- "phf",
- "phf_codegen",
- "string_cache",
- "string_cache_codegen",
+ "phf 0.8.0",
+ "phf_codegen 0.8.0",
+ "string_cache 0.8.4",
+ "string_cache_codegen 0.5.2",
  "tendril",
 ]
 
@@ -1874,6 +1920,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 
 [[package]]
+name = "microformats"
+version = "0.2.0"
+source = "git+https://gitlab.com/maxburon/microformats-parser#bba3f07d86243aec21b378f80db1a8c29d70235d"
+dependencies = [
+ "chrono",
+ "html5ever 0.22.5",
+ "lazy_static",
+ "log 0.4.17",
+ "regex 1.5.5",
+ "serde",
+ "serde_json",
+ "thiserror",
+ "url",
+]
+
+[[package]]
 name = "mime"
 version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2006,7 +2068,7 @@ version = "0.1.45"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
 dependencies = [
- "autocfg",
+ "autocfg 1.1.0",
  "num-traits",
 ]
 
@@ -2016,7 +2078,7 @@ version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
 dependencies = [
- "autocfg",
+ "autocfg 1.1.0",
 ]
 
 [[package]]
@@ -2053,7 +2115,7 @@ version = "0.9.73"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0"
 dependencies = [
- "autocfg",
+ "autocfg 1.1.0",
  "cc",
  "libc",
  "pkg-config",
@@ -2132,6 +2194,15 @@ dependencies = [
 
 [[package]]
 name = "phf"
+version = "0.7.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18"
+dependencies = [
+ "phf_shared 0.7.24",
+]
+
+[[package]]
+name = "phf"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
@@ -2143,6 +2214,16 @@ dependencies = [
 
 [[package]]
 name = "phf_codegen"
+version = "0.7.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e"
+dependencies = [
+ "phf_generator 0.7.24",
+ "phf_shared 0.7.24",
+]
+
+[[package]]
+name = "phf_codegen"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815"
@@ -2153,6 +2234,16 @@ dependencies = [
 
 [[package]]
 name = "phf_generator"
+version = "0.7.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
+dependencies = [
+ "phf_shared 0.7.24",
+ "rand 0.6.5",
+]
+
+[[package]]
+name = "phf_generator"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
@@ -2180,9 +2271,18 @@ dependencies = [
  "phf_generator 0.8.0",
  "phf_shared 0.8.0",
  "proc-macro-hack",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "syn 1.0.92",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.7.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
+dependencies = [
+ "siphasher 0.2.3",
 ]
 
 [[package]]
@@ -2191,7 +2291,7 @@ version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
 dependencies = [
- "siphasher",
+ "siphasher 0.3.10",
 ]
 
 [[package]]
@@ -2200,7 +2300,7 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
 dependencies = [
- "siphasher",
+ "siphasher 0.3.10",
 ]
 
 [[package]]
@@ -2224,9 +2324,9 @@ version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -2297,11 +2397,20 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
 
 [[package]]
 name = "proc-macro2"
+version = "0.4.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
+dependencies = [
+ "unicode-xid 0.1.0",
+]
+
+[[package]]
+name = "proc-macro2"
 version = "1.0.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
 dependencies = [
- "unicode-xid",
+ "unicode-xid 0.2.3",
 ]
 
 [[package]]
@@ -2353,9 +2462,9 @@ checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc"
 dependencies = [
  "anyhow",
  "itertools",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -2382,11 +2491,20 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
 
 [[package]]
 name = "quote"
+version = "0.6.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
+dependencies = [
+ "proc-macro2 0.4.30",
+]
+
+[[package]]
+name = "quote"
 version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
 dependencies = [
- "proc-macro2",
+ "proc-macro2 1.0.37",
 ]
 
 [[package]]
@@ -2404,6 +2522,25 @@ dependencies = [
 
 [[package]]
 name = "rand"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
+dependencies = [
+ "autocfg 0.1.8",
+ "libc",
+ "rand_chacha 0.1.1",
+ "rand_core 0.4.2",
+ "rand_hc 0.1.0",
+ "rand_isaac",
+ "rand_jitter",
+ "rand_os",
+ "rand_pcg 0.1.2",
+ "rand_xorshift",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "rand"
 version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
@@ -2412,8 +2549,8 @@ dependencies = [
  "libc",
  "rand_chacha 0.2.2",
  "rand_core 0.5.1",
- "rand_hc",
- "rand_pcg",
+ "rand_hc 0.2.0",
+ "rand_pcg 0.2.1",
 ]
 
 [[package]]
@@ -2429,6 +2566,16 @@ dependencies = [
 
 [[package]]
 name = "rand_chacha"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
+dependencies = [
+ "autocfg 0.1.8",
+ "rand_core 0.3.1",
+]
+
+[[package]]
+name = "rand_chacha"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
@@ -2482,6 +2629,15 @@ dependencies = [
 
 [[package]]
 name = "rand_hc"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
+dependencies = [
+ "rand_core 0.3.1",
+]
+
+[[package]]
+name = "rand_hc"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
@@ -2490,6 +2646,50 @@ dependencies = [
 ]
 
 [[package]]
+name = "rand_isaac"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
+dependencies = [
+ "rand_core 0.3.1",
+]
+
+[[package]]
+name = "rand_jitter"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
+dependencies = [
+ "libc",
+ "rand_core 0.4.2",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "rand_os"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
+dependencies = [
+ "cloudabi",
+ "fuchsia-cprng",
+ "libc",
+ "rand_core 0.4.2",
+ "rdrand",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "rand_pcg"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
+dependencies = [
+ "autocfg 0.1.8",
+ "rand_core 0.4.2",
+]
+
+[[package]]
 name = "rand_pcg"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2499,6 +2699,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "rand_xorshift"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
+dependencies = [
+ "rand_core 0.3.1",
+]
+
+[[package]]
 name = "rdrand"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2775,8 +2984,8 @@ dependencies = [
  "fxhash",
  "log 0.4.17",
  "matches",
- "phf",
- "phf_codegen",
+ "phf 0.8.0",
+ "phf_codegen 0.8.0",
  "precomputed-hash",
  "servo_arc",
  "smallvec",
@@ -2819,9 +3028,9 @@ version = "1.0.137"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -2975,6 +3184,12 @@ checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3"
 
 [[package]]
 name = "siphasher"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
+
+[[package]]
+name = "siphasher"
 version = "0.3.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
@@ -3053,11 +3268,11 @@ version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
 dependencies = [
- "proc-macro2",
- "quote",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
  "serde",
  "serde_derive",
- "syn",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -3067,13 +3282,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
 dependencies = [
  "base-x",
- "proc-macro2",
- "quote",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
  "serde",
  "serde_derive",
  "serde_json",
  "sha1",
- "syn",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -3084,6 +3299,21 @@ checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
 
 [[package]]
 name = "string_cache"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89c058a82f9fd69b1becf8c274f412281038877c553182f1d02eb027045a2d67"
+dependencies = [
+ "lazy_static",
+ "new_debug_unreachable",
+ "phf_shared 0.7.24",
+ "precomputed-hash",
+ "serde",
+ "string_cache_codegen 0.4.4",
+ "string_cache_shared",
+]
+
+[[package]]
+name = "string_cache"
 version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08"
@@ -3098,17 +3328,36 @@ dependencies = [
 
 [[package]]
 name = "string_cache_codegen"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0f45ed1b65bf9a4bf2f7b7dc59212d1926e9eaf00fa998988e420fd124467c6"
+dependencies = [
+ "phf_generator 0.7.24",
+ "phf_shared 0.7.24",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "string_cache_shared",
+]
+
+[[package]]
+name = "string_cache_codegen"
 version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
 dependencies = [
  "phf_generator 0.10.0",
  "phf_shared 0.10.0",
- "proc-macro2",
- "quote",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
 ]
 
 [[package]]
+name = "string_cache_shared"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
+
+[[package]]
 name = "subtle"
 version = "2.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3116,13 +3365,24 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
 
 [[package]]
 name = "syn"
+version = "0.15.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
+dependencies = [
+ "proc-macro2 0.4.30",
+ "quote 0.6.13",
+ "unicode-xid 0.1.0",
+]
+
+[[package]]
+name = "syn"
 version = "1.0.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52"
 dependencies = [
- "proc-macro2",
- "quote",
- "unicode-xid",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "unicode-xid 0.2.3",
 ]
 
 [[package]]
@@ -3216,9 +3476,9 @@ version = "1.0.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -3292,10 +3552,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f"
 dependencies = [
  "proc-macro-hack",
- "proc-macro2",
- "quote",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
  "standback",
- "syn",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -3359,9 +3619,9 @@ version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -3529,9 +3789,9 @@ version = "0.1.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "syn 1.0.92",
 ]
 
 [[package]]
@@ -3641,6 +3901,12 @@ checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
 
 [[package]]
 name = "unicode-xid"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
+
+[[package]]
+name = "unicode-xid"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
@@ -3815,9 +4081,9 @@ dependencies = [
  "bumpalo",
  "lazy_static",
  "log 0.4.17",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "syn 1.0.92",
  "wasm-bindgen-shared",
 ]
 
@@ -3839,7 +4105,7 @@ version = "0.2.80"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5"
 dependencies = [
- "quote",
+ "quote 1.0.18",
  "wasm-bindgen-macro-support",
 ]
 
@@ -3849,9 +4115,9 @@ version = "0.2.80"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.37",
+ "quote 1.0.18",
+ "syn 1.0.92",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index 90532eb..b100649 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -104,12 +104,11 @@ version = "^2.11.0"
 features = ["http"]
 [dependencies.hyper]
 version = "^0.14.17"
-features = ["client", "stream", "runtime"]
-[dependencies.hyper-rustls]
-version = "^0.23.0"
-default-features = false
-features = ["webpki-tokio", "http1", "http2", "tls12", "logging"]
+features = ["stream", "runtime"]
 [dependencies.reqwest]
 version = "^0.11.10"
 default-features = false
-features = ["rustls-tls-webpki-roots", "gzip", "brotli", "json", "stream"]
\ No newline at end of file
+features = ["rustls-tls-webpki-roots", "gzip", "brotli", "json", "stream"]
+[dependencies.microformats]
+version = "^0.2.0"
+git = "https://gitlab.com/maxburon/microformats-parser"
diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs
index 3c3072d..eec2f85 100644
--- a/src/frontend/mod.rs
+++ b/src/frontend/mod.rs
@@ -286,8 +286,10 @@ pub fn homepage<D: Storage>(db: D, endpoints: IndiewebEndpoints) -> impl Filter<
         })
 }
 
-pub fn onboarding<D: Storage, T: hyper::client::connect::Connect + Clone + Send + Sync + 'static>(
-    db: D, endpoints: IndiewebEndpoints, http: hyper::Client<T, hyper::Body>
+pub fn onboarding<D: Storage>(
+    db: D,
+    endpoints: IndiewebEndpoints,
+    http: reqwest::Client
 ) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
     let inject_db = move || db.clone();
     warp::get()
@@ -304,7 +306,7 @@ pub fn onboarding<D: Storage, T: hyper::client::connect::Connect + Clone + Send
             .and(warp::any().map(inject_db))
             .and(warp::body::json::<OnboardingData>())
             .and(warp::any().map(move || http.clone()))
-            .and_then(|host: warp::host::Authority, db: D, body: OnboardingData, http: _| async move {
+            .and_then(|host: warp::host::Authority, db: D, body: OnboardingData, http: reqwest::Client| async move {
                 let user_uid = format!("https://{}/", host.as_str());
                 if db.post_exists(&user_uid).await.map_err(FrontendError::from)? {
                     
diff --git a/src/indieauth.rs b/src/indieauth.rs
index 4dfe11d..57c0301 100644
--- a/src/indieauth.rs
+++ b/src/indieauth.rs
@@ -62,8 +62,8 @@ impl From<serde_json::Error> for IndieAuthError {
     }
 }
 
-impl From<hyper::Error> for IndieAuthError {
-    fn from(err: hyper::Error) -> Self {
+impl From<reqwest::Error> for IndieAuthError {
+    fn from(err: reqwest::Error) -> Self {
         Self {
             msg: format!("{}", err),
             source: Some(Box::new(err)),
@@ -90,11 +90,10 @@ impl User {
     }
 }
 
-pub fn require_token<T>(token_endpoint: String, http: hyper::Client<T, hyper::Body>) -> impl Filter<Extract = (User,), Error = Rejection> + Clone
-where T: hyper::client::connect::Connect + Clone + Send + Sync + 'static {
+pub fn require_token(token_endpoint: String, http: reqwest::Client) -> impl Filter<Extract = (User,), Error = Rejection> + Clone {
     // It might be OK to panic here, because we're still inside the initialisation sequence for now.
     // Proper error handling on the top of this should be used though.
-    let token_endpoint_uri = hyper::Uri::try_from(&token_endpoint)
+    let token_endpoint_uri = url::Url::parse(&token_endpoint)
         .expect("Couldn't parse the token endpoint URI!");
     warp::any()
         .map(move || token_endpoint_uri.clone())
@@ -110,60 +109,36 @@ where T: hyper::client::connect::Connect + Clone + Send + Sync + 'static {
                 Err(err)
             }
         }).unify())
-        .and_then(|token_endpoint, http: hyper::Client<T, hyper::Body>, token| async move {
-            let request = hyper::Request::builder()
-                .method(hyper::Method::GET)
-                .uri(token_endpoint)
-                .header("Authorization", token)
-                .header("Accept", "application/json")
-                .body(hyper::Body::from(""))
-                // TODO is it acceptable to panic here?
-                .unwrap();
-
+        .and_then(|token_endpoint, http: reqwest::Client, token| async move {
             use hyper::StatusCode;
 
-            match http.request(request).await {
-                Ok(mut res) => match res.status() {
-                    StatusCode::OK => {
-                        use hyper::body::HttpBody;
-                        use bytes::BufMut;
-                        let mut buf: Vec<u8> = Vec::default();
-                        while let Some(chunk) = res.body_mut().data().await {
-                            if let Err(err) = chunk {
-                                return Err(IndieAuthError::from(err).into());
-                            }
-                            buf.put(chunk.unwrap());
-                        }
-                        match serde_json::from_slice(&buf) {
+            match http
+                .get(token_endpoint)
+                .header("Authorization", token)
+                .header("Accept", "application/json")
+                .send()
+                .await
+            {
+                Ok(res) => match res.status() {
+                    StatusCode::OK => match res.json::<serde_json::Value>().await {
+                        Ok(json) => match serde_json::from_value::<User>(json.clone()) {
                             Ok(user) => Ok(user),
                             Err(err) => {
-                                if let Ok(json) = serde_json::from_slice::<serde_json::Value>(&buf) {
-                                    if Some(false) == json["active"].as_bool() {
-                                        Err(IndieAuthError {
-                                            source: None,
-                                            kind: ErrorKind::NotAuthorized,
-                                            msg: "The token endpoint deemed the token as not \"active\".".to_string()
-                                        }.into())
-                                    } else {
-                                        Err(IndieAuthError::from(err).into())
-                                    }
+                                if let Some(false) = json["active"].as_bool() {
+                                    Err(IndieAuthError {
+                                        source: None,
+                                        kind: ErrorKind::NotAuthorized,
+                                        msg: "The token is not active for this user.".to_owned()
+                                    }.into())
                                 } else {
                                     Err(IndieAuthError::from(err).into())
                                 }
                             }
                         }
+                        Err(err) => Err(IndieAuthError::from(err).into())
                     },
                     StatusCode::BAD_REQUEST => {
-                        use hyper::body::HttpBody;
-                        use bytes::BufMut;
-                        let mut buf: Vec<u8> = Vec::default();
-                        while let Some(chunk) = res.body_mut().data().await {
-                            if let Err(err) = chunk {
-                                return Err(IndieAuthError::from(err).into());
-                            }
-                            buf.put(chunk.unwrap());
-                        }
-                        match serde_json::from_slice::<TokenEndpointError>(&buf) {
+                        match res.json::<TokenEndpointError>().await {
                             Ok(err) => {
                                 if err.error == "unauthorized" {
                                     Err(IndieAuthError {
@@ -211,8 +186,8 @@ mod tests {
     }
 
     #[inline]
-    fn get_http_client() -> hyper::Client<impl hyper::client::connect::Connect + Clone + Send + Sync + 'static, hyper::Body> {
-        hyper::Client::new()
+    fn get_http_client() -> reqwest::Client {
+        reqwest::Client::new()
     }
     
     #[tokio::test]
diff --git a/src/main.rs b/src/main.rs
index 0234abc..ed8c8e7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,15 +1,15 @@
 use log::{debug, error, info};
 use std::{convert::Infallible, env, time::Duration};
 use url::Url;
-use hyper::client::{HttpConnector,connect::dns::GaiResolver};
-use hyper_rustls::HttpsConnector;
 use warp::{Filter, host::Authority};
 
 #[tokio::main]
 async fn main() {
+    // TODO turn into a feature so I can enable and disable it
     #[cfg(debug_assertions)]
     console_subscriber::init();
-    // TODO json logging in the future?
+
+    // TODO use tracing instead of log
     let logger_env = env_logger::Env::new().filter_or("RUST_LOG", "info");
     env_logger::init_from_env(logger_env);
 
@@ -97,18 +97,6 @@ async fn main() {
             }
         };
 
-    // TODO remove this and see what screams to replace it with reqwest
-    let http_client: hyper::Client<HttpsConnector<HttpConnector<GaiResolver>>, hyper::Body> = {
-        let builder = hyper::Client::builder();
-        let https = hyper_rustls::HttpsConnectorBuilder::new()
-            .with_webpki_roots()
-            .https_only()
-            .enable_http1()
-            .enable_http2()
-            .build();
-        builder.build(https)
-    };
-
     // This thing handles redirects automatically but is type-incompatible with hyper::Client
     // Bonus: less generics to be aware of, this thing hides its complexity
     let http: reqwest::Client = {
@@ -119,7 +107,7 @@ async fn main() {
                 "/",
                 env!("CARGO_PKG_VERSION")
             ));
-        // TODO add a root certificate if there's an environment variable pointing at it
+        // TODO: add a root certificate if there's an environment variable pointing at it
         //builder = builder.add_root_certificate(reqwest::Certificate::from_pem(todo!()));
 
         builder.build().unwrap()
@@ -155,14 +143,18 @@ async fn main() {
 
         let onboarding = warp::path("onboarding")
             .and(warp::path::end())
-            .and(kittybox::frontend::onboarding(database.clone(), endpoints.clone(), http_client.clone()));
+            .and(kittybox::frontend::onboarding(
+                database.clone(),
+                endpoints.clone(),
+                http.clone()
+            ));
         
         let micropub = warp::path("micropub")
             .and(warp::path::end()
                  .and(kittybox::micropub::micropub(
                      database.clone(),
                      token_endpoint.to_string(),
-                     http_client.clone()
+                     http.clone()
                  ))
                  .or(warp::get()
                      .and(warp::path("client"))
diff --git a/src/micropub/mod.rs b/src/micropub/mod.rs
index 7aad51a..7175e56 100644
--- a/src/micropub/mod.rs
+++ b/src/micropub/mod.rs
@@ -51,7 +51,7 @@ impl From<StorageError> for MicropubError {
                 crate::database::ErrorKind::NotFound => ErrorType::NotFound,
                 _ => ErrorType::InternalServerError
             },
-            error_description: format!("Backend error: {}", err.to_string())
+            error_description: format!("Backend error: {}", err)
         }
     }
 }
@@ -158,12 +158,12 @@ mod util {
 }
 
 // TODO actually save the post to the database and schedule post-processing
-pub(crate) async fn _post<D: Storage, T: hyper::client::connect::Connect + Clone + Send + Sync + 'static>(
+pub(crate) async fn _post<D: Storage>(
     user: crate::indieauth::User,
     uid: String,
     mf2: serde_json::Value,
     db: D,
-    http: hyper::Client<T, hyper::Body>
+    http: reqwest::Client
 ) -> Result<impl warp::Reply, MicropubError> {
     // Here, we have the following guarantees:
     // - The user is the same user for this host (guaranteed by ensure_same_user)
@@ -248,23 +248,78 @@ pub(crate) async fn _post<D: Storage, T: hyper::client::connect::Connect + Clone
         use bytes::{Buf, BufMut};
         use futures_util::StreamExt;
 
-        let mut contextually_significant_posts: Vec<hyper::Uri> = vec![];
+        let uid: &str = mf2["properties"]["uid"][0].as_str().unwrap();
+
+        let mut contextually_significant_posts: Vec<url::Url> = vec![];
         for prop in &["in-reply-to", "like-of", "repost-of", "bookmark-of"] {
             if let Some(array) = mf2["properties"][prop].as_array() {
                 contextually_significant_posts.extend(
                     array
                         .iter()
-                        .filter_map(|v| v.as_str().and_then(|v| v.parse::<hyper::Uri>().ok())),
+                        .filter_map(|v| v.as_str())
+                        .filter_map(|v| v.parse::<url::Url>().ok()),
                 );
             }
         }
+        // TODO parse HTML in e-content and add links found here
         contextually_significant_posts.sort_unstable_by_key(|u| u.to_string());
         contextually_significant_posts.dedup();
 
-        // TODO: Make a stream to fetch all these posts and convert them to MF2
-        drop(http);
+        #[derive(Debug)]
+        #[allow(dead_code)]
+        struct FetchedPostContext {
+            url: url::Url,
+            // TODO see if we can use non-strings for non-UTF-8 HTML
+            html: String,
+            mf2: serde_json::Value,
+            webmention: Option<hyper::Uri>
+        }
+
+        {
+            // TODO: Make a stream to fetch all these posts and convert them to MF2
+            let post_contexts = {
+                let http = &http;
+                tokio_stream::iter(contextually_significant_posts
+                                   .into_iter()
+                ).then(move |url: url::Url| async move {
+                    let html: String = todo!("Fetch the post using {:?}", http);
+                    // We just need to get the following here:
+                    // 1. We need to preserve the URL
+                    // 2. We need to get the HTML for MF2 processing
+                    // 3. We need to get the webmention endpoint address
+                    // All of that can be done in one go.
+
+                    // XXX stub!
+
+                    dbg!(FetchedPostContext {
+                        url, html,
+                        mf2: serde_json::to_value(microformats::from_html(&html, url).unwrap()).unwrap(),
+                        webmention: None
+                    })
+                })
+                    .collect::<Vec<FetchedPostContext>>()
+                    .await
+            };
 
-        todo!()
+            drop(post_contexts);
+        }
+        // At this point we can start syndicating the post.
+        // Currently we don't really support any syndication endpoints, but still!
+        if let Some(syndicate_to) = mf2["properties"]["mp-syndicate-to"].as_array() {
+            let http = &http;
+            tokio_stream::iter(syndicate_to)
+                .filter_map(|i| futures::future::ready(i.as_str()))
+                .for_each_concurrent(3, |s: &str| async move {
+                    #[allow(clippy::match_single_binding)]
+                    match s {
+                        _ => {
+                            todo!("Syndicate to generic webmention-aware service {}", s);
+                        }
+                        // TODO special handling for non-webmention-aware services like the birdsite
+                    }
+                })
+                .await;
+        }
     });
     
     Ok(reply)
@@ -378,11 +433,10 @@ async fn check_auth(host: warp::host::Authority, user: User) -> Result<User, war
 }
 
 #[cfg(any(not(debug_assertions), test))]
-fn ensure_same_user_as_host<T>(
+fn ensure_same_user_as_host(
     token_endpoint: String,
-    http: hyper::Client<T, hyper::Body>
-) -> impl Filter<Extract = (User,), Error = warp::Rejection> + Clone
-where T: hyper::client::connect::Connect + Clone + Send + Sync + 'static {
+    http: reqwest::Client
+) -> impl Filter<Extract = (User,), Error = warp::Rejection> + Clone {
     crate::util::require_host()
         .and(crate::indieauth::require_token(token_endpoint, http))
         .and_then(check_auth)
@@ -443,12 +497,11 @@ async fn dispatch_post_body(
 }
 
 #[cfg_attr(all(debug_assertions, not(test)), allow(unused_variables))]
-pub fn post<D: 'static + Storage, T>(
+pub fn post<D: 'static + Storage>(
     db: D,
     token_endpoint: String,
-    http: hyper::Client<T, hyper::Body>
-) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone
-where T: hyper::client::connect::Connect + Clone + Send + Sync + 'static {
+    http: reqwest::Client
+) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
     let inject_db = warp::any().map(move || db.clone());
     #[cfg(all(debug_assertions, not(test)))]
     let ensure_same_user = warp::any().map(|| crate::indieauth::User::new(
@@ -467,7 +520,7 @@ where T: hyper::client::connect::Connect + Clone + Send + Sync + 'static {
         .and(inject_db)
         .and(warp::any().map(move || http.clone()))
         .and(ensure_same_user)
-        .and_then(|body: Either<MicropubAction, serde_json::Value>, db: D, http: hyper::Client<T, hyper::Body>, user: crate::indieauth::User| async move {
+        .and_then(|body: Either<MicropubAction, serde_json::Value>, db: D, http: reqwest::Client, user: crate::indieauth::User| async move {
             (match body {
                 Either::Left(action) => {
                     post_action(action, db, user).await.map(|p| Box::new(p) as Box<dyn warp::Reply>)
@@ -588,8 +641,11 @@ async fn _query<D: Storage>(
     }
 }
 
-pub fn query<D: Storage, T>(db: D, token_endpoint: String, http: hyper::Client<T, hyper::Body>) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone
-where T: hyper::client::connect::Connect + Clone + Send + Sync + 'static {
+pub fn query<D: Storage>(
+    db: D,
+    token_endpoint: String,
+    http: reqwest::Client
+) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
     warp::get()
         .map(move || db.clone())
         .and(warp::query::<MicropubQuery>())
@@ -626,8 +682,11 @@ pub async fn recover(err: Rejection) -> Result<impl warp::Reply, Infallible> {
     Ok(warp::reply::with_status(warp::reply::json(&error), error.into()))
 }
 
-pub fn micropub<D: 'static + Storage, T>(db: D, token_endpoint: String, http: hyper::Client<T, hyper::Body>) -> impl Filter<Extract = (impl warp::Reply,), Error = Infallible> + Clone
-where T: hyper::client::connect::Connect + Clone + Send + Sync + 'static {
+pub fn micropub<D: 'static + Storage>(
+    db: D,
+    token_endpoint: String,
+    http: reqwest::Client
+) -> impl Filter<Extract = (impl warp::Reply,), Error = Infallible> + Clone {
     query(db.clone(), token_endpoint.clone(), http.clone())
         .or(post(db, token_endpoint, http))
         .or(options())
@@ -685,7 +744,7 @@ mod tests {
                         let (uid, mf2) = super::post::normalize_mf2(post, &user);
 
                         super::_post(
-                            user, uid, mf2, db, hyper::Client::new()
+                            user, uid, mf2, db, reqwest::Client::new()
                         ).await.map_err(warp::reject::custom)
                     })
             )
@@ -730,7 +789,7 @@ mod tests {
                         let (uid, mf2) = super::post::normalize_mf2(post, &user);
 
                         super::_post(
-                            user, uid, mf2, db, hyper::Client::new()
+                            user, uid, mf2, db, reqwest::Client::new()
                         ).await.map_err(warp::reject::custom)
                     })
             )