├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE-MIT ├── LICENSE_APACHE ├── README.md ├── src ├── cf.rs ├── cf_base.rs ├── lib.rs └── utils.rs └── wrangler_example.toml /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | wasm-pack.log 4 | build/ 5 | /wrangler.toml -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 19 | 20 | [[package]] 21 | name = "android-tzdata" 22 | version = "0.1.1" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 25 | 26 | [[package]] 27 | name = "android_system_properties" 28 | version = "0.1.5" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 31 | dependencies = [ 32 | "libc", 33 | ] 34 | 35 | [[package]] 36 | name = "anyhow" 37 | version = "1.0.95" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" 40 | 41 | [[package]] 42 | name = "async-trait" 43 | version = "0.1.86" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" 46 | dependencies = [ 47 | "proc-macro2", 48 | "quote", 49 | "syn", 50 | ] 51 | 52 | [[package]] 53 | name = "autocfg" 54 | version = "1.4.0" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 57 | 58 | [[package]] 59 | name = "backtrace" 60 | version = "0.3.74" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 63 | dependencies = [ 64 | "addr2line", 65 | "cfg-if", 66 | "libc", 67 | "miniz_oxide", 68 | "object", 69 | "rustc-demangle", 70 | "windows-targets", 71 | ] 72 | 73 | [[package]] 74 | name = "base64" 75 | version = "0.22.1" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 78 | 79 | [[package]] 80 | name = "bumpalo" 81 | version = "3.17.0" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" 84 | 85 | [[package]] 86 | name = "byteorder" 87 | version = "1.5.0" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 90 | 91 | [[package]] 92 | name = "bytes" 93 | version = "1.10.0" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" 96 | 97 | [[package]] 98 | name = "cc" 99 | version = "1.2.13" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | checksum = "c7777341816418c02e033934a09f20dc0ccaf65a5201ef8a450ae0105a573fda" 102 | dependencies = [ 103 | "shlex", 104 | ] 105 | 106 | [[package]] 107 | name = "cfg-if" 108 | version = "1.0.0" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 111 | 112 | [[package]] 113 | name = "cfg_aliases" 114 | version = "0.2.1" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 117 | 118 | [[package]] 119 | name = "chrono" 120 | version = "0.4.39" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" 123 | dependencies = [ 124 | "android-tzdata", 125 | "iana-time-zone", 126 | "js-sys", 127 | "num-traits", 128 | "serde", 129 | "wasm-bindgen", 130 | "windows-targets", 131 | ] 132 | 133 | [[package]] 134 | name = "console_error_panic_hook" 135 | version = "0.1.7" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" 138 | dependencies = [ 139 | "cfg-if", 140 | "wasm-bindgen", 141 | ] 142 | 143 | [[package]] 144 | name = "constant_time_eq" 145 | version = "0.3.1" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" 148 | 149 | [[package]] 150 | name = "core-foundation-sys" 151 | version = "0.8.7" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 154 | 155 | [[package]] 156 | name = "darling" 157 | version = "0.20.10" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" 160 | dependencies = [ 161 | "darling_core", 162 | "darling_macro", 163 | ] 164 | 165 | [[package]] 166 | name = "darling_core" 167 | version = "0.20.10" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" 170 | dependencies = [ 171 | "fnv", 172 | "ident_case", 173 | "proc-macro2", 174 | "quote", 175 | "strsim", 176 | "syn", 177 | ] 178 | 179 | [[package]] 180 | name = "darling_macro" 181 | version = "0.20.10" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" 184 | dependencies = [ 185 | "darling_core", 186 | "quote", 187 | "syn", 188 | ] 189 | 190 | [[package]] 191 | name = "ddns" 192 | version = "0.2.0" 193 | dependencies = [ 194 | "anyhow", 195 | "cfg-if", 196 | "chrono", 197 | "console_error_panic_hook", 198 | "constant_time_eq", 199 | "reqwest", 200 | "serde", 201 | "serde_json", 202 | "serde_with", 203 | "tokio", 204 | "worker", 205 | ] 206 | 207 | [[package]] 208 | name = "deranged" 209 | version = "0.3.11" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" 212 | dependencies = [ 213 | "powerfmt", 214 | "serde", 215 | ] 216 | 217 | [[package]] 218 | name = "displaydoc" 219 | version = "0.2.5" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 222 | dependencies = [ 223 | "proc-macro2", 224 | "quote", 225 | "syn", 226 | ] 227 | 228 | [[package]] 229 | name = "equivalent" 230 | version = "1.0.1" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 233 | 234 | [[package]] 235 | name = "fnv" 236 | version = "1.0.7" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 239 | 240 | [[package]] 241 | name = "form_urlencoded" 242 | version = "1.2.1" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 245 | dependencies = [ 246 | "percent-encoding", 247 | ] 248 | 249 | [[package]] 250 | name = "futures-channel" 251 | version = "0.3.31" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 254 | dependencies = [ 255 | "futures-core", 256 | ] 257 | 258 | [[package]] 259 | name = "futures-core" 260 | version = "0.3.31" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 263 | 264 | [[package]] 265 | name = "futures-io" 266 | version = "0.3.31" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 269 | 270 | [[package]] 271 | name = "futures-macro" 272 | version = "0.3.31" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 275 | dependencies = [ 276 | "proc-macro2", 277 | "quote", 278 | "syn", 279 | ] 280 | 281 | [[package]] 282 | name = "futures-sink" 283 | version = "0.3.31" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 286 | 287 | [[package]] 288 | name = "futures-task" 289 | version = "0.3.31" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 292 | 293 | [[package]] 294 | name = "futures-util" 295 | version = "0.3.31" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 298 | dependencies = [ 299 | "futures-core", 300 | "futures-io", 301 | "futures-macro", 302 | "futures-sink", 303 | "futures-task", 304 | "memchr", 305 | "pin-project-lite", 306 | "pin-utils", 307 | "slab", 308 | ] 309 | 310 | [[package]] 311 | name = "getrandom" 312 | version = "0.2.15" 313 | source = "registry+https://github.com/rust-lang/crates.io-index" 314 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 315 | dependencies = [ 316 | "cfg-if", 317 | "js-sys", 318 | "libc", 319 | "wasi", 320 | "wasm-bindgen", 321 | ] 322 | 323 | [[package]] 324 | name = "gimli" 325 | version = "0.31.1" 326 | source = "registry+https://github.com/rust-lang/crates.io-index" 327 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 328 | 329 | [[package]] 330 | name = "hashbrown" 331 | version = "0.12.3" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 334 | 335 | [[package]] 336 | name = "hashbrown" 337 | version = "0.15.2" 338 | source = "registry+https://github.com/rust-lang/crates.io-index" 339 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 340 | 341 | [[package]] 342 | name = "hex" 343 | version = "0.4.3" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 346 | 347 | [[package]] 348 | name = "http" 349 | version = "1.2.0" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" 352 | dependencies = [ 353 | "bytes", 354 | "fnv", 355 | "itoa", 356 | ] 357 | 358 | [[package]] 359 | name = "http-body" 360 | version = "1.0.1" 361 | source = "registry+https://github.com/rust-lang/crates.io-index" 362 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 363 | dependencies = [ 364 | "bytes", 365 | "http", 366 | ] 367 | 368 | [[package]] 369 | name = "http-body-util" 370 | version = "0.1.2" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" 373 | dependencies = [ 374 | "bytes", 375 | "futures-util", 376 | "http", 377 | "http-body", 378 | "pin-project-lite", 379 | ] 380 | 381 | [[package]] 382 | name = "httparse" 383 | version = "1.10.0" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" 386 | 387 | [[package]] 388 | name = "hyper" 389 | version = "1.6.0" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" 392 | dependencies = [ 393 | "bytes", 394 | "futures-channel", 395 | "futures-util", 396 | "http", 397 | "http-body", 398 | "httparse", 399 | "itoa", 400 | "pin-project-lite", 401 | "smallvec", 402 | "tokio", 403 | "want", 404 | ] 405 | 406 | [[package]] 407 | name = "hyper-rustls" 408 | version = "0.27.5" 409 | source = "registry+https://github.com/rust-lang/crates.io-index" 410 | checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" 411 | dependencies = [ 412 | "futures-util", 413 | "http", 414 | "hyper", 415 | "hyper-util", 416 | "rustls", 417 | "rustls-pki-types", 418 | "tokio", 419 | "tokio-rustls", 420 | "tower-service", 421 | "webpki-roots", 422 | ] 423 | 424 | [[package]] 425 | name = "hyper-util" 426 | version = "0.1.10" 427 | source = "registry+https://github.com/rust-lang/crates.io-index" 428 | checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" 429 | dependencies = [ 430 | "bytes", 431 | "futures-channel", 432 | "futures-util", 433 | "http", 434 | "http-body", 435 | "hyper", 436 | "pin-project-lite", 437 | "socket2", 438 | "tokio", 439 | "tower-service", 440 | "tracing", 441 | ] 442 | 443 | [[package]] 444 | name = "iana-time-zone" 445 | version = "0.1.61" 446 | source = "registry+https://github.com/rust-lang/crates.io-index" 447 | checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" 448 | dependencies = [ 449 | "android_system_properties", 450 | "core-foundation-sys", 451 | "iana-time-zone-haiku", 452 | "js-sys", 453 | "wasm-bindgen", 454 | "windows-core", 455 | ] 456 | 457 | [[package]] 458 | name = "iana-time-zone-haiku" 459 | version = "0.1.2" 460 | source = "registry+https://github.com/rust-lang/crates.io-index" 461 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 462 | dependencies = [ 463 | "cc", 464 | ] 465 | 466 | [[package]] 467 | name = "icu_collections" 468 | version = "1.5.0" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" 471 | dependencies = [ 472 | "displaydoc", 473 | "yoke", 474 | "zerofrom", 475 | "zerovec", 476 | ] 477 | 478 | [[package]] 479 | name = "icu_locid" 480 | version = "1.5.0" 481 | source = "registry+https://github.com/rust-lang/crates.io-index" 482 | checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" 483 | dependencies = [ 484 | "displaydoc", 485 | "litemap", 486 | "tinystr", 487 | "writeable", 488 | "zerovec", 489 | ] 490 | 491 | [[package]] 492 | name = "icu_locid_transform" 493 | version = "1.5.0" 494 | source = "registry+https://github.com/rust-lang/crates.io-index" 495 | checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" 496 | dependencies = [ 497 | "displaydoc", 498 | "icu_locid", 499 | "icu_locid_transform_data", 500 | "icu_provider", 501 | "tinystr", 502 | "zerovec", 503 | ] 504 | 505 | [[package]] 506 | name = "icu_locid_transform_data" 507 | version = "1.5.0" 508 | source = "registry+https://github.com/rust-lang/crates.io-index" 509 | checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" 510 | 511 | [[package]] 512 | name = "icu_normalizer" 513 | version = "1.5.0" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" 516 | dependencies = [ 517 | "displaydoc", 518 | "icu_collections", 519 | "icu_normalizer_data", 520 | "icu_properties", 521 | "icu_provider", 522 | "smallvec", 523 | "utf16_iter", 524 | "utf8_iter", 525 | "write16", 526 | "zerovec", 527 | ] 528 | 529 | [[package]] 530 | name = "icu_normalizer_data" 531 | version = "1.5.0" 532 | source = "registry+https://github.com/rust-lang/crates.io-index" 533 | checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" 534 | 535 | [[package]] 536 | name = "icu_properties" 537 | version = "1.5.1" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" 540 | dependencies = [ 541 | "displaydoc", 542 | "icu_collections", 543 | "icu_locid_transform", 544 | "icu_properties_data", 545 | "icu_provider", 546 | "tinystr", 547 | "zerovec", 548 | ] 549 | 550 | [[package]] 551 | name = "icu_properties_data" 552 | version = "1.5.0" 553 | source = "registry+https://github.com/rust-lang/crates.io-index" 554 | checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" 555 | 556 | [[package]] 557 | name = "icu_provider" 558 | version = "1.5.0" 559 | source = "registry+https://github.com/rust-lang/crates.io-index" 560 | checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" 561 | dependencies = [ 562 | "displaydoc", 563 | "icu_locid", 564 | "icu_provider_macros", 565 | "stable_deref_trait", 566 | "tinystr", 567 | "writeable", 568 | "yoke", 569 | "zerofrom", 570 | "zerovec", 571 | ] 572 | 573 | [[package]] 574 | name = "icu_provider_macros" 575 | version = "1.5.0" 576 | source = "registry+https://github.com/rust-lang/crates.io-index" 577 | checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" 578 | dependencies = [ 579 | "proc-macro2", 580 | "quote", 581 | "syn", 582 | ] 583 | 584 | [[package]] 585 | name = "ident_case" 586 | version = "1.0.1" 587 | source = "registry+https://github.com/rust-lang/crates.io-index" 588 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 589 | 590 | [[package]] 591 | name = "idna" 592 | version = "1.0.3" 593 | source = "registry+https://github.com/rust-lang/crates.io-index" 594 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 595 | dependencies = [ 596 | "idna_adapter", 597 | "smallvec", 598 | "utf8_iter", 599 | ] 600 | 601 | [[package]] 602 | name = "idna_adapter" 603 | version = "1.2.0" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" 606 | dependencies = [ 607 | "icu_normalizer", 608 | "icu_properties", 609 | ] 610 | 611 | [[package]] 612 | name = "indexmap" 613 | version = "1.9.3" 614 | source = "registry+https://github.com/rust-lang/crates.io-index" 615 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 616 | dependencies = [ 617 | "autocfg", 618 | "hashbrown 0.12.3", 619 | "serde", 620 | ] 621 | 622 | [[package]] 623 | name = "indexmap" 624 | version = "2.7.1" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" 627 | dependencies = [ 628 | "equivalent", 629 | "hashbrown 0.15.2", 630 | "serde", 631 | ] 632 | 633 | [[package]] 634 | name = "ipnet" 635 | version = "2.11.0" 636 | source = "registry+https://github.com/rust-lang/crates.io-index" 637 | checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" 638 | 639 | [[package]] 640 | name = "itoa" 641 | version = "1.0.14" 642 | source = "registry+https://github.com/rust-lang/crates.io-index" 643 | checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" 644 | 645 | [[package]] 646 | name = "js-sys" 647 | version = "0.3.77" 648 | source = "registry+https://github.com/rust-lang/crates.io-index" 649 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 650 | dependencies = [ 651 | "once_cell", 652 | "wasm-bindgen", 653 | ] 654 | 655 | [[package]] 656 | name = "libc" 657 | version = "0.2.169" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" 660 | 661 | [[package]] 662 | name = "litemap" 663 | version = "0.7.4" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" 666 | 667 | [[package]] 668 | name = "log" 669 | version = "0.4.25" 670 | source = "registry+https://github.com/rust-lang/crates.io-index" 671 | checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" 672 | 673 | [[package]] 674 | name = "matchit" 675 | version = "0.7.3" 676 | source = "registry+https://github.com/rust-lang/crates.io-index" 677 | checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" 678 | 679 | [[package]] 680 | name = "memchr" 681 | version = "2.7.4" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 684 | 685 | [[package]] 686 | name = "mime" 687 | version = "0.3.17" 688 | source = "registry+https://github.com/rust-lang/crates.io-index" 689 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 690 | 691 | [[package]] 692 | name = "miniz_oxide" 693 | version = "0.8.3" 694 | source = "registry+https://github.com/rust-lang/crates.io-index" 695 | checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" 696 | dependencies = [ 697 | "adler2", 698 | ] 699 | 700 | [[package]] 701 | name = "mio" 702 | version = "1.0.3" 703 | source = "registry+https://github.com/rust-lang/crates.io-index" 704 | checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" 705 | dependencies = [ 706 | "libc", 707 | "wasi", 708 | "windows-sys 0.52.0", 709 | ] 710 | 711 | [[package]] 712 | name = "num-conv" 713 | version = "0.1.0" 714 | source = "registry+https://github.com/rust-lang/crates.io-index" 715 | checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" 716 | 717 | [[package]] 718 | name = "num-traits" 719 | version = "0.2.19" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 722 | dependencies = [ 723 | "autocfg", 724 | ] 725 | 726 | [[package]] 727 | name = "object" 728 | version = "0.36.7" 729 | source = "registry+https://github.com/rust-lang/crates.io-index" 730 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 731 | dependencies = [ 732 | "memchr", 733 | ] 734 | 735 | [[package]] 736 | name = "once_cell" 737 | version = "1.20.3" 738 | source = "registry+https://github.com/rust-lang/crates.io-index" 739 | checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" 740 | 741 | [[package]] 742 | name = "percent-encoding" 743 | version = "2.3.1" 744 | source = "registry+https://github.com/rust-lang/crates.io-index" 745 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 746 | 747 | [[package]] 748 | name = "pin-project" 749 | version = "1.1.9" 750 | source = "registry+https://github.com/rust-lang/crates.io-index" 751 | checksum = "dfe2e71e1471fe07709406bf725f710b02927c9c54b2b5b2ec0e8087d97c327d" 752 | dependencies = [ 753 | "pin-project-internal", 754 | ] 755 | 756 | [[package]] 757 | name = "pin-project-internal" 758 | version = "1.1.9" 759 | source = "registry+https://github.com/rust-lang/crates.io-index" 760 | checksum = "f6e859e6e5bd50440ab63c47e3ebabc90f26251f7c73c3d3e837b74a1cc3fa67" 761 | dependencies = [ 762 | "proc-macro2", 763 | "quote", 764 | "syn", 765 | ] 766 | 767 | [[package]] 768 | name = "pin-project-lite" 769 | version = "0.2.16" 770 | source = "registry+https://github.com/rust-lang/crates.io-index" 771 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 772 | 773 | [[package]] 774 | name = "pin-utils" 775 | version = "0.1.0" 776 | source = "registry+https://github.com/rust-lang/crates.io-index" 777 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 778 | 779 | [[package]] 780 | name = "powerfmt" 781 | version = "0.2.0" 782 | source = "registry+https://github.com/rust-lang/crates.io-index" 783 | checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 784 | 785 | [[package]] 786 | name = "ppv-lite86" 787 | version = "0.2.20" 788 | source = "registry+https://github.com/rust-lang/crates.io-index" 789 | checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" 790 | dependencies = [ 791 | "zerocopy", 792 | ] 793 | 794 | [[package]] 795 | name = "proc-macro2" 796 | version = "1.0.93" 797 | source = "registry+https://github.com/rust-lang/crates.io-index" 798 | checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" 799 | dependencies = [ 800 | "unicode-ident", 801 | ] 802 | 803 | [[package]] 804 | name = "quinn" 805 | version = "0.11.6" 806 | source = "registry+https://github.com/rust-lang/crates.io-index" 807 | checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" 808 | dependencies = [ 809 | "bytes", 810 | "pin-project-lite", 811 | "quinn-proto", 812 | "quinn-udp", 813 | "rustc-hash", 814 | "rustls", 815 | "socket2", 816 | "thiserror 2.0.11", 817 | "tokio", 818 | "tracing", 819 | ] 820 | 821 | [[package]] 822 | name = "quinn-proto" 823 | version = "0.11.9" 824 | source = "registry+https://github.com/rust-lang/crates.io-index" 825 | checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" 826 | dependencies = [ 827 | "bytes", 828 | "getrandom", 829 | "rand", 830 | "ring", 831 | "rustc-hash", 832 | "rustls", 833 | "rustls-pki-types", 834 | "slab", 835 | "thiserror 2.0.11", 836 | "tinyvec", 837 | "tracing", 838 | "web-time", 839 | ] 840 | 841 | [[package]] 842 | name = "quinn-udp" 843 | version = "0.5.9" 844 | source = "registry+https://github.com/rust-lang/crates.io-index" 845 | checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904" 846 | dependencies = [ 847 | "cfg_aliases", 848 | "libc", 849 | "once_cell", 850 | "socket2", 851 | "tracing", 852 | "windows-sys 0.59.0", 853 | ] 854 | 855 | [[package]] 856 | name = "quote" 857 | version = "1.0.38" 858 | source = "registry+https://github.com/rust-lang/crates.io-index" 859 | checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" 860 | dependencies = [ 861 | "proc-macro2", 862 | ] 863 | 864 | [[package]] 865 | name = "rand" 866 | version = "0.8.5" 867 | source = "registry+https://github.com/rust-lang/crates.io-index" 868 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 869 | dependencies = [ 870 | "libc", 871 | "rand_chacha", 872 | "rand_core", 873 | ] 874 | 875 | [[package]] 876 | name = "rand_chacha" 877 | version = "0.3.1" 878 | source = "registry+https://github.com/rust-lang/crates.io-index" 879 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 880 | dependencies = [ 881 | "ppv-lite86", 882 | "rand_core", 883 | ] 884 | 885 | [[package]] 886 | name = "rand_core" 887 | version = "0.6.4" 888 | source = "registry+https://github.com/rust-lang/crates.io-index" 889 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 890 | dependencies = [ 891 | "getrandom", 892 | ] 893 | 894 | [[package]] 895 | name = "reqwest" 896 | version = "0.12.12" 897 | source = "registry+https://github.com/rust-lang/crates.io-index" 898 | checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" 899 | dependencies = [ 900 | "base64", 901 | "bytes", 902 | "futures-core", 903 | "futures-util", 904 | "http", 905 | "http-body", 906 | "http-body-util", 907 | "hyper", 908 | "hyper-rustls", 909 | "hyper-util", 910 | "ipnet", 911 | "js-sys", 912 | "log", 913 | "mime", 914 | "once_cell", 915 | "percent-encoding", 916 | "pin-project-lite", 917 | "quinn", 918 | "rustls", 919 | "rustls-pemfile", 920 | "rustls-pki-types", 921 | "serde", 922 | "serde_json", 923 | "serde_urlencoded", 924 | "sync_wrapper", 925 | "tokio", 926 | "tokio-rustls", 927 | "tower", 928 | "tower-service", 929 | "url", 930 | "wasm-bindgen", 931 | "wasm-bindgen-futures", 932 | "web-sys", 933 | "webpki-roots", 934 | "windows-registry", 935 | ] 936 | 937 | [[package]] 938 | name = "ring" 939 | version = "0.17.8" 940 | source = "registry+https://github.com/rust-lang/crates.io-index" 941 | checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" 942 | dependencies = [ 943 | "cc", 944 | "cfg-if", 945 | "getrandom", 946 | "libc", 947 | "spin", 948 | "untrusted", 949 | "windows-sys 0.52.0", 950 | ] 951 | 952 | [[package]] 953 | name = "rustc-demangle" 954 | version = "0.1.24" 955 | source = "registry+https://github.com/rust-lang/crates.io-index" 956 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 957 | 958 | [[package]] 959 | name = "rustc-hash" 960 | version = "2.1.1" 961 | source = "registry+https://github.com/rust-lang/crates.io-index" 962 | checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" 963 | 964 | [[package]] 965 | name = "rustls" 966 | version = "0.23.22" 967 | source = "registry+https://github.com/rust-lang/crates.io-index" 968 | checksum = "9fb9263ab4eb695e42321db096e3b8fbd715a59b154d5c88d82db2175b681ba7" 969 | dependencies = [ 970 | "once_cell", 971 | "ring", 972 | "rustls-pki-types", 973 | "rustls-webpki", 974 | "subtle", 975 | "zeroize", 976 | ] 977 | 978 | [[package]] 979 | name = "rustls-pemfile" 980 | version = "2.2.0" 981 | source = "registry+https://github.com/rust-lang/crates.io-index" 982 | checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" 983 | dependencies = [ 984 | "rustls-pki-types", 985 | ] 986 | 987 | [[package]] 988 | name = "rustls-pki-types" 989 | version = "1.11.0" 990 | source = "registry+https://github.com/rust-lang/crates.io-index" 991 | checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" 992 | dependencies = [ 993 | "web-time", 994 | ] 995 | 996 | [[package]] 997 | name = "rustls-webpki" 998 | version = "0.102.8" 999 | source = "registry+https://github.com/rust-lang/crates.io-index" 1000 | checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" 1001 | dependencies = [ 1002 | "ring", 1003 | "rustls-pki-types", 1004 | "untrusted", 1005 | ] 1006 | 1007 | [[package]] 1008 | name = "rustversion" 1009 | version = "1.0.19" 1010 | source = "registry+https://github.com/rust-lang/crates.io-index" 1011 | checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" 1012 | 1013 | [[package]] 1014 | name = "ryu" 1015 | version = "1.0.19" 1016 | source = "registry+https://github.com/rust-lang/crates.io-index" 1017 | checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" 1018 | 1019 | [[package]] 1020 | name = "serde" 1021 | version = "1.0.217" 1022 | source = "registry+https://github.com/rust-lang/crates.io-index" 1023 | checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" 1024 | dependencies = [ 1025 | "serde_derive", 1026 | ] 1027 | 1028 | [[package]] 1029 | name = "serde-wasm-bindgen" 1030 | version = "0.5.0" 1031 | source = "registry+https://github.com/rust-lang/crates.io-index" 1032 | checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" 1033 | dependencies = [ 1034 | "js-sys", 1035 | "serde", 1036 | "wasm-bindgen", 1037 | ] 1038 | 1039 | [[package]] 1040 | name = "serde-wasm-bindgen" 1041 | version = "0.6.5" 1042 | source = "registry+https://github.com/rust-lang/crates.io-index" 1043 | checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" 1044 | dependencies = [ 1045 | "js-sys", 1046 | "serde", 1047 | "wasm-bindgen", 1048 | ] 1049 | 1050 | [[package]] 1051 | name = "serde_derive" 1052 | version = "1.0.217" 1053 | source = "registry+https://github.com/rust-lang/crates.io-index" 1054 | checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" 1055 | dependencies = [ 1056 | "proc-macro2", 1057 | "quote", 1058 | "syn", 1059 | ] 1060 | 1061 | [[package]] 1062 | name = "serde_json" 1063 | version = "1.0.138" 1064 | source = "registry+https://github.com/rust-lang/crates.io-index" 1065 | checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" 1066 | dependencies = [ 1067 | "itoa", 1068 | "memchr", 1069 | "ryu", 1070 | "serde", 1071 | ] 1072 | 1073 | [[package]] 1074 | name = "serde_urlencoded" 1075 | version = "0.7.1" 1076 | source = "registry+https://github.com/rust-lang/crates.io-index" 1077 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1078 | dependencies = [ 1079 | "form_urlencoded", 1080 | "itoa", 1081 | "ryu", 1082 | "serde", 1083 | ] 1084 | 1085 | [[package]] 1086 | name = "serde_with" 1087 | version = "3.12.0" 1088 | source = "registry+https://github.com/rust-lang/crates.io-index" 1089 | checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" 1090 | dependencies = [ 1091 | "base64", 1092 | "chrono", 1093 | "hex", 1094 | "indexmap 1.9.3", 1095 | "indexmap 2.7.1", 1096 | "serde", 1097 | "serde_derive", 1098 | "serde_json", 1099 | "serde_with_macros", 1100 | "time", 1101 | ] 1102 | 1103 | [[package]] 1104 | name = "serde_with_macros" 1105 | version = "3.12.0" 1106 | source = "registry+https://github.com/rust-lang/crates.io-index" 1107 | checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" 1108 | dependencies = [ 1109 | "darling", 1110 | "proc-macro2", 1111 | "quote", 1112 | "syn", 1113 | ] 1114 | 1115 | [[package]] 1116 | name = "shlex" 1117 | version = "1.3.0" 1118 | source = "registry+https://github.com/rust-lang/crates.io-index" 1119 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1120 | 1121 | [[package]] 1122 | name = "slab" 1123 | version = "0.4.9" 1124 | source = "registry+https://github.com/rust-lang/crates.io-index" 1125 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 1126 | dependencies = [ 1127 | "autocfg", 1128 | ] 1129 | 1130 | [[package]] 1131 | name = "smallvec" 1132 | version = "1.13.2" 1133 | source = "registry+https://github.com/rust-lang/crates.io-index" 1134 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 1135 | 1136 | [[package]] 1137 | name = "socket2" 1138 | version = "0.5.8" 1139 | source = "registry+https://github.com/rust-lang/crates.io-index" 1140 | checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" 1141 | dependencies = [ 1142 | "libc", 1143 | "windows-sys 0.52.0", 1144 | ] 1145 | 1146 | [[package]] 1147 | name = "spin" 1148 | version = "0.9.8" 1149 | source = "registry+https://github.com/rust-lang/crates.io-index" 1150 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 1151 | 1152 | [[package]] 1153 | name = "stable_deref_trait" 1154 | version = "1.2.0" 1155 | source = "registry+https://github.com/rust-lang/crates.io-index" 1156 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 1157 | 1158 | [[package]] 1159 | name = "strsim" 1160 | version = "0.11.1" 1161 | source = "registry+https://github.com/rust-lang/crates.io-index" 1162 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 1163 | 1164 | [[package]] 1165 | name = "subtle" 1166 | version = "2.6.1" 1167 | source = "registry+https://github.com/rust-lang/crates.io-index" 1168 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 1169 | 1170 | [[package]] 1171 | name = "syn" 1172 | version = "2.0.98" 1173 | source = "registry+https://github.com/rust-lang/crates.io-index" 1174 | checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" 1175 | dependencies = [ 1176 | "proc-macro2", 1177 | "quote", 1178 | "unicode-ident", 1179 | ] 1180 | 1181 | [[package]] 1182 | name = "sync_wrapper" 1183 | version = "1.0.2" 1184 | source = "registry+https://github.com/rust-lang/crates.io-index" 1185 | checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 1186 | dependencies = [ 1187 | "futures-core", 1188 | ] 1189 | 1190 | [[package]] 1191 | name = "synstructure" 1192 | version = "0.13.1" 1193 | source = "registry+https://github.com/rust-lang/crates.io-index" 1194 | checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" 1195 | dependencies = [ 1196 | "proc-macro2", 1197 | "quote", 1198 | "syn", 1199 | ] 1200 | 1201 | [[package]] 1202 | name = "thiserror" 1203 | version = "1.0.69" 1204 | source = "registry+https://github.com/rust-lang/crates.io-index" 1205 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 1206 | dependencies = [ 1207 | "thiserror-impl 1.0.69", 1208 | ] 1209 | 1210 | [[package]] 1211 | name = "thiserror" 1212 | version = "2.0.11" 1213 | source = "registry+https://github.com/rust-lang/crates.io-index" 1214 | checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" 1215 | dependencies = [ 1216 | "thiserror-impl 2.0.11", 1217 | ] 1218 | 1219 | [[package]] 1220 | name = "thiserror-impl" 1221 | version = "1.0.69" 1222 | source = "registry+https://github.com/rust-lang/crates.io-index" 1223 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 1224 | dependencies = [ 1225 | "proc-macro2", 1226 | "quote", 1227 | "syn", 1228 | ] 1229 | 1230 | [[package]] 1231 | name = "thiserror-impl" 1232 | version = "2.0.11" 1233 | source = "registry+https://github.com/rust-lang/crates.io-index" 1234 | checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" 1235 | dependencies = [ 1236 | "proc-macro2", 1237 | "quote", 1238 | "syn", 1239 | ] 1240 | 1241 | [[package]] 1242 | name = "time" 1243 | version = "0.3.37" 1244 | source = "registry+https://github.com/rust-lang/crates.io-index" 1245 | checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" 1246 | dependencies = [ 1247 | "deranged", 1248 | "itoa", 1249 | "num-conv", 1250 | "powerfmt", 1251 | "serde", 1252 | "time-core", 1253 | "time-macros", 1254 | ] 1255 | 1256 | [[package]] 1257 | name = "time-core" 1258 | version = "0.1.2" 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" 1260 | checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" 1261 | 1262 | [[package]] 1263 | name = "time-macros" 1264 | version = "0.2.19" 1265 | source = "registry+https://github.com/rust-lang/crates.io-index" 1266 | checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" 1267 | dependencies = [ 1268 | "num-conv", 1269 | "time-core", 1270 | ] 1271 | 1272 | [[package]] 1273 | name = "tinystr" 1274 | version = "0.7.6" 1275 | source = "registry+https://github.com/rust-lang/crates.io-index" 1276 | checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" 1277 | dependencies = [ 1278 | "displaydoc", 1279 | "zerovec", 1280 | ] 1281 | 1282 | [[package]] 1283 | name = "tinyvec" 1284 | version = "1.8.1" 1285 | source = "registry+https://github.com/rust-lang/crates.io-index" 1286 | checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" 1287 | dependencies = [ 1288 | "tinyvec_macros", 1289 | ] 1290 | 1291 | [[package]] 1292 | name = "tinyvec_macros" 1293 | version = "0.1.1" 1294 | source = "registry+https://github.com/rust-lang/crates.io-index" 1295 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1296 | 1297 | [[package]] 1298 | name = "tokio" 1299 | version = "1.43.0" 1300 | source = "registry+https://github.com/rust-lang/crates.io-index" 1301 | checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" 1302 | dependencies = [ 1303 | "backtrace", 1304 | "bytes", 1305 | "libc", 1306 | "mio", 1307 | "pin-project-lite", 1308 | "socket2", 1309 | "tokio-macros", 1310 | "windows-sys 0.52.0", 1311 | ] 1312 | 1313 | [[package]] 1314 | name = "tokio-macros" 1315 | version = "2.5.0" 1316 | source = "registry+https://github.com/rust-lang/crates.io-index" 1317 | checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 1318 | dependencies = [ 1319 | "proc-macro2", 1320 | "quote", 1321 | "syn", 1322 | ] 1323 | 1324 | [[package]] 1325 | name = "tokio-rustls" 1326 | version = "0.26.1" 1327 | source = "registry+https://github.com/rust-lang/crates.io-index" 1328 | checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" 1329 | dependencies = [ 1330 | "rustls", 1331 | "tokio", 1332 | ] 1333 | 1334 | [[package]] 1335 | name = "tower" 1336 | version = "0.5.2" 1337 | source = "registry+https://github.com/rust-lang/crates.io-index" 1338 | checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 1339 | dependencies = [ 1340 | "futures-core", 1341 | "futures-util", 1342 | "pin-project-lite", 1343 | "sync_wrapper", 1344 | "tokio", 1345 | "tower-layer", 1346 | "tower-service", 1347 | ] 1348 | 1349 | [[package]] 1350 | name = "tower-layer" 1351 | version = "0.3.3" 1352 | source = "registry+https://github.com/rust-lang/crates.io-index" 1353 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 1354 | 1355 | [[package]] 1356 | name = "tower-service" 1357 | version = "0.3.3" 1358 | source = "registry+https://github.com/rust-lang/crates.io-index" 1359 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 1360 | 1361 | [[package]] 1362 | name = "tracing" 1363 | version = "0.1.41" 1364 | source = "registry+https://github.com/rust-lang/crates.io-index" 1365 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 1366 | dependencies = [ 1367 | "pin-project-lite", 1368 | "tracing-core", 1369 | ] 1370 | 1371 | [[package]] 1372 | name = "tracing-core" 1373 | version = "0.1.33" 1374 | source = "registry+https://github.com/rust-lang/crates.io-index" 1375 | checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" 1376 | dependencies = [ 1377 | "once_cell", 1378 | ] 1379 | 1380 | [[package]] 1381 | name = "try-lock" 1382 | version = "0.2.5" 1383 | source = "registry+https://github.com/rust-lang/crates.io-index" 1384 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 1385 | 1386 | [[package]] 1387 | name = "unicode-ident" 1388 | version = "1.0.16" 1389 | source = "registry+https://github.com/rust-lang/crates.io-index" 1390 | checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" 1391 | 1392 | [[package]] 1393 | name = "untrusted" 1394 | version = "0.9.0" 1395 | source = "registry+https://github.com/rust-lang/crates.io-index" 1396 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 1397 | 1398 | [[package]] 1399 | name = "url" 1400 | version = "2.5.4" 1401 | source = "registry+https://github.com/rust-lang/crates.io-index" 1402 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 1403 | dependencies = [ 1404 | "form_urlencoded", 1405 | "idna", 1406 | "percent-encoding", 1407 | ] 1408 | 1409 | [[package]] 1410 | name = "utf16_iter" 1411 | version = "1.0.5" 1412 | source = "registry+https://github.com/rust-lang/crates.io-index" 1413 | checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" 1414 | 1415 | [[package]] 1416 | name = "utf8_iter" 1417 | version = "1.0.4" 1418 | source = "registry+https://github.com/rust-lang/crates.io-index" 1419 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 1420 | 1421 | [[package]] 1422 | name = "want" 1423 | version = "0.3.1" 1424 | source = "registry+https://github.com/rust-lang/crates.io-index" 1425 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 1426 | dependencies = [ 1427 | "try-lock", 1428 | ] 1429 | 1430 | [[package]] 1431 | name = "wasi" 1432 | version = "0.11.0+wasi-snapshot-preview1" 1433 | source = "registry+https://github.com/rust-lang/crates.io-index" 1434 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1435 | 1436 | [[package]] 1437 | name = "wasm-bindgen" 1438 | version = "0.2.100" 1439 | source = "registry+https://github.com/rust-lang/crates.io-index" 1440 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 1441 | dependencies = [ 1442 | "cfg-if", 1443 | "once_cell", 1444 | "rustversion", 1445 | "wasm-bindgen-macro", 1446 | ] 1447 | 1448 | [[package]] 1449 | name = "wasm-bindgen-backend" 1450 | version = "0.2.100" 1451 | source = "registry+https://github.com/rust-lang/crates.io-index" 1452 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 1453 | dependencies = [ 1454 | "bumpalo", 1455 | "log", 1456 | "proc-macro2", 1457 | "quote", 1458 | "syn", 1459 | "wasm-bindgen-shared", 1460 | ] 1461 | 1462 | [[package]] 1463 | name = "wasm-bindgen-futures" 1464 | version = "0.4.50" 1465 | source = "registry+https://github.com/rust-lang/crates.io-index" 1466 | checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" 1467 | dependencies = [ 1468 | "cfg-if", 1469 | "js-sys", 1470 | "once_cell", 1471 | "wasm-bindgen", 1472 | "web-sys", 1473 | ] 1474 | 1475 | [[package]] 1476 | name = "wasm-bindgen-macro" 1477 | version = "0.2.100" 1478 | source = "registry+https://github.com/rust-lang/crates.io-index" 1479 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 1480 | dependencies = [ 1481 | "quote", 1482 | "wasm-bindgen-macro-support", 1483 | ] 1484 | 1485 | [[package]] 1486 | name = "wasm-bindgen-macro-support" 1487 | version = "0.2.100" 1488 | source = "registry+https://github.com/rust-lang/crates.io-index" 1489 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 1490 | dependencies = [ 1491 | "proc-macro2", 1492 | "quote", 1493 | "syn", 1494 | "wasm-bindgen-backend", 1495 | "wasm-bindgen-shared", 1496 | ] 1497 | 1498 | [[package]] 1499 | name = "wasm-bindgen-shared" 1500 | version = "0.2.100" 1501 | source = "registry+https://github.com/rust-lang/crates.io-index" 1502 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 1503 | dependencies = [ 1504 | "unicode-ident", 1505 | ] 1506 | 1507 | [[package]] 1508 | name = "wasm-streams" 1509 | version = "0.4.2" 1510 | source = "registry+https://github.com/rust-lang/crates.io-index" 1511 | checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" 1512 | dependencies = [ 1513 | "futures-util", 1514 | "js-sys", 1515 | "wasm-bindgen", 1516 | "wasm-bindgen-futures", 1517 | "web-sys", 1518 | ] 1519 | 1520 | [[package]] 1521 | name = "web-sys" 1522 | version = "0.3.77" 1523 | source = "registry+https://github.com/rust-lang/crates.io-index" 1524 | checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 1525 | dependencies = [ 1526 | "js-sys", 1527 | "wasm-bindgen", 1528 | ] 1529 | 1530 | [[package]] 1531 | name = "web-time" 1532 | version = "1.1.0" 1533 | source = "registry+https://github.com/rust-lang/crates.io-index" 1534 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 1535 | dependencies = [ 1536 | "js-sys", 1537 | "wasm-bindgen", 1538 | ] 1539 | 1540 | [[package]] 1541 | name = "webpki-roots" 1542 | version = "0.26.8" 1543 | source = "registry+https://github.com/rust-lang/crates.io-index" 1544 | checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" 1545 | dependencies = [ 1546 | "rustls-pki-types", 1547 | ] 1548 | 1549 | [[package]] 1550 | name = "windows-core" 1551 | version = "0.52.0" 1552 | source = "registry+https://github.com/rust-lang/crates.io-index" 1553 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 1554 | dependencies = [ 1555 | "windows-targets", 1556 | ] 1557 | 1558 | [[package]] 1559 | name = "windows-registry" 1560 | version = "0.2.0" 1561 | source = "registry+https://github.com/rust-lang/crates.io-index" 1562 | checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" 1563 | dependencies = [ 1564 | "windows-result", 1565 | "windows-strings", 1566 | "windows-targets", 1567 | ] 1568 | 1569 | [[package]] 1570 | name = "windows-result" 1571 | version = "0.2.0" 1572 | source = "registry+https://github.com/rust-lang/crates.io-index" 1573 | checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" 1574 | dependencies = [ 1575 | "windows-targets", 1576 | ] 1577 | 1578 | [[package]] 1579 | name = "windows-strings" 1580 | version = "0.1.0" 1581 | source = "registry+https://github.com/rust-lang/crates.io-index" 1582 | checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" 1583 | dependencies = [ 1584 | "windows-result", 1585 | "windows-targets", 1586 | ] 1587 | 1588 | [[package]] 1589 | name = "windows-sys" 1590 | version = "0.52.0" 1591 | source = "registry+https://github.com/rust-lang/crates.io-index" 1592 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1593 | dependencies = [ 1594 | "windows-targets", 1595 | ] 1596 | 1597 | [[package]] 1598 | name = "windows-sys" 1599 | version = "0.59.0" 1600 | source = "registry+https://github.com/rust-lang/crates.io-index" 1601 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 1602 | dependencies = [ 1603 | "windows-targets", 1604 | ] 1605 | 1606 | [[package]] 1607 | name = "windows-targets" 1608 | version = "0.52.6" 1609 | source = "registry+https://github.com/rust-lang/crates.io-index" 1610 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1611 | dependencies = [ 1612 | "windows_aarch64_gnullvm", 1613 | "windows_aarch64_msvc", 1614 | "windows_i686_gnu", 1615 | "windows_i686_gnullvm", 1616 | "windows_i686_msvc", 1617 | "windows_x86_64_gnu", 1618 | "windows_x86_64_gnullvm", 1619 | "windows_x86_64_msvc", 1620 | ] 1621 | 1622 | [[package]] 1623 | name = "windows_aarch64_gnullvm" 1624 | version = "0.52.6" 1625 | source = "registry+https://github.com/rust-lang/crates.io-index" 1626 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1627 | 1628 | [[package]] 1629 | name = "windows_aarch64_msvc" 1630 | version = "0.52.6" 1631 | source = "registry+https://github.com/rust-lang/crates.io-index" 1632 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1633 | 1634 | [[package]] 1635 | name = "windows_i686_gnu" 1636 | version = "0.52.6" 1637 | source = "registry+https://github.com/rust-lang/crates.io-index" 1638 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1639 | 1640 | [[package]] 1641 | name = "windows_i686_gnullvm" 1642 | version = "0.52.6" 1643 | source = "registry+https://github.com/rust-lang/crates.io-index" 1644 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1645 | 1646 | [[package]] 1647 | name = "windows_i686_msvc" 1648 | version = "0.52.6" 1649 | source = "registry+https://github.com/rust-lang/crates.io-index" 1650 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1651 | 1652 | [[package]] 1653 | name = "windows_x86_64_gnu" 1654 | version = "0.52.6" 1655 | source = "registry+https://github.com/rust-lang/crates.io-index" 1656 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1657 | 1658 | [[package]] 1659 | name = "windows_x86_64_gnullvm" 1660 | version = "0.52.6" 1661 | source = "registry+https://github.com/rust-lang/crates.io-index" 1662 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1663 | 1664 | [[package]] 1665 | name = "windows_x86_64_msvc" 1666 | version = "0.52.6" 1667 | source = "registry+https://github.com/rust-lang/crates.io-index" 1668 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 1669 | 1670 | [[package]] 1671 | name = "worker" 1672 | version = "0.5.0" 1673 | source = "registry+https://github.com/rust-lang/crates.io-index" 1674 | checksum = "727789ca7eff9733efbea9d0e97779edc1cf1926e98aee7d7d8afe32805458aa" 1675 | dependencies = [ 1676 | "async-trait", 1677 | "bytes", 1678 | "chrono", 1679 | "futures-channel", 1680 | "futures-util", 1681 | "http", 1682 | "http-body", 1683 | "js-sys", 1684 | "matchit", 1685 | "pin-project", 1686 | "serde", 1687 | "serde-wasm-bindgen 0.6.5", 1688 | "serde_json", 1689 | "serde_urlencoded", 1690 | "tokio", 1691 | "url", 1692 | "wasm-bindgen", 1693 | "wasm-bindgen-futures", 1694 | "wasm-streams", 1695 | "web-sys", 1696 | "worker-kv", 1697 | "worker-macros", 1698 | "worker-sys", 1699 | ] 1700 | 1701 | [[package]] 1702 | name = "worker-kv" 1703 | version = "0.7.0" 1704 | source = "registry+https://github.com/rust-lang/crates.io-index" 1705 | checksum = "7f06d4d1416a9f8346ee9123b0d9a11b3cfa38e6cfb5a139698017d1597c4d41" 1706 | dependencies = [ 1707 | "js-sys", 1708 | "serde", 1709 | "serde-wasm-bindgen 0.5.0", 1710 | "serde_json", 1711 | "thiserror 1.0.69", 1712 | "wasm-bindgen", 1713 | "wasm-bindgen-futures", 1714 | ] 1715 | 1716 | [[package]] 1717 | name = "worker-macros" 1718 | version = "0.5.0" 1719 | source = "registry+https://github.com/rust-lang/crates.io-index" 1720 | checksum = "7d625c24570ba9207a2617476013335f28a95cbe513e59bb814ffba092a18058" 1721 | dependencies = [ 1722 | "async-trait", 1723 | "proc-macro2", 1724 | "quote", 1725 | "syn", 1726 | "wasm-bindgen", 1727 | "wasm-bindgen-futures", 1728 | "wasm-bindgen-macro-support", 1729 | "worker-sys", 1730 | ] 1731 | 1732 | [[package]] 1733 | name = "worker-sys" 1734 | version = "0.5.0" 1735 | source = "registry+https://github.com/rust-lang/crates.io-index" 1736 | checksum = "34563340d41016b4381257c5a16b0d2bc590dbe00500ecfbebcaa16f5f85ce90" 1737 | dependencies = [ 1738 | "cfg-if", 1739 | "js-sys", 1740 | "wasm-bindgen", 1741 | "web-sys", 1742 | ] 1743 | 1744 | [[package]] 1745 | name = "write16" 1746 | version = "1.0.0" 1747 | source = "registry+https://github.com/rust-lang/crates.io-index" 1748 | checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" 1749 | 1750 | [[package]] 1751 | name = "writeable" 1752 | version = "0.5.5" 1753 | source = "registry+https://github.com/rust-lang/crates.io-index" 1754 | checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" 1755 | 1756 | [[package]] 1757 | name = "yoke" 1758 | version = "0.7.5" 1759 | source = "registry+https://github.com/rust-lang/crates.io-index" 1760 | checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" 1761 | dependencies = [ 1762 | "serde", 1763 | "stable_deref_trait", 1764 | "yoke-derive", 1765 | "zerofrom", 1766 | ] 1767 | 1768 | [[package]] 1769 | name = "yoke-derive" 1770 | version = "0.7.5" 1771 | source = "registry+https://github.com/rust-lang/crates.io-index" 1772 | checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" 1773 | dependencies = [ 1774 | "proc-macro2", 1775 | "quote", 1776 | "syn", 1777 | "synstructure", 1778 | ] 1779 | 1780 | [[package]] 1781 | name = "zerocopy" 1782 | version = "0.7.35" 1783 | source = "registry+https://github.com/rust-lang/crates.io-index" 1784 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 1785 | dependencies = [ 1786 | "byteorder", 1787 | "zerocopy-derive", 1788 | ] 1789 | 1790 | [[package]] 1791 | name = "zerocopy-derive" 1792 | version = "0.7.35" 1793 | source = "registry+https://github.com/rust-lang/crates.io-index" 1794 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 1795 | dependencies = [ 1796 | "proc-macro2", 1797 | "quote", 1798 | "syn", 1799 | ] 1800 | 1801 | [[package]] 1802 | name = "zerofrom" 1803 | version = "0.1.5" 1804 | source = "registry+https://github.com/rust-lang/crates.io-index" 1805 | checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" 1806 | dependencies = [ 1807 | "zerofrom-derive", 1808 | ] 1809 | 1810 | [[package]] 1811 | name = "zerofrom-derive" 1812 | version = "0.1.5" 1813 | source = "registry+https://github.com/rust-lang/crates.io-index" 1814 | checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" 1815 | dependencies = [ 1816 | "proc-macro2", 1817 | "quote", 1818 | "syn", 1819 | "synstructure", 1820 | ] 1821 | 1822 | [[package]] 1823 | name = "zeroize" 1824 | version = "1.8.1" 1825 | source = "registry+https://github.com/rust-lang/crates.io-index" 1826 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 1827 | 1828 | [[package]] 1829 | name = "zerovec" 1830 | version = "0.10.4" 1831 | source = "registry+https://github.com/rust-lang/crates.io-index" 1832 | checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" 1833 | dependencies = [ 1834 | "yoke", 1835 | "zerofrom", 1836 | "zerovec-derive", 1837 | ] 1838 | 1839 | [[package]] 1840 | name = "zerovec-derive" 1841 | version = "0.10.3" 1842 | source = "registry+https://github.com/rust-lang/crates.io-index" 1843 | checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" 1844 | dependencies = [ 1845 | "proc-macro2", 1846 | "quote", 1847 | "syn", 1848 | ] 1849 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["ihciah"] 3 | description = "DDNS on cloudflare worker" 4 | edition = "2021" 5 | license = "MIT/Apache-2.0" 6 | name = "ddns" 7 | repository = "https://github.com/ihciah/ddns-worker" 8 | version = "0.2.0" 9 | 10 | [lib] 11 | crate-type = ["cdylib", "rlib"] 12 | 13 | [features] 14 | default = ["console_error_panic_hook"] 15 | 16 | [dependencies] 17 | anyhow = "1" 18 | cfg-if = "1" 19 | reqwest = { version = "0.12.12", default-features = false, features = [ 20 | "json", 21 | "rustls-tls", 22 | ] } 23 | worker = "0.5.0" 24 | constant_time_eq = "0.3.1" 25 | 26 | # For cf_base 27 | chrono = { version = "0.4", features = ["serde"] } 28 | serde = { version = "1.0", features = ["derive"] } 29 | serde_json = "1.0" 30 | serde_with = "3.12.0" 31 | 32 | # The `console_error_panic_hook` crate provides better debugging of panics by 33 | # logging them with `console.error`. This is great for development, but requires 34 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 35 | # code size when deploying. 36 | console_error_panic_hook = { version = "0.1.1", optional = true } 37 | 38 | [dev-dependencies] 39 | tokio = { version = "1", features = ["rt", "macros"] } 40 | 41 | [profile.release] 42 | # Tell `rustc` to optimize for small code size. 43 | opt-level = "s" 44 | lto = true 45 | strip = true 46 | codegen-units = 1 47 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 ihciah 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /LICENSE_APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DDNS based on Cloudflare Worker 2 | 3 | ## Usage 4 | 1. Copy `wrangler_example.toml` as `wrangler.toml`, and set: 5 | - `ZONE_ID`: You can find it in your [domain homepage](https://dash.cloudflare.com/). 6 | - `EMAIL`: Your Cloudflare account email. 7 | - `KEY`: Your Cloudflare API key, generate it [here](https://dash.cloudflare.com/profile/api-tokens) and allow it modify dns record. 8 | - `TOKEN_ddns.example.com`: The key format is `"TOKEN_" + your_sub_domain`. The value is the token for your sub-domain, you can set it as a long random string. 9 | 10 | 2. Run `npx wrangler deploy`. 11 | 12 | 3. You can `curl -X POST https://ddns.YOUR_WORKER_DOMAIN.workers.dev/update/ddns.example.com/EXAMPLE_TOKEN` to update the record to the client ip address. If you want to update different subdomains, you may add multiple key-values like `TOKEN_ddns2.example.com`. 13 | 14 | 4. If you want to specify ip address by your own, add the header `force-ip`. Note this can skip country checking. 15 | 16 | ## Note 17 | You can also set `COUNTRY` variable in `wrangler.toml` to only allow requests from that country(for example, when you misused a VPN, the DNS record will be your VPN outbound IP, which maybe not what you want). If you don't want it, just leave the key blank. Country code format is as `ISO 3166-1 Alpha 2`, for example, `CN`, `US`, `SG`. 18 | 19 | [The doc](https://developers.cloudflare.com/workers/languages/rust/) helps you prepare the environment. 20 | 21 | Wow so wasm! 22 | -------------------------------------------------------------------------------- /src/cf.rs: -------------------------------------------------------------------------------- 1 | use std::net::Ipv4Addr; 2 | 3 | use crate::cf_base::{ 4 | ApiErrors, ApiResult, ApiSuccess, Credentials, DnsContent, DnsContentOwned, DnsRecord, 5 | ListDnsRecordsParams, SearchMatch, UpdateDnsRecordParams, 6 | }; 7 | 8 | const CLOUDFLARE_API_URL: &str = "https://api.cloudflare.com/client/v4"; 9 | 10 | pub struct Client { 11 | cli: reqwest::Client, 12 | credentials: Credentials, 13 | } 14 | 15 | impl Client { 16 | pub fn new(email: String, key: String) -> Self { 17 | let credentials = Credentials::UserAuthKey { email, key }; 18 | Self::new_with_credentials(credentials) 19 | } 20 | 21 | #[allow(unused)] 22 | pub fn new_with_token(token: String) -> Self { 23 | let credentials = Credentials::UserAuthToken { token }; 24 | Self::new_with_credentials(credentials) 25 | } 26 | 27 | fn new_with_credentials(credentials: Credentials) -> Self { 28 | Self { 29 | cli: reqwest::Client::new(), 30 | credentials, 31 | } 32 | } 33 | 34 | pub async fn update_dns(&self, zone_id: &str, domain: &str, ip: &str) -> anyhow::Result<()> { 35 | let ipv4 = ip.parse::()?; 36 | let record = match self.get_any_a_record(zone_id, domain).await? { 37 | Some(record) => record, 38 | None => return Err(anyhow::anyhow!("no record found")), 39 | }; 40 | if matches!(record.content, DnsContentOwned::A { content: c } if c == ipv4) { 41 | // already exists 42 | return Ok(()); 43 | } 44 | self.update_a_record(zone_id, record, ipv4).await?; 45 | Ok(()) 46 | } 47 | 48 | async fn get_any_a_record( 49 | &self, 50 | zone_id: &str, 51 | domain: &str, 52 | ) -> anyhow::Result> { 53 | let list_param = ListDnsRecordsParams { 54 | name: Some(domain), 55 | search_match: Some(SearchMatch::Any), 56 | ..Default::default() 57 | }; 58 | let req = self 59 | .cli 60 | .get(format!("{CLOUDFLARE_API_URL}/zones/{zone_id}/dns_records")) 61 | .query(&list_param); 62 | let mut resp = self.do_request::>(req).await?; 63 | while let Some(record) = resp.result.pop() { 64 | if record.name == domain && matches!(record.content, DnsContentOwned::A { content: _ }) 65 | { 66 | return Ok(Some(record)); 67 | } 68 | } 69 | Ok(None) 70 | } 71 | 72 | async fn update_a_record( 73 | &self, 74 | zone_id: &str, 75 | record: DnsRecord, 76 | ip: Ipv4Addr, 77 | ) -> anyhow::Result { 78 | let update_param = UpdateDnsRecordParams { 79 | name: &record.name, 80 | content: DnsContent::A { content: ip }, 81 | ttl: Some(60), 82 | proxied: None, 83 | }; 84 | let req = self 85 | .cli 86 | .put(format!( 87 | "{CLOUDFLARE_API_URL}/zones/{zone_id}/dns_records/{}", 88 | record.id 89 | )) 90 | .json(&update_param); 91 | let resp = self.do_request::(req).await?; 92 | Ok(resp.result) 93 | } 94 | 95 | async fn do_request( 96 | &self, 97 | mut req: reqwest::RequestBuilder, 98 | ) -> anyhow::Result> { 99 | for (k, v) in self.credentials.headers() { 100 | req = req.header(k, v.as_ref()); 101 | } 102 | let req = req.build()?; 103 | let resp = self.cli.execute(req).await?; 104 | 105 | if resp.status().is_success() { 106 | let parsed: Result, reqwest::Error> = resp.json().await; 107 | Ok(parsed?) 108 | } else { 109 | let parsed: Result = resp.json().await; 110 | if let Some(e) = parsed?.errors.pop() { 111 | Err(e.into()) 112 | } else { 113 | Err(anyhow::anyhow!("api error")) 114 | } 115 | } 116 | } 117 | } 118 | 119 | #[cfg(test)] 120 | mod tests { 121 | use super::*; 122 | 123 | #[tokio::test] 124 | async fn get_record() { 125 | let cli = Client::new("ihciah@gmail.com".into(), "".into()); 126 | cli.get_any_a_record("", "test.ihc.im").await.unwrap(); 127 | } 128 | 129 | #[tokio::test] 130 | async fn update_record() { 131 | let cli = Client::new("ihciah@gmail.com".into(), "".into()); 132 | let record = cli 133 | .get_any_a_record("", "test.ihc.im") 134 | .await 135 | .unwrap() 136 | .unwrap(); 137 | cli.update_a_record("", record, Ipv4Addr::new(127, 0, 0, 1)) 138 | .await 139 | .unwrap(); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/cf_base.rs: -------------------------------------------------------------------------------- 1 | //! Fork part of code from crate cloudflare because its wasm support is not well. 2 | #![allow(unused)] 3 | 4 | use std::{ 5 | borrow::Cow, 6 | collections::HashMap, 7 | net::{Ipv4Addr, Ipv6Addr}, 8 | }; 9 | 10 | use chrono::{DateTime, Utc}; 11 | use serde::{de::DeserializeOwned, Deserialize, Serialize}; 12 | use serde_json::value::Value as JValue; 13 | 14 | #[derive(Deserialize, Serialize, Clone, Debug)] 15 | #[serde(tag = "type")] 16 | #[allow(clippy::upper_case_acronyms)] 17 | pub enum DnsContent<'a> { 18 | A { content: Ipv4Addr }, 19 | AAAA { content: Ipv6Addr }, 20 | CNAME { content: &'a str }, 21 | NS { content: &'a str }, 22 | MX { content: &'a str, priority: u16 }, 23 | TXT { content: &'a str }, 24 | SRV { content: &'a str }, 25 | } 26 | 27 | #[derive(Deserialize, Serialize, Clone, Debug)] 28 | #[serde(tag = "type")] 29 | #[allow(clippy::upper_case_acronyms)] 30 | pub enum DnsContentOwned { 31 | A { content: Ipv4Addr }, 32 | AAAA { content: Ipv6Addr }, 33 | CNAME { content: String }, 34 | NS { content: String }, 35 | MX { content: String, priority: u16 }, 36 | TXT { content: String }, 37 | SRV { content: String }, 38 | } 39 | 40 | #[derive(Deserialize, Debug)] 41 | pub struct DnsRecord { 42 | /// DNS record name 43 | pub name: String, 44 | /// Time to live for DNS record. Value of 1 is 'automatic' 45 | pub ttl: u32, 46 | /// When the record was last modified 47 | pub modified_on: DateTime, 48 | /// When the record was created 49 | pub created_on: DateTime, 50 | /// Whether this record can be modified/deleted (true means it's managed by Cloudflare) 51 | pub proxiable: bool, 52 | /// Type of the DNS record that also holds the record value 53 | #[serde(flatten)] 54 | pub content: DnsContentOwned, 55 | /// DNS record identifier tag 56 | pub id: String, 57 | /// Whether the record is receiving the performance and security benefits of Cloudflare 58 | pub proxied: bool, 59 | } 60 | 61 | pub trait ApiResult: DeserializeOwned + std::fmt::Debug {} 62 | 63 | impl ApiResult for DnsRecord {} 64 | impl ApiResult for Vec {} 65 | 66 | #[derive(Serialize, Clone, Debug)] 67 | #[serde(rename_all = "lowercase")] 68 | pub enum ListDnsRecordsOrder { 69 | Type, 70 | Name, 71 | Content, 72 | Ttl, 73 | Proxied, 74 | } 75 | 76 | #[derive(Serialize, Clone, Debug)] 77 | pub enum OrderDirection { 78 | #[serde(rename = "asc")] 79 | Ascending, 80 | #[serde(rename = "desc")] 81 | Descending, 82 | } 83 | 84 | /// Used as a parameter to API calls that search for a resource (e.g. DNS records). 85 | /// Tells the API whether to return results that match all search requirements or at least one (any). 86 | #[derive(Serialize, Clone, Debug)] 87 | #[serde(rename_all = "lowercase")] 88 | pub enum SearchMatch { 89 | /// Match all search requirements 90 | All, 91 | /// Match at least one search requirement 92 | Any, 93 | } 94 | 95 | #[serde_with::skip_serializing_none] 96 | #[derive(Serialize, Clone, Debug, Default)] 97 | pub struct ListDnsRecordsParams<'a> { 98 | #[serde(flatten)] 99 | pub record_type: Option>, 100 | pub name: Option<&'a str>, 101 | pub page: Option, 102 | pub per_page: Option, 103 | pub order: Option, 104 | pub direction: Option, 105 | #[serde(rename = "match")] 106 | pub search_match: Option, 107 | } 108 | 109 | #[serde_with::skip_serializing_none] 110 | #[derive(Serialize, Clone, Debug)] 111 | pub struct UpdateDnsRecordParams<'a> { 112 | /// Time to live for DNS record. Value of 1 is 'automatic' 113 | #[serde(skip_serializing_if = "Option::is_none")] 114 | pub ttl: Option, 115 | /// Whether the record is receiving the performance and security benefits of Cloudflare 116 | #[serde(skip_serializing_if = "Option::is_none")] 117 | pub proxied: Option, 118 | /// DNS record name 119 | pub name: &'a str, 120 | /// Type of the DNS record that also holds the record value 121 | #[serde(flatten)] 122 | pub content: DnsContent<'a>, 123 | } 124 | 125 | #[derive(Clone, Debug)] 126 | pub enum Credentials { 127 | UserAuthKey { email: String, key: String }, 128 | UserAuthToken { token: String }, 129 | Service { key: String }, 130 | } 131 | 132 | impl Credentials { 133 | pub fn headers(&self) -> Vec<(&'static str, Cow<'_, str>)> { 134 | match self { 135 | Self::UserAuthKey { email, key } => { 136 | vec![ 137 | ("X-Auth-Email", Cow::Borrowed(email.as_str())), 138 | ("X-Auth-Key", Cow::Borrowed(key.as_str())), 139 | ] 140 | } 141 | Self::UserAuthToken { token } => { 142 | vec![( 143 | "Authorization", 144 | Cow::Owned(format!("Bearer {}", token.as_str())), 145 | )] 146 | } 147 | Self::Service { key } => vec![("X-Auth-User-Service-Key", Cow::Borrowed(key.as_str()))], 148 | } 149 | } 150 | } 151 | 152 | /// Note that APIError's `eq` implementation only compares `code` and `message`. 153 | /// It does NOT compare the `other` values. 154 | #[derive(Deserialize, Debug)] 155 | pub struct ApiError { 156 | pub code: u16, 157 | pub message: String, 158 | #[serde(flatten)] 159 | pub other: HashMap, 160 | } 161 | 162 | /// Note that APIErrors's `eq` implementation only compares `code` and `message`. 163 | /// It does NOT compare the `other` values. 164 | #[derive(Deserialize, Debug, Default)] 165 | pub struct ApiErrors { 166 | #[serde(flatten)] 167 | pub other: HashMap, 168 | pub errors: Vec, 169 | } 170 | 171 | impl PartialEq for ApiErrors { 172 | fn eq(&self, other: &Self) -> bool { 173 | self.errors == other.errors 174 | } 175 | } 176 | 177 | impl PartialEq for ApiError { 178 | fn eq(&self, other: &Self) -> bool { 179 | self.code == other.code && self.message == other.message 180 | } 181 | } 182 | 183 | impl Eq for ApiError {} 184 | impl Eq for ApiErrors {} 185 | impl std::error::Error for ApiError {} 186 | 187 | impl std::fmt::Display for ApiError { 188 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 189 | write!(f, "Error {}: {}", self.code, self.message) 190 | } 191 | } 192 | 193 | #[derive(Deserialize, Debug, PartialEq)] 194 | pub struct ApiSuccess { 195 | pub result: ResultType, 196 | pub result_info: Option, 197 | pub messages: JValue, 198 | pub errors: Vec, 199 | } 200 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use worker::*; 2 | 3 | mod cf; 4 | mod cf_base; 5 | mod utils; 6 | 7 | const MAX_DOMAIN_LEN: usize = 64; 8 | 9 | async fn set_record(req: Request, ctx: RouteContext<()>) -> Result { 10 | // Get user token 11 | let Some(user_token) = ctx.param("token") else { 12 | return Response::error("No token found", 403); 13 | }; 14 | 15 | // Get user domain 16 | let Some(user_domain) = ctx.param("domain") else { 17 | return Response::error("No domain found", 400); 18 | }; 19 | 20 | // Validate user domain and token 21 | if user_domain 22 | .chars() 23 | .any(|c| !c.is_ascii_alphanumeric() && c != '.') 24 | { 25 | return Response::error("Domain contains invalid characters", 400); 26 | } 27 | if user_domain.len() > MAX_DOMAIN_LEN { 28 | return Response::error("Domain is too long", 400); 29 | } 30 | let Ok(token) = ctx.var(&format!("TOKEN_{user_domain}")) else { 31 | return Response::error( 32 | format!("Token not found or invalid for domain {user_domain}"), 33 | 403, 34 | ); 35 | }; 36 | if !constant_time_eq::constant_time_eq(token.to_string().as_bytes(), user_token.as_bytes()) { 37 | return Response::error( 38 | format!("Token not found or invalid for domain {user_domain}"), 39 | 403, 40 | ); 41 | } 42 | 43 | // Load vars 44 | let Ok(zone_id) = ctx.var("ZONE_ID") else { 45 | return Response::error("missing ZONE_ID", 500); 46 | }; 47 | let Ok(email) = ctx.var("EMAIL") else { 48 | return Response::error("missing EMAIL", 500); 49 | }; 50 | let Ok(key) = ctx.var("KEY") else { 51 | return Response::error("missing KEY", 500); 52 | }; 53 | 54 | // Get user ip 55 | let user_ip = if let Some(force_ip) = req.headers().get("force-ip").expect("internal error") { 56 | force_ip 57 | } else { 58 | // We only serve for given country if use cf-connecting-ip 59 | if let (Ok(country), Some(req_country)) = 60 | (ctx.var("COUNTRY"), req.cf().and_then(|f| f.country())) 61 | { 62 | let cty = country.to_string(); 63 | if !cty.is_empty() && cty != req_country { 64 | return Response::error( 65 | format!("Only available in {cty}, your country is {req_country}"), 66 | 403, 67 | ); 68 | } 69 | } 70 | match req 71 | .headers() 72 | .get("cf-connecting-ip") 73 | .expect("internal error") 74 | { 75 | Some(ip) => ip, 76 | None => return Response::error("Missing cf-connecting-ip", 500), 77 | } 78 | }; 79 | 80 | let client = cf::Client::new(email.to_string(), key.to_string()); 81 | match client 82 | .update_dns(&zone_id.to_string(), user_domain, &user_ip) 83 | .await 84 | { 85 | Ok(_) => Response::ok("Update success"), 86 | Err(e) => Response::error(format!("Update failed: {e}"), 500), 87 | } 88 | } 89 | 90 | #[event(fetch)] 91 | pub async fn main(req: Request, env: Env, _ctx: worker::Context) -> Result { 92 | utils::log_request(&req); 93 | utils::set_panic_hook(); 94 | 95 | let router = Router::new(); 96 | router 97 | .get("/", |_, _| Response::ok("DDNS Service by ihciah!")) 98 | .post("/", |_, _| Response::ok("DDNS Service by ihciah!")) 99 | .post_async("/update/:domain/:token", set_record) 100 | .run(req, env) 101 | .await 102 | } 103 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | use cfg_if::cfg_if; 2 | use worker::{console_log, Date, Request}; 3 | 4 | cfg_if! { 5 | // https://github.com/rustwasm/console_error_panic_hook#readme 6 | if #[cfg(feature = "console_error_panic_hook")] { 7 | extern crate console_error_panic_hook; 8 | pub use self::console_error_panic_hook::set_once as set_panic_hook; 9 | } else { 10 | #[inline] 11 | pub fn set_panic_hook() {} 12 | } 13 | } 14 | 15 | pub fn log_request(req: &Request) { 16 | console_log!( 17 | "{} - [{}], located at: {:?}, within: {}", 18 | Date::now().to_string(), 19 | req.path(), 20 | req.cf().and_then(|cf| cf.coordinates()).unwrap_or_default(), 21 | req.cf() 22 | .and_then(|cf| cf.region()) 23 | .unwrap_or_else(|| "unknown region".into()) 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /wrangler_example.toml: -------------------------------------------------------------------------------- 1 | name = "ddns" 2 | main = "build/worker/shim.mjs" 3 | compatibility_date = "2023-12-01" 4 | 5 | [vars] 6 | ZONE_ID = "" 7 | EMAIL = "" 8 | KEY = "" 9 | COUNTRY = "CN" 10 | "TOKEN_ddns.example.com" = "EXAMPLE_TOKEN" 11 | 12 | [build] 13 | command = "cargo install -q worker-build && worker-build --release" 14 | 15 | [env.dev] 16 | build = { command = "cargo install -q worker-build && worker-build --dev" } 17 | --------------------------------------------------------------------------------