├── README.md ├── actix-cocktail-api ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md └── src │ ├── main.rs │ ├── model.rs │ └── routes.rs ├── data ├── README.md └── recipes.json ├── flask-cocktail-api ├── .gitattributes ├── .gitignore ├── Makefile ├── README.md ├── add_slug.py ├── prospector.yaml ├── pyproject.toml ├── setup.py ├── src │ └── cocktailapi │ │ ├── __init__.py │ │ ├── model.py │ │ └── objectid.py ├── tests │ └── test_flaskcocktailapi.py └── tox.ini └── test_scripts ├── README.md ├── cocktail.json ├── delete_cocktail.sh ├── get_cocktail.sh ├── list_cocktails.sh ├── new_cocktail.sh └── update_cocktail.sh /README.md: -------------------------------------------------------------------------------- 1 | # Notice: Repository Deprecation 2 | This repository is deprecated and no longer actively maintained. It contains outdated code examples or practices that do not align with current MongoDB best practices. While the repository remains accessible for reference purposes, we strongly discourage its use in production environments. 3 | Users should be aware that this repository will not receive any further updates, bug fixes, or security patches. This code may expose you to security vulnerabilities, compatibility issues with current MongoDB versions, and potential performance problems. Any implementation based on this repository is at the user's own risk. 4 | For up-to-date resources, please refer to the [MongoDB Developer Center](https://mongodb.com/developer). 5 | 6 | # Rewrite it in Rust 7 | 8 | *Rewrite it in Rust* is a short blog post series on the [MongoDB Developer Hub](https://developer.mongodb.com). 9 | 10 | The [Python & Flask project](./flask-cocktail-api/) and the [Rust & Actix-Web project](./actix-cocktail-api) code was written to support the blog posts and aren't really designed to be viewed separately. There is also a small, low-quality selection of random cocktail recipes in a [MongoDB database export](./data). 11 | 12 | I'll link to the blog posts here as they are published! 13 | -------------------------------------------------------------------------------- /actix-cocktail-api/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /actix-cocktail-api/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "actix-cocktail-api" 5 | version = "0.1.0" 6 | dependencies = [ 7 | "actix-web", 8 | "chrono", 9 | "futures", 10 | "mongodb", 11 | "serde", 12 | "serde_json", 13 | "tokio", 14 | ] 15 | 16 | [[package]] 17 | name = "actix-codec" 18 | version = "0.3.0" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | checksum = "78d1833b3838dbe990df0f1f87baf640cf6146e898166afe401839d1b001e570" 21 | dependencies = [ 22 | "bitflags", 23 | "bytes 0.5.6", 24 | "futures-core", 25 | "futures-sink", 26 | "log", 27 | "pin-project 0.4.28", 28 | "tokio", 29 | "tokio-util", 30 | ] 31 | 32 | [[package]] 33 | name = "actix-connect" 34 | version = "2.0.0" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "177837a10863f15ba8d3ae3ec12fac1099099529ed20083a27fdfe247381d0dc" 37 | dependencies = [ 38 | "actix-codec", 39 | "actix-rt", 40 | "actix-service", 41 | "actix-utils", 42 | "derive_more", 43 | "either", 44 | "futures-util", 45 | "http", 46 | "log", 47 | "trust-dns-proto", 48 | "trust-dns-resolver", 49 | ] 50 | 51 | [[package]] 52 | name = "actix-http" 53 | version = "2.2.0" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | checksum = "452299e87817ae5673910e53c243484ca38be3828db819b6011736fc6982e874" 56 | dependencies = [ 57 | "actix-codec", 58 | "actix-connect", 59 | "actix-rt", 60 | "actix-service", 61 | "actix-threadpool", 62 | "actix-utils", 63 | "base64 0.13.0", 64 | "bitflags", 65 | "brotli2", 66 | "bytes 0.5.6", 67 | "cookie", 68 | "copyless", 69 | "derive_more", 70 | "either", 71 | "encoding_rs", 72 | "flate2", 73 | "futures-channel", 74 | "futures-core", 75 | "futures-util", 76 | "fxhash", 77 | "h2", 78 | "http", 79 | "httparse", 80 | "indexmap", 81 | "itoa", 82 | "language-tags", 83 | "lazy_static", 84 | "log", 85 | "mime", 86 | "percent-encoding", 87 | "pin-project 1.0.7", 88 | "rand", 89 | "regex", 90 | "serde", 91 | "serde_json", 92 | "serde_urlencoded", 93 | "sha-1 0.9.4", 94 | "slab", 95 | "time 0.2.26", 96 | ] 97 | 98 | [[package]] 99 | name = "actix-macros" 100 | version = "0.1.3" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655" 103 | dependencies = [ 104 | "quote", 105 | "syn", 106 | ] 107 | 108 | [[package]] 109 | name = "actix-router" 110 | version = "0.2.7" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | checksum = "2ad299af73649e1fc893e333ccf86f377751eb95ff875d095131574c6f43452c" 113 | dependencies = [ 114 | "bytestring", 115 | "http", 116 | "log", 117 | "regex", 118 | "serde", 119 | ] 120 | 121 | [[package]] 122 | name = "actix-rt" 123 | version = "1.1.1" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "143fcc2912e0d1de2bcf4e2f720d2a60c28652ab4179685a1ee159e0fb3db227" 126 | dependencies = [ 127 | "actix-macros", 128 | "actix-threadpool", 129 | "copyless", 130 | "futures-channel", 131 | "futures-util", 132 | "smallvec", 133 | "tokio", 134 | ] 135 | 136 | [[package]] 137 | name = "actix-server" 138 | version = "1.0.4" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "45407e6e672ca24784baa667c5d32ef109ccdd8d5e0b5ebb9ef8a67f4dfb708e" 141 | dependencies = [ 142 | "actix-codec", 143 | "actix-rt", 144 | "actix-service", 145 | "actix-utils", 146 | "futures-channel", 147 | "futures-util", 148 | "log", 149 | "mio", 150 | "mio-uds", 151 | "num_cpus", 152 | "slab", 153 | "socket2", 154 | ] 155 | 156 | [[package]] 157 | name = "actix-service" 158 | version = "1.0.6" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | checksum = "0052435d581b5be835d11f4eb3bce417c8af18d87ddf8ace99f8e67e595882bb" 161 | dependencies = [ 162 | "futures-util", 163 | "pin-project 0.4.28", 164 | ] 165 | 166 | [[package]] 167 | name = "actix-testing" 168 | version = "1.0.1" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "47239ca38799ab74ee6a8a94d1ce857014b2ac36f242f70f3f75a66f691e791c" 171 | dependencies = [ 172 | "actix-macros", 173 | "actix-rt", 174 | "actix-server", 175 | "actix-service", 176 | "log", 177 | "socket2", 178 | ] 179 | 180 | [[package]] 181 | name = "actix-threadpool" 182 | version = "0.3.3" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | checksum = "d209f04d002854b9afd3743032a27b066158817965bf5d036824d19ac2cc0e30" 185 | dependencies = [ 186 | "derive_more", 187 | "futures-channel", 188 | "lazy_static", 189 | "log", 190 | "num_cpus", 191 | "parking_lot", 192 | "threadpool", 193 | ] 194 | 195 | [[package]] 196 | name = "actix-tls" 197 | version = "2.0.0" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "24789b7d7361cf5503a504ebe1c10806896f61e96eca9a7350e23001aca715fb" 200 | dependencies = [ 201 | "actix-codec", 202 | "actix-service", 203 | "actix-utils", 204 | "futures-util", 205 | ] 206 | 207 | [[package]] 208 | name = "actix-utils" 209 | version = "2.0.0" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "2e9022dec56632d1d7979e59af14f0597a28a830a9c1c7fec8b2327eb9f16b5a" 212 | dependencies = [ 213 | "actix-codec", 214 | "actix-rt", 215 | "actix-service", 216 | "bitflags", 217 | "bytes 0.5.6", 218 | "either", 219 | "futures-channel", 220 | "futures-sink", 221 | "futures-util", 222 | "log", 223 | "pin-project 0.4.28", 224 | "slab", 225 | ] 226 | 227 | [[package]] 228 | name = "actix-web" 229 | version = "3.3.2" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "e641d4a172e7faa0862241a20ff4f1f5ab0ab7c279f00c2d4587b77483477b86" 232 | dependencies = [ 233 | "actix-codec", 234 | "actix-http", 235 | "actix-macros", 236 | "actix-router", 237 | "actix-rt", 238 | "actix-server", 239 | "actix-service", 240 | "actix-testing", 241 | "actix-threadpool", 242 | "actix-tls", 243 | "actix-utils", 244 | "actix-web-codegen", 245 | "awc", 246 | "bytes 0.5.6", 247 | "derive_more", 248 | "encoding_rs", 249 | "futures-channel", 250 | "futures-core", 251 | "futures-util", 252 | "fxhash", 253 | "log", 254 | "mime", 255 | "pin-project 1.0.7", 256 | "regex", 257 | "serde", 258 | "serde_json", 259 | "serde_urlencoded", 260 | "socket2", 261 | "time 0.2.26", 262 | "tinyvec", 263 | "url", 264 | ] 265 | 266 | [[package]] 267 | name = "actix-web-codegen" 268 | version = "0.4.0" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | checksum = "ad26f77093333e0e7c6ffe54ebe3582d908a104e448723eec6d43d08b07143fb" 271 | dependencies = [ 272 | "proc-macro2", 273 | "quote", 274 | "syn", 275 | ] 276 | 277 | [[package]] 278 | name = "addr2line" 279 | version = "0.14.1" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" 282 | dependencies = [ 283 | "gimli", 284 | ] 285 | 286 | [[package]] 287 | name = "adler" 288 | version = "1.0.2" 289 | source = "registry+https://github.com/rust-lang/crates.io-index" 290 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 291 | 292 | [[package]] 293 | name = "aho-corasick" 294 | version = "0.7.15" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" 297 | dependencies = [ 298 | "memchr", 299 | ] 300 | 301 | [[package]] 302 | name = "async-trait" 303 | version = "0.1.50" 304 | source = "registry+https://github.com/rust-lang/crates.io-index" 305 | checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722" 306 | dependencies = [ 307 | "proc-macro2", 308 | "quote", 309 | "syn", 310 | ] 311 | 312 | [[package]] 313 | name = "autocfg" 314 | version = "1.0.1" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 317 | 318 | [[package]] 319 | name = "awc" 320 | version = "2.0.3" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | checksum = "b381e490e7b0cfc37ebc54079b0413d8093ef43d14a4e4747083f7fa47a9e691" 323 | dependencies = [ 324 | "actix-codec", 325 | "actix-http", 326 | "actix-rt", 327 | "actix-service", 328 | "base64 0.13.0", 329 | "bytes 0.5.6", 330 | "cfg-if 1.0.0", 331 | "derive_more", 332 | "futures-core", 333 | "log", 334 | "mime", 335 | "percent-encoding", 336 | "rand", 337 | "serde", 338 | "serde_json", 339 | "serde_urlencoded", 340 | ] 341 | 342 | [[package]] 343 | name = "backtrace" 344 | version = "0.3.58" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "88fb5a785d6b44fd9d6700935608639af1b8356de1e55d5f7c2740f4faa15d82" 347 | dependencies = [ 348 | "addr2line", 349 | "cc", 350 | "cfg-if 1.0.0", 351 | "libc", 352 | "miniz_oxide", 353 | "object", 354 | "rustc-demangle", 355 | ] 356 | 357 | [[package]] 358 | name = "base-x" 359 | version = "0.2.8" 360 | source = "registry+https://github.com/rust-lang/crates.io-index" 361 | checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" 362 | 363 | [[package]] 364 | name = "base64" 365 | version = "0.11.0" 366 | source = "registry+https://github.com/rust-lang/crates.io-index" 367 | checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" 368 | 369 | [[package]] 370 | name = "base64" 371 | version = "0.12.3" 372 | source = "registry+https://github.com/rust-lang/crates.io-index" 373 | checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" 374 | 375 | [[package]] 376 | name = "base64" 377 | version = "0.13.0" 378 | source = "registry+https://github.com/rust-lang/crates.io-index" 379 | checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" 380 | 381 | [[package]] 382 | name = "bitflags" 383 | version = "1.2.1" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 386 | 387 | [[package]] 388 | name = "block-buffer" 389 | version = "0.7.3" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" 392 | dependencies = [ 393 | "block-padding", 394 | "byte-tools", 395 | "byteorder", 396 | "generic-array 0.12.4", 397 | ] 398 | 399 | [[package]] 400 | name = "block-buffer" 401 | version = "0.9.0" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" 404 | dependencies = [ 405 | "generic-array 0.14.4", 406 | ] 407 | 408 | [[package]] 409 | name = "block-padding" 410 | version = "0.1.5" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" 413 | dependencies = [ 414 | "byte-tools", 415 | ] 416 | 417 | [[package]] 418 | name = "brotli-sys" 419 | version = "0.3.2" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" 422 | dependencies = [ 423 | "cc", 424 | "libc", 425 | ] 426 | 427 | [[package]] 428 | name = "brotli2" 429 | version = "0.3.2" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" 432 | dependencies = [ 433 | "brotli-sys", 434 | "libc", 435 | ] 436 | 437 | [[package]] 438 | name = "bson" 439 | version = "1.2.2" 440 | source = "registry+https://github.com/rust-lang/crates.io-index" 441 | checksum = "38b6553abdb9d2d8f262f0b5bccf807321d5b7d1a12796bcede8e1f150e85f2e" 442 | dependencies = [ 443 | "base64 0.13.0", 444 | "chrono", 445 | "hex", 446 | "lazy_static", 447 | "linked-hash-map", 448 | "rand", 449 | "serde", 450 | "serde_json", 451 | "uuid", 452 | ] 453 | 454 | [[package]] 455 | name = "bumpalo" 456 | version = "3.6.1" 457 | source = "registry+https://github.com/rust-lang/crates.io-index" 458 | checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" 459 | 460 | [[package]] 461 | name = "byte-tools" 462 | version = "0.3.1" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" 465 | 466 | [[package]] 467 | name = "byteorder" 468 | version = "1.4.3" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 471 | 472 | [[package]] 473 | name = "bytes" 474 | version = "0.5.6" 475 | source = "registry+https://github.com/rust-lang/crates.io-index" 476 | checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" 477 | 478 | [[package]] 479 | name = "bytes" 480 | version = "1.0.1" 481 | source = "registry+https://github.com/rust-lang/crates.io-index" 482 | checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" 483 | 484 | [[package]] 485 | name = "bytestring" 486 | version = "1.0.0" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "90706ba19e97b90786e19dc0d5e2abd80008d99d4c0c5d1ad0b5e72cec7c494d" 489 | dependencies = [ 490 | "bytes 1.0.1", 491 | ] 492 | 493 | [[package]] 494 | name = "cc" 495 | version = "1.0.67" 496 | source = "registry+https://github.com/rust-lang/crates.io-index" 497 | checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" 498 | 499 | [[package]] 500 | name = "cfg-if" 501 | version = "0.1.10" 502 | source = "registry+https://github.com/rust-lang/crates.io-index" 503 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 504 | 505 | [[package]] 506 | name = "cfg-if" 507 | version = "1.0.0" 508 | source = "registry+https://github.com/rust-lang/crates.io-index" 509 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 510 | 511 | [[package]] 512 | name = "chrono" 513 | version = "0.4.19" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" 516 | dependencies = [ 517 | "libc", 518 | "num-integer", 519 | "num-traits", 520 | "serde", 521 | "time 0.1.44", 522 | "winapi 0.3.9", 523 | ] 524 | 525 | [[package]] 526 | name = "const_fn" 527 | version = "0.4.7" 528 | source = "registry+https://github.com/rust-lang/crates.io-index" 529 | checksum = "402da840495de3f976eaefc3485b7f5eb5b0bf9761f9a47be27fe975b3b8c2ec" 530 | 531 | [[package]] 532 | name = "convert_case" 533 | version = "0.4.0" 534 | source = "registry+https://github.com/rust-lang/crates.io-index" 535 | checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" 536 | 537 | [[package]] 538 | name = "cookie" 539 | version = "0.14.4" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951" 542 | dependencies = [ 543 | "percent-encoding", 544 | "time 0.2.26", 545 | "version_check", 546 | ] 547 | 548 | [[package]] 549 | name = "copyless" 550 | version = "0.1.5" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" 553 | 554 | [[package]] 555 | name = "cpuid-bool" 556 | version = "0.1.2" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" 559 | 560 | [[package]] 561 | name = "crc32fast" 562 | version = "1.2.1" 563 | source = "registry+https://github.com/rust-lang/crates.io-index" 564 | checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" 565 | dependencies = [ 566 | "cfg-if 1.0.0", 567 | ] 568 | 569 | [[package]] 570 | name = "crypto-mac" 571 | version = "0.7.0" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" 574 | dependencies = [ 575 | "generic-array 0.12.4", 576 | "subtle", 577 | ] 578 | 579 | [[package]] 580 | name = "darling" 581 | version = "0.12.4" 582 | source = "registry+https://github.com/rust-lang/crates.io-index" 583 | checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c" 584 | dependencies = [ 585 | "darling_core", 586 | "darling_macro", 587 | ] 588 | 589 | [[package]] 590 | name = "darling_core" 591 | version = "0.12.4" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36" 594 | dependencies = [ 595 | "fnv", 596 | "ident_case", 597 | "proc-macro2", 598 | "quote", 599 | "strsim", 600 | "syn", 601 | ] 602 | 603 | [[package]] 604 | name = "darling_macro" 605 | version = "0.12.4" 606 | source = "registry+https://github.com/rust-lang/crates.io-index" 607 | checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a" 608 | dependencies = [ 609 | "darling_core", 610 | "quote", 611 | "syn", 612 | ] 613 | 614 | [[package]] 615 | name = "derivative" 616 | version = "2.2.0" 617 | source = "registry+https://github.com/rust-lang/crates.io-index" 618 | checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" 619 | dependencies = [ 620 | "proc-macro2", 621 | "quote", 622 | "syn", 623 | ] 624 | 625 | [[package]] 626 | name = "derive_more" 627 | version = "0.99.13" 628 | source = "registry+https://github.com/rust-lang/crates.io-index" 629 | checksum = "f82b1b72f1263f214c0f823371768776c4f5841b942c9883aa8e5ec584fd0ba6" 630 | dependencies = [ 631 | "convert_case", 632 | "proc-macro2", 633 | "quote", 634 | "syn", 635 | ] 636 | 637 | [[package]] 638 | name = "digest" 639 | version = "0.8.1" 640 | source = "registry+https://github.com/rust-lang/crates.io-index" 641 | checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" 642 | dependencies = [ 643 | "generic-array 0.12.4", 644 | ] 645 | 646 | [[package]] 647 | name = "digest" 648 | version = "0.9.0" 649 | source = "registry+https://github.com/rust-lang/crates.io-index" 650 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" 651 | dependencies = [ 652 | "generic-array 0.14.4", 653 | ] 654 | 655 | [[package]] 656 | name = "discard" 657 | version = "1.0.4" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" 660 | 661 | [[package]] 662 | name = "either" 663 | version = "1.6.1" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" 666 | 667 | [[package]] 668 | name = "encoding_rs" 669 | version = "0.8.28" 670 | source = "registry+https://github.com/rust-lang/crates.io-index" 671 | checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" 672 | dependencies = [ 673 | "cfg-if 1.0.0", 674 | ] 675 | 676 | [[package]] 677 | name = "enum-as-inner" 678 | version = "0.3.3" 679 | source = "registry+https://github.com/rust-lang/crates.io-index" 680 | checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" 681 | dependencies = [ 682 | "heck", 683 | "proc-macro2", 684 | "quote", 685 | "syn", 686 | ] 687 | 688 | [[package]] 689 | name = "err-derive" 690 | version = "0.2.4" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "22deed3a8124cff5fa835713fa105621e43bbdc46690c3a6b68328a012d350d4" 693 | dependencies = [ 694 | "proc-macro-error", 695 | "proc-macro2", 696 | "quote", 697 | "rustversion", 698 | "syn", 699 | "synstructure", 700 | ] 701 | 702 | [[package]] 703 | name = "fake-simd" 704 | version = "0.1.2" 705 | source = "registry+https://github.com/rust-lang/crates.io-index" 706 | checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" 707 | 708 | [[package]] 709 | name = "flate2" 710 | version = "1.0.20" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" 713 | dependencies = [ 714 | "cfg-if 1.0.0", 715 | "crc32fast", 716 | "libc", 717 | "miniz_oxide", 718 | ] 719 | 720 | [[package]] 721 | name = "fnv" 722 | version = "1.0.7" 723 | source = "registry+https://github.com/rust-lang/crates.io-index" 724 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 725 | 726 | [[package]] 727 | name = "form_urlencoded" 728 | version = "1.0.1" 729 | source = "registry+https://github.com/rust-lang/crates.io-index" 730 | checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" 731 | dependencies = [ 732 | "matches", 733 | "percent-encoding", 734 | ] 735 | 736 | [[package]] 737 | name = "fuchsia-zircon" 738 | version = "0.3.3" 739 | source = "registry+https://github.com/rust-lang/crates.io-index" 740 | checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" 741 | dependencies = [ 742 | "bitflags", 743 | "fuchsia-zircon-sys", 744 | ] 745 | 746 | [[package]] 747 | name = "fuchsia-zircon-sys" 748 | version = "0.3.3" 749 | source = "registry+https://github.com/rust-lang/crates.io-index" 750 | checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" 751 | 752 | [[package]] 753 | name = "futures" 754 | version = "0.3.14" 755 | source = "registry+https://github.com/rust-lang/crates.io-index" 756 | checksum = "a9d5813545e459ad3ca1bff9915e9ad7f1a47dc6a91b627ce321d5863b7dd253" 757 | dependencies = [ 758 | "futures-channel", 759 | "futures-core", 760 | "futures-executor", 761 | "futures-io", 762 | "futures-sink", 763 | "futures-task", 764 | "futures-util", 765 | ] 766 | 767 | [[package]] 768 | name = "futures-channel" 769 | version = "0.3.14" 770 | source = "registry+https://github.com/rust-lang/crates.io-index" 771 | checksum = "ce79c6a52a299137a6013061e0cf0e688fce5d7f1bc60125f520912fdb29ec25" 772 | dependencies = [ 773 | "futures-core", 774 | "futures-sink", 775 | ] 776 | 777 | [[package]] 778 | name = "futures-core" 779 | version = "0.3.14" 780 | source = "registry+https://github.com/rust-lang/crates.io-index" 781 | checksum = "098cd1c6dda6ca01650f1a37a794245eb73181d0d4d4e955e2f3c37db7af1815" 782 | 783 | [[package]] 784 | name = "futures-executor" 785 | version = "0.3.14" 786 | source = "registry+https://github.com/rust-lang/crates.io-index" 787 | checksum = "10f6cb7042eda00f0049b1d2080aa4b93442997ee507eb3828e8bd7577f94c9d" 788 | dependencies = [ 789 | "futures-core", 790 | "futures-task", 791 | "futures-util", 792 | ] 793 | 794 | [[package]] 795 | name = "futures-io" 796 | version = "0.3.14" 797 | source = "registry+https://github.com/rust-lang/crates.io-index" 798 | checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04" 799 | 800 | [[package]] 801 | name = "futures-macro" 802 | version = "0.3.14" 803 | source = "registry+https://github.com/rust-lang/crates.io-index" 804 | checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b" 805 | dependencies = [ 806 | "proc-macro-hack", 807 | "proc-macro2", 808 | "quote", 809 | "syn", 810 | ] 811 | 812 | [[package]] 813 | name = "futures-sink" 814 | version = "0.3.14" 815 | source = "registry+https://github.com/rust-lang/crates.io-index" 816 | checksum = "5c5629433c555de3d82861a7a4e3794a4c40040390907cfbfd7143a92a426c23" 817 | 818 | [[package]] 819 | name = "futures-task" 820 | version = "0.3.14" 821 | source = "registry+https://github.com/rust-lang/crates.io-index" 822 | checksum = "ba7aa51095076f3ba6d9a1f702f74bd05ec65f555d70d2033d55ba8d69f581bc" 823 | 824 | [[package]] 825 | name = "futures-util" 826 | version = "0.3.14" 827 | source = "registry+https://github.com/rust-lang/crates.io-index" 828 | checksum = "3c144ad54d60f23927f0a6b6d816e4271278b64f005ad65e4e35291d2de9c025" 829 | dependencies = [ 830 | "futures-channel", 831 | "futures-core", 832 | "futures-io", 833 | "futures-macro", 834 | "futures-sink", 835 | "futures-task", 836 | "memchr", 837 | "pin-project-lite 0.2.6", 838 | "pin-utils", 839 | "proc-macro-hack", 840 | "proc-macro-nested", 841 | "slab", 842 | ] 843 | 844 | [[package]] 845 | name = "fxhash" 846 | version = "0.2.1" 847 | source = "registry+https://github.com/rust-lang/crates.io-index" 848 | checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" 849 | dependencies = [ 850 | "byteorder", 851 | ] 852 | 853 | [[package]] 854 | name = "generic-array" 855 | version = "0.12.4" 856 | source = "registry+https://github.com/rust-lang/crates.io-index" 857 | checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" 858 | dependencies = [ 859 | "typenum", 860 | ] 861 | 862 | [[package]] 863 | name = "generic-array" 864 | version = "0.14.4" 865 | source = "registry+https://github.com/rust-lang/crates.io-index" 866 | checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" 867 | dependencies = [ 868 | "typenum", 869 | "version_check", 870 | ] 871 | 872 | [[package]] 873 | name = "getrandom" 874 | version = "0.1.16" 875 | source = "registry+https://github.com/rust-lang/crates.io-index" 876 | checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" 877 | dependencies = [ 878 | "cfg-if 1.0.0", 879 | "libc", 880 | "wasi 0.9.0+wasi-snapshot-preview1", 881 | ] 882 | 883 | [[package]] 884 | name = "getrandom" 885 | version = "0.2.2" 886 | source = "registry+https://github.com/rust-lang/crates.io-index" 887 | checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" 888 | dependencies = [ 889 | "cfg-if 1.0.0", 890 | "libc", 891 | "wasi 0.10.0+wasi-snapshot-preview1", 892 | ] 893 | 894 | [[package]] 895 | name = "gimli" 896 | version = "0.23.0" 897 | source = "registry+https://github.com/rust-lang/crates.io-index" 898 | checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" 899 | 900 | [[package]] 901 | name = "h2" 902 | version = "0.2.7" 903 | source = "registry+https://github.com/rust-lang/crates.io-index" 904 | checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535" 905 | dependencies = [ 906 | "bytes 0.5.6", 907 | "fnv", 908 | "futures-core", 909 | "futures-sink", 910 | "futures-util", 911 | "http", 912 | "indexmap", 913 | "slab", 914 | "tokio", 915 | "tokio-util", 916 | "tracing", 917 | "tracing-futures", 918 | ] 919 | 920 | [[package]] 921 | name = "hashbrown" 922 | version = "0.9.1" 923 | source = "registry+https://github.com/rust-lang/crates.io-index" 924 | checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" 925 | 926 | [[package]] 927 | name = "heck" 928 | version = "0.3.2" 929 | source = "registry+https://github.com/rust-lang/crates.io-index" 930 | checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" 931 | dependencies = [ 932 | "unicode-segmentation", 933 | ] 934 | 935 | [[package]] 936 | name = "hermit-abi" 937 | version = "0.1.18" 938 | source = "registry+https://github.com/rust-lang/crates.io-index" 939 | checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" 940 | dependencies = [ 941 | "libc", 942 | ] 943 | 944 | [[package]] 945 | name = "hex" 946 | version = "0.4.3" 947 | source = "registry+https://github.com/rust-lang/crates.io-index" 948 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 949 | 950 | [[package]] 951 | name = "hmac" 952 | version = "0.7.1" 953 | source = "registry+https://github.com/rust-lang/crates.io-index" 954 | checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" 955 | dependencies = [ 956 | "crypto-mac", 957 | "digest 0.8.1", 958 | ] 959 | 960 | [[package]] 961 | name = "hostname" 962 | version = "0.3.1" 963 | source = "registry+https://github.com/rust-lang/crates.io-index" 964 | checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" 965 | dependencies = [ 966 | "libc", 967 | "match_cfg", 968 | "winapi 0.3.9", 969 | ] 970 | 971 | [[package]] 972 | name = "http" 973 | version = "0.2.4" 974 | source = "registry+https://github.com/rust-lang/crates.io-index" 975 | checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" 976 | dependencies = [ 977 | "bytes 1.0.1", 978 | "fnv", 979 | "itoa", 980 | ] 981 | 982 | [[package]] 983 | name = "http-body" 984 | version = "0.3.1" 985 | source = "registry+https://github.com/rust-lang/crates.io-index" 986 | checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" 987 | dependencies = [ 988 | "bytes 0.5.6", 989 | "http", 990 | ] 991 | 992 | [[package]] 993 | name = "httparse" 994 | version = "1.4.0" 995 | source = "registry+https://github.com/rust-lang/crates.io-index" 996 | checksum = "4a1ce40d6fc9764887c2fdc7305c3dcc429ba11ff981c1509416afd5697e4437" 997 | 998 | [[package]] 999 | name = "httpdate" 1000 | version = "0.3.2" 1001 | source = "registry+https://github.com/rust-lang/crates.io-index" 1002 | checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" 1003 | 1004 | [[package]] 1005 | name = "hyper" 1006 | version = "0.13.10" 1007 | source = "registry+https://github.com/rust-lang/crates.io-index" 1008 | checksum = "8a6f157065790a3ed2f88679250419b5cdd96e714a0d65f7797fd337186e96bb" 1009 | dependencies = [ 1010 | "bytes 0.5.6", 1011 | "futures-channel", 1012 | "futures-core", 1013 | "futures-util", 1014 | "h2", 1015 | "http", 1016 | "http-body", 1017 | "httparse", 1018 | "httpdate", 1019 | "itoa", 1020 | "pin-project 1.0.7", 1021 | "socket2", 1022 | "tokio", 1023 | "tower-service", 1024 | "tracing", 1025 | "want", 1026 | ] 1027 | 1028 | [[package]] 1029 | name = "hyper-rustls" 1030 | version = "0.21.0" 1031 | source = "registry+https://github.com/rust-lang/crates.io-index" 1032 | checksum = "37743cc83e8ee85eacfce90f2f4102030d9ff0a95244098d781e9bee4a90abb6" 1033 | dependencies = [ 1034 | "bytes 0.5.6", 1035 | "futures-util", 1036 | "hyper", 1037 | "log", 1038 | "rustls 0.18.1", 1039 | "tokio", 1040 | "tokio-rustls 0.14.1", 1041 | "webpki", 1042 | ] 1043 | 1044 | [[package]] 1045 | name = "ident_case" 1046 | version = "1.0.1" 1047 | source = "registry+https://github.com/rust-lang/crates.io-index" 1048 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 1049 | 1050 | [[package]] 1051 | name = "idna" 1052 | version = "0.2.3" 1053 | source = "registry+https://github.com/rust-lang/crates.io-index" 1054 | checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" 1055 | dependencies = [ 1056 | "matches", 1057 | "unicode-bidi", 1058 | "unicode-normalization", 1059 | ] 1060 | 1061 | [[package]] 1062 | name = "indexmap" 1063 | version = "1.6.2" 1064 | source = "registry+https://github.com/rust-lang/crates.io-index" 1065 | checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" 1066 | dependencies = [ 1067 | "autocfg", 1068 | "hashbrown", 1069 | ] 1070 | 1071 | [[package]] 1072 | name = "instant" 1073 | version = "0.1.9" 1074 | source = "registry+https://github.com/rust-lang/crates.io-index" 1075 | checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" 1076 | dependencies = [ 1077 | "cfg-if 1.0.0", 1078 | ] 1079 | 1080 | [[package]] 1081 | name = "iovec" 1082 | version = "0.1.4" 1083 | source = "registry+https://github.com/rust-lang/crates.io-index" 1084 | checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" 1085 | dependencies = [ 1086 | "libc", 1087 | ] 1088 | 1089 | [[package]] 1090 | name = "ipconfig" 1091 | version = "0.2.2" 1092 | source = "registry+https://github.com/rust-lang/crates.io-index" 1093 | checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" 1094 | dependencies = [ 1095 | "socket2", 1096 | "widestring", 1097 | "winapi 0.3.9", 1098 | "winreg 0.6.2", 1099 | ] 1100 | 1101 | [[package]] 1102 | name = "ipnet" 1103 | version = "2.3.0" 1104 | source = "registry+https://github.com/rust-lang/crates.io-index" 1105 | checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" 1106 | 1107 | [[package]] 1108 | name = "itoa" 1109 | version = "0.4.7" 1110 | source = "registry+https://github.com/rust-lang/crates.io-index" 1111 | checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" 1112 | 1113 | [[package]] 1114 | name = "js-sys" 1115 | version = "0.3.50" 1116 | source = "registry+https://github.com/rust-lang/crates.io-index" 1117 | checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c" 1118 | dependencies = [ 1119 | "wasm-bindgen", 1120 | ] 1121 | 1122 | [[package]] 1123 | name = "kernel32-sys" 1124 | version = "0.2.2" 1125 | source = "registry+https://github.com/rust-lang/crates.io-index" 1126 | checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 1127 | dependencies = [ 1128 | "winapi 0.2.8", 1129 | "winapi-build", 1130 | ] 1131 | 1132 | [[package]] 1133 | name = "language-tags" 1134 | version = "0.2.2" 1135 | source = "registry+https://github.com/rust-lang/crates.io-index" 1136 | checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" 1137 | 1138 | [[package]] 1139 | name = "lazy_static" 1140 | version = "1.4.0" 1141 | source = "registry+https://github.com/rust-lang/crates.io-index" 1142 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 1143 | 1144 | [[package]] 1145 | name = "libc" 1146 | version = "0.2.94" 1147 | source = "registry+https://github.com/rust-lang/crates.io-index" 1148 | checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e" 1149 | 1150 | [[package]] 1151 | name = "linked-hash-map" 1152 | version = "0.5.4" 1153 | source = "registry+https://github.com/rust-lang/crates.io-index" 1154 | checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" 1155 | 1156 | [[package]] 1157 | name = "lock_api" 1158 | version = "0.4.3" 1159 | source = "registry+https://github.com/rust-lang/crates.io-index" 1160 | checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176" 1161 | dependencies = [ 1162 | "scopeguard", 1163 | ] 1164 | 1165 | [[package]] 1166 | name = "log" 1167 | version = "0.4.14" 1168 | source = "registry+https://github.com/rust-lang/crates.io-index" 1169 | checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" 1170 | dependencies = [ 1171 | "cfg-if 1.0.0", 1172 | ] 1173 | 1174 | [[package]] 1175 | name = "lru-cache" 1176 | version = "0.1.2" 1177 | source = "registry+https://github.com/rust-lang/crates.io-index" 1178 | checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" 1179 | dependencies = [ 1180 | "linked-hash-map", 1181 | ] 1182 | 1183 | [[package]] 1184 | name = "match_cfg" 1185 | version = "0.1.0" 1186 | source = "registry+https://github.com/rust-lang/crates.io-index" 1187 | checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" 1188 | 1189 | [[package]] 1190 | name = "matches" 1191 | version = "0.1.8" 1192 | source = "registry+https://github.com/rust-lang/crates.io-index" 1193 | checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" 1194 | 1195 | [[package]] 1196 | name = "md-5" 1197 | version = "0.8.0" 1198 | source = "registry+https://github.com/rust-lang/crates.io-index" 1199 | checksum = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8" 1200 | dependencies = [ 1201 | "block-buffer 0.7.3", 1202 | "digest 0.8.1", 1203 | "opaque-debug 0.2.3", 1204 | ] 1205 | 1206 | [[package]] 1207 | name = "memchr" 1208 | version = "2.3.4" 1209 | source = "registry+https://github.com/rust-lang/crates.io-index" 1210 | checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" 1211 | 1212 | [[package]] 1213 | name = "mime" 1214 | version = "0.3.16" 1215 | source = "registry+https://github.com/rust-lang/crates.io-index" 1216 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 1217 | 1218 | [[package]] 1219 | name = "mime_guess" 1220 | version = "2.0.3" 1221 | source = "registry+https://github.com/rust-lang/crates.io-index" 1222 | checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" 1223 | dependencies = [ 1224 | "mime", 1225 | "unicase", 1226 | ] 1227 | 1228 | [[package]] 1229 | name = "miniz_oxide" 1230 | version = "0.4.4" 1231 | source = "registry+https://github.com/rust-lang/crates.io-index" 1232 | checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" 1233 | dependencies = [ 1234 | "adler", 1235 | "autocfg", 1236 | ] 1237 | 1238 | [[package]] 1239 | name = "mio" 1240 | version = "0.6.23" 1241 | source = "registry+https://github.com/rust-lang/crates.io-index" 1242 | checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" 1243 | dependencies = [ 1244 | "cfg-if 0.1.10", 1245 | "fuchsia-zircon", 1246 | "fuchsia-zircon-sys", 1247 | "iovec", 1248 | "kernel32-sys", 1249 | "libc", 1250 | "log", 1251 | "miow", 1252 | "net2", 1253 | "slab", 1254 | "winapi 0.2.8", 1255 | ] 1256 | 1257 | [[package]] 1258 | name = "mio-uds" 1259 | version = "0.6.8" 1260 | source = "registry+https://github.com/rust-lang/crates.io-index" 1261 | checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" 1262 | dependencies = [ 1263 | "iovec", 1264 | "libc", 1265 | "mio", 1266 | ] 1267 | 1268 | [[package]] 1269 | name = "miow" 1270 | version = "0.2.2" 1271 | source = "registry+https://github.com/rust-lang/crates.io-index" 1272 | checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" 1273 | dependencies = [ 1274 | "kernel32-sys", 1275 | "net2", 1276 | "winapi 0.2.8", 1277 | "ws2_32-sys", 1278 | ] 1279 | 1280 | [[package]] 1281 | name = "mongodb" 1282 | version = "1.2.1" 1283 | source = "registry+https://github.com/rust-lang/crates.io-index" 1284 | checksum = "4d2870708d8bdb6c652e20a7a04cf2e7e0493c786a650cc39eecd134a46e919e" 1285 | dependencies = [ 1286 | "async-trait", 1287 | "base64 0.11.0", 1288 | "bitflags", 1289 | "bson", 1290 | "chrono", 1291 | "derivative", 1292 | "err-derive", 1293 | "futures", 1294 | "hex", 1295 | "hmac", 1296 | "lazy_static", 1297 | "md-5", 1298 | "os_info", 1299 | "pbkdf2", 1300 | "percent-encoding", 1301 | "rand", 1302 | "reqwest", 1303 | "rustls 0.17.0", 1304 | "serde", 1305 | "serde_bytes", 1306 | "serde_with", 1307 | "sha-1 0.8.2", 1308 | "sha2", 1309 | "socket2", 1310 | "stringprep", 1311 | "strsim", 1312 | "take_mut", 1313 | "time 0.1.44", 1314 | "tokio", 1315 | "tokio-rustls 0.13.1", 1316 | "trust-dns-proto", 1317 | "trust-dns-resolver", 1318 | "typed-builder", 1319 | "uuid", 1320 | "version_check", 1321 | "webpki", 1322 | "webpki-roots 0.18.0", 1323 | ] 1324 | 1325 | [[package]] 1326 | name = "net2" 1327 | version = "0.2.37" 1328 | source = "registry+https://github.com/rust-lang/crates.io-index" 1329 | checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" 1330 | dependencies = [ 1331 | "cfg-if 0.1.10", 1332 | "libc", 1333 | "winapi 0.3.9", 1334 | ] 1335 | 1336 | [[package]] 1337 | name = "num-integer" 1338 | version = "0.1.44" 1339 | source = "registry+https://github.com/rust-lang/crates.io-index" 1340 | checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" 1341 | dependencies = [ 1342 | "autocfg", 1343 | "num-traits", 1344 | ] 1345 | 1346 | [[package]] 1347 | name = "num-traits" 1348 | version = "0.2.14" 1349 | source = "registry+https://github.com/rust-lang/crates.io-index" 1350 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" 1351 | dependencies = [ 1352 | "autocfg", 1353 | ] 1354 | 1355 | [[package]] 1356 | name = "num_cpus" 1357 | version = "1.13.0" 1358 | source = "registry+https://github.com/rust-lang/crates.io-index" 1359 | checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" 1360 | dependencies = [ 1361 | "hermit-abi", 1362 | "libc", 1363 | ] 1364 | 1365 | [[package]] 1366 | name = "object" 1367 | version = "0.23.0" 1368 | source = "registry+https://github.com/rust-lang/crates.io-index" 1369 | checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" 1370 | 1371 | [[package]] 1372 | name = "once_cell" 1373 | version = "1.7.2" 1374 | source = "registry+https://github.com/rust-lang/crates.io-index" 1375 | checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" 1376 | 1377 | [[package]] 1378 | name = "opaque-debug" 1379 | version = "0.2.3" 1380 | source = "registry+https://github.com/rust-lang/crates.io-index" 1381 | checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" 1382 | 1383 | [[package]] 1384 | name = "opaque-debug" 1385 | version = "0.3.0" 1386 | source = "registry+https://github.com/rust-lang/crates.io-index" 1387 | checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" 1388 | 1389 | [[package]] 1390 | name = "os_info" 1391 | version = "3.0.4" 1392 | source = "registry+https://github.com/rust-lang/crates.io-index" 1393 | checksum = "afaa687e89d04fcd3573987b14965578e54434a120c9477500e24b95b6fe79ee" 1394 | dependencies = [ 1395 | "log", 1396 | "winapi 0.3.9", 1397 | ] 1398 | 1399 | [[package]] 1400 | name = "parking_lot" 1401 | version = "0.11.1" 1402 | source = "registry+https://github.com/rust-lang/crates.io-index" 1403 | checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" 1404 | dependencies = [ 1405 | "instant", 1406 | "lock_api", 1407 | "parking_lot_core", 1408 | ] 1409 | 1410 | [[package]] 1411 | name = "parking_lot_core" 1412 | version = "0.8.3" 1413 | source = "registry+https://github.com/rust-lang/crates.io-index" 1414 | checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" 1415 | dependencies = [ 1416 | "cfg-if 1.0.0", 1417 | "instant", 1418 | "libc", 1419 | "redox_syscall", 1420 | "smallvec", 1421 | "winapi 0.3.9", 1422 | ] 1423 | 1424 | [[package]] 1425 | name = "pbkdf2" 1426 | version = "0.3.0" 1427 | source = "registry+https://github.com/rust-lang/crates.io-index" 1428 | checksum = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" 1429 | dependencies = [ 1430 | "byteorder", 1431 | "crypto-mac", 1432 | ] 1433 | 1434 | [[package]] 1435 | name = "percent-encoding" 1436 | version = "2.1.0" 1437 | source = "registry+https://github.com/rust-lang/crates.io-index" 1438 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 1439 | 1440 | [[package]] 1441 | name = "pin-project" 1442 | version = "0.4.28" 1443 | source = "registry+https://github.com/rust-lang/crates.io-index" 1444 | checksum = "918192b5c59119d51e0cd221f4d49dde9112824ba717369e903c97d076083d0f" 1445 | dependencies = [ 1446 | "pin-project-internal 0.4.28", 1447 | ] 1448 | 1449 | [[package]] 1450 | name = "pin-project" 1451 | version = "1.0.7" 1452 | source = "registry+https://github.com/rust-lang/crates.io-index" 1453 | checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4" 1454 | dependencies = [ 1455 | "pin-project-internal 1.0.7", 1456 | ] 1457 | 1458 | [[package]] 1459 | name = "pin-project-internal" 1460 | version = "0.4.28" 1461 | source = "registry+https://github.com/rust-lang/crates.io-index" 1462 | checksum = "3be26700300be6d9d23264c73211d8190e755b6b5ca7a1b28230025511b52a5e" 1463 | dependencies = [ 1464 | "proc-macro2", 1465 | "quote", 1466 | "syn", 1467 | ] 1468 | 1469 | [[package]] 1470 | name = "pin-project-internal" 1471 | version = "1.0.7" 1472 | source = "registry+https://github.com/rust-lang/crates.io-index" 1473 | checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f" 1474 | dependencies = [ 1475 | "proc-macro2", 1476 | "quote", 1477 | "syn", 1478 | ] 1479 | 1480 | [[package]] 1481 | name = "pin-project-lite" 1482 | version = "0.1.12" 1483 | source = "registry+https://github.com/rust-lang/crates.io-index" 1484 | checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" 1485 | 1486 | [[package]] 1487 | name = "pin-project-lite" 1488 | version = "0.2.6" 1489 | source = "registry+https://github.com/rust-lang/crates.io-index" 1490 | checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" 1491 | 1492 | [[package]] 1493 | name = "pin-utils" 1494 | version = "0.1.0" 1495 | source = "registry+https://github.com/rust-lang/crates.io-index" 1496 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1497 | 1498 | [[package]] 1499 | name = "ppv-lite86" 1500 | version = "0.2.10" 1501 | source = "registry+https://github.com/rust-lang/crates.io-index" 1502 | checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" 1503 | 1504 | [[package]] 1505 | name = "proc-macro-error" 1506 | version = "1.0.4" 1507 | source = "registry+https://github.com/rust-lang/crates.io-index" 1508 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 1509 | dependencies = [ 1510 | "proc-macro-error-attr", 1511 | "proc-macro2", 1512 | "quote", 1513 | "syn", 1514 | "version_check", 1515 | ] 1516 | 1517 | [[package]] 1518 | name = "proc-macro-error-attr" 1519 | version = "1.0.4" 1520 | source = "registry+https://github.com/rust-lang/crates.io-index" 1521 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 1522 | dependencies = [ 1523 | "proc-macro2", 1524 | "quote", 1525 | "version_check", 1526 | ] 1527 | 1528 | [[package]] 1529 | name = "proc-macro-hack" 1530 | version = "0.5.19" 1531 | source = "registry+https://github.com/rust-lang/crates.io-index" 1532 | checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" 1533 | 1534 | [[package]] 1535 | name = "proc-macro-nested" 1536 | version = "0.1.7" 1537 | source = "registry+https://github.com/rust-lang/crates.io-index" 1538 | checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" 1539 | 1540 | [[package]] 1541 | name = "proc-macro2" 1542 | version = "1.0.26" 1543 | source = "registry+https://github.com/rust-lang/crates.io-index" 1544 | checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" 1545 | dependencies = [ 1546 | "unicode-xid", 1547 | ] 1548 | 1549 | [[package]] 1550 | name = "quick-error" 1551 | version = "1.2.3" 1552 | source = "registry+https://github.com/rust-lang/crates.io-index" 1553 | checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" 1554 | 1555 | [[package]] 1556 | name = "quote" 1557 | version = "1.0.9" 1558 | source = "registry+https://github.com/rust-lang/crates.io-index" 1559 | checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" 1560 | dependencies = [ 1561 | "proc-macro2", 1562 | ] 1563 | 1564 | [[package]] 1565 | name = "rand" 1566 | version = "0.7.3" 1567 | source = "registry+https://github.com/rust-lang/crates.io-index" 1568 | checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" 1569 | dependencies = [ 1570 | "getrandom 0.1.16", 1571 | "libc", 1572 | "rand_chacha", 1573 | "rand_core", 1574 | "rand_hc", 1575 | "rand_pcg", 1576 | ] 1577 | 1578 | [[package]] 1579 | name = "rand_chacha" 1580 | version = "0.2.2" 1581 | source = "registry+https://github.com/rust-lang/crates.io-index" 1582 | checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" 1583 | dependencies = [ 1584 | "ppv-lite86", 1585 | "rand_core", 1586 | ] 1587 | 1588 | [[package]] 1589 | name = "rand_core" 1590 | version = "0.5.1" 1591 | source = "registry+https://github.com/rust-lang/crates.io-index" 1592 | checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" 1593 | dependencies = [ 1594 | "getrandom 0.1.16", 1595 | ] 1596 | 1597 | [[package]] 1598 | name = "rand_hc" 1599 | version = "0.2.0" 1600 | source = "registry+https://github.com/rust-lang/crates.io-index" 1601 | checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" 1602 | dependencies = [ 1603 | "rand_core", 1604 | ] 1605 | 1606 | [[package]] 1607 | name = "rand_pcg" 1608 | version = "0.2.1" 1609 | source = "registry+https://github.com/rust-lang/crates.io-index" 1610 | checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" 1611 | dependencies = [ 1612 | "rand_core", 1613 | ] 1614 | 1615 | [[package]] 1616 | name = "redox_syscall" 1617 | version = "0.2.7" 1618 | source = "registry+https://github.com/rust-lang/crates.io-index" 1619 | checksum = "85dd92e586f7355c633911e11f77f3d12f04b1b1bd76a198bd34ae3af8341ef2" 1620 | dependencies = [ 1621 | "bitflags", 1622 | ] 1623 | 1624 | [[package]] 1625 | name = "regex" 1626 | version = "1.4.6" 1627 | source = "registry+https://github.com/rust-lang/crates.io-index" 1628 | checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759" 1629 | dependencies = [ 1630 | "aho-corasick", 1631 | "memchr", 1632 | "regex-syntax", 1633 | ] 1634 | 1635 | [[package]] 1636 | name = "regex-syntax" 1637 | version = "0.6.23" 1638 | source = "registry+https://github.com/rust-lang/crates.io-index" 1639 | checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548" 1640 | 1641 | [[package]] 1642 | name = "reqwest" 1643 | version = "0.10.10" 1644 | source = "registry+https://github.com/rust-lang/crates.io-index" 1645 | checksum = "0718f81a8e14c4dbb3b34cf23dc6aaf9ab8a0dfec160c534b3dbca1aaa21f47c" 1646 | dependencies = [ 1647 | "base64 0.13.0", 1648 | "bytes 0.5.6", 1649 | "encoding_rs", 1650 | "futures-core", 1651 | "futures-util", 1652 | "http", 1653 | "http-body", 1654 | "hyper", 1655 | "hyper-rustls", 1656 | "ipnet", 1657 | "js-sys", 1658 | "lazy_static", 1659 | "log", 1660 | "mime", 1661 | "mime_guess", 1662 | "percent-encoding", 1663 | "pin-project-lite 0.2.6", 1664 | "rustls 0.18.1", 1665 | "serde", 1666 | "serde_json", 1667 | "serde_urlencoded", 1668 | "tokio", 1669 | "tokio-rustls 0.14.1", 1670 | "url", 1671 | "wasm-bindgen", 1672 | "wasm-bindgen-futures", 1673 | "web-sys", 1674 | "webpki-roots 0.20.0", 1675 | "winreg 0.7.0", 1676 | ] 1677 | 1678 | [[package]] 1679 | name = "resolv-conf" 1680 | version = "0.7.0" 1681 | source = "registry+https://github.com/rust-lang/crates.io-index" 1682 | checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" 1683 | dependencies = [ 1684 | "hostname", 1685 | "quick-error", 1686 | ] 1687 | 1688 | [[package]] 1689 | name = "ring" 1690 | version = "0.16.20" 1691 | source = "registry+https://github.com/rust-lang/crates.io-index" 1692 | checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" 1693 | dependencies = [ 1694 | "cc", 1695 | "libc", 1696 | "once_cell", 1697 | "spin", 1698 | "untrusted", 1699 | "web-sys", 1700 | "winapi 0.3.9", 1701 | ] 1702 | 1703 | [[package]] 1704 | name = "rustc-demangle" 1705 | version = "0.1.18" 1706 | source = "registry+https://github.com/rust-lang/crates.io-index" 1707 | checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" 1708 | 1709 | [[package]] 1710 | name = "rustc_version" 1711 | version = "0.2.3" 1712 | source = "registry+https://github.com/rust-lang/crates.io-index" 1713 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 1714 | dependencies = [ 1715 | "semver", 1716 | ] 1717 | 1718 | [[package]] 1719 | name = "rustls" 1720 | version = "0.17.0" 1721 | source = "registry+https://github.com/rust-lang/crates.io-index" 1722 | checksum = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1" 1723 | dependencies = [ 1724 | "base64 0.11.0", 1725 | "log", 1726 | "ring", 1727 | "sct", 1728 | "webpki", 1729 | ] 1730 | 1731 | [[package]] 1732 | name = "rustls" 1733 | version = "0.18.1" 1734 | source = "registry+https://github.com/rust-lang/crates.io-index" 1735 | checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" 1736 | dependencies = [ 1737 | "base64 0.12.3", 1738 | "log", 1739 | "ring", 1740 | "sct", 1741 | "webpki", 1742 | ] 1743 | 1744 | [[package]] 1745 | name = "rustversion" 1746 | version = "1.0.4" 1747 | source = "registry+https://github.com/rust-lang/crates.io-index" 1748 | checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd" 1749 | 1750 | [[package]] 1751 | name = "ryu" 1752 | version = "1.0.5" 1753 | source = "registry+https://github.com/rust-lang/crates.io-index" 1754 | checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" 1755 | 1756 | [[package]] 1757 | name = "scopeguard" 1758 | version = "1.1.0" 1759 | source = "registry+https://github.com/rust-lang/crates.io-index" 1760 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1761 | 1762 | [[package]] 1763 | name = "sct" 1764 | version = "0.6.1" 1765 | source = "registry+https://github.com/rust-lang/crates.io-index" 1766 | checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" 1767 | dependencies = [ 1768 | "ring", 1769 | "untrusted", 1770 | ] 1771 | 1772 | [[package]] 1773 | name = "semver" 1774 | version = "0.9.0" 1775 | source = "registry+https://github.com/rust-lang/crates.io-index" 1776 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 1777 | dependencies = [ 1778 | "semver-parser", 1779 | ] 1780 | 1781 | [[package]] 1782 | name = "semver-parser" 1783 | version = "0.7.0" 1784 | source = "registry+https://github.com/rust-lang/crates.io-index" 1785 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 1786 | 1787 | [[package]] 1788 | name = "serde" 1789 | version = "1.0.125" 1790 | source = "registry+https://github.com/rust-lang/crates.io-index" 1791 | checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" 1792 | dependencies = [ 1793 | "serde_derive", 1794 | ] 1795 | 1796 | [[package]] 1797 | name = "serde_bytes" 1798 | version = "0.11.5" 1799 | source = "registry+https://github.com/rust-lang/crates.io-index" 1800 | checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9" 1801 | dependencies = [ 1802 | "serde", 1803 | ] 1804 | 1805 | [[package]] 1806 | name = "serde_derive" 1807 | version = "1.0.125" 1808 | source = "registry+https://github.com/rust-lang/crates.io-index" 1809 | checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" 1810 | dependencies = [ 1811 | "proc-macro2", 1812 | "quote", 1813 | "syn", 1814 | ] 1815 | 1816 | [[package]] 1817 | name = "serde_json" 1818 | version = "1.0.64" 1819 | source = "registry+https://github.com/rust-lang/crates.io-index" 1820 | checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" 1821 | dependencies = [ 1822 | "indexmap", 1823 | "itoa", 1824 | "ryu", 1825 | "serde", 1826 | ] 1827 | 1828 | [[package]] 1829 | name = "serde_urlencoded" 1830 | version = "0.7.0" 1831 | source = "registry+https://github.com/rust-lang/crates.io-index" 1832 | checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" 1833 | dependencies = [ 1834 | "form_urlencoded", 1835 | "itoa", 1836 | "ryu", 1837 | "serde", 1838 | ] 1839 | 1840 | [[package]] 1841 | name = "serde_with" 1842 | version = "1.8.1" 1843 | source = "registry+https://github.com/rust-lang/crates.io-index" 1844 | checksum = "26b0b98f61935da47683bf5c46b965ce1642ef1db78860b8a1defb68bf1b5b43" 1845 | dependencies = [ 1846 | "rustversion", 1847 | "serde", 1848 | "serde_with_macros", 1849 | ] 1850 | 1851 | [[package]] 1852 | name = "serde_with_macros" 1853 | version = "1.4.1" 1854 | source = "registry+https://github.com/rust-lang/crates.io-index" 1855 | checksum = "e48b35457e9d855d3dc05ef32a73e0df1e2c0fd72c38796a4ee909160c8eeec2" 1856 | dependencies = [ 1857 | "darling", 1858 | "proc-macro2", 1859 | "quote", 1860 | "syn", 1861 | ] 1862 | 1863 | [[package]] 1864 | name = "sha-1" 1865 | version = "0.8.2" 1866 | source = "registry+https://github.com/rust-lang/crates.io-index" 1867 | checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" 1868 | dependencies = [ 1869 | "block-buffer 0.7.3", 1870 | "digest 0.8.1", 1871 | "fake-simd", 1872 | "opaque-debug 0.2.3", 1873 | ] 1874 | 1875 | [[package]] 1876 | name = "sha-1" 1877 | version = "0.9.4" 1878 | source = "registry+https://github.com/rust-lang/crates.io-index" 1879 | checksum = "dfebf75d25bd900fd1e7d11501efab59bc846dbc76196839663e6637bba9f25f" 1880 | dependencies = [ 1881 | "block-buffer 0.9.0", 1882 | "cfg-if 1.0.0", 1883 | "cpuid-bool", 1884 | "digest 0.9.0", 1885 | "opaque-debug 0.3.0", 1886 | ] 1887 | 1888 | [[package]] 1889 | name = "sha1" 1890 | version = "0.6.0" 1891 | source = "registry+https://github.com/rust-lang/crates.io-index" 1892 | checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" 1893 | 1894 | [[package]] 1895 | name = "sha2" 1896 | version = "0.8.2" 1897 | source = "registry+https://github.com/rust-lang/crates.io-index" 1898 | checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" 1899 | dependencies = [ 1900 | "block-buffer 0.7.3", 1901 | "digest 0.8.1", 1902 | "fake-simd", 1903 | "opaque-debug 0.2.3", 1904 | ] 1905 | 1906 | [[package]] 1907 | name = "signal-hook-registry" 1908 | version = "1.3.0" 1909 | source = "registry+https://github.com/rust-lang/crates.io-index" 1910 | checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" 1911 | dependencies = [ 1912 | "libc", 1913 | ] 1914 | 1915 | [[package]] 1916 | name = "slab" 1917 | version = "0.4.3" 1918 | source = "registry+https://github.com/rust-lang/crates.io-index" 1919 | checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" 1920 | 1921 | [[package]] 1922 | name = "smallvec" 1923 | version = "1.6.1" 1924 | source = "registry+https://github.com/rust-lang/crates.io-index" 1925 | checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" 1926 | 1927 | [[package]] 1928 | name = "socket2" 1929 | version = "0.3.19" 1930 | source = "registry+https://github.com/rust-lang/crates.io-index" 1931 | checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" 1932 | dependencies = [ 1933 | "cfg-if 1.0.0", 1934 | "libc", 1935 | "winapi 0.3.9", 1936 | ] 1937 | 1938 | [[package]] 1939 | name = "spin" 1940 | version = "0.5.2" 1941 | source = "registry+https://github.com/rust-lang/crates.io-index" 1942 | checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" 1943 | 1944 | [[package]] 1945 | name = "standback" 1946 | version = "0.2.17" 1947 | source = "registry+https://github.com/rust-lang/crates.io-index" 1948 | checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" 1949 | dependencies = [ 1950 | "version_check", 1951 | ] 1952 | 1953 | [[package]] 1954 | name = "stdweb" 1955 | version = "0.4.20" 1956 | source = "registry+https://github.com/rust-lang/crates.io-index" 1957 | checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" 1958 | dependencies = [ 1959 | "discard", 1960 | "rustc_version", 1961 | "stdweb-derive", 1962 | "stdweb-internal-macros", 1963 | "stdweb-internal-runtime", 1964 | "wasm-bindgen", 1965 | ] 1966 | 1967 | [[package]] 1968 | name = "stdweb-derive" 1969 | version = "0.5.3" 1970 | source = "registry+https://github.com/rust-lang/crates.io-index" 1971 | checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" 1972 | dependencies = [ 1973 | "proc-macro2", 1974 | "quote", 1975 | "serde", 1976 | "serde_derive", 1977 | "syn", 1978 | ] 1979 | 1980 | [[package]] 1981 | name = "stdweb-internal-macros" 1982 | version = "0.2.9" 1983 | source = "registry+https://github.com/rust-lang/crates.io-index" 1984 | checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" 1985 | dependencies = [ 1986 | "base-x", 1987 | "proc-macro2", 1988 | "quote", 1989 | "serde", 1990 | "serde_derive", 1991 | "serde_json", 1992 | "sha1", 1993 | "syn", 1994 | ] 1995 | 1996 | [[package]] 1997 | name = "stdweb-internal-runtime" 1998 | version = "0.1.5" 1999 | source = "registry+https://github.com/rust-lang/crates.io-index" 2000 | checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" 2001 | 2002 | [[package]] 2003 | name = "stringprep" 2004 | version = "0.1.2" 2005 | source = "registry+https://github.com/rust-lang/crates.io-index" 2006 | checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" 2007 | dependencies = [ 2008 | "unicode-bidi", 2009 | "unicode-normalization", 2010 | ] 2011 | 2012 | [[package]] 2013 | name = "strsim" 2014 | version = "0.10.0" 2015 | source = "registry+https://github.com/rust-lang/crates.io-index" 2016 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 2017 | 2018 | [[package]] 2019 | name = "subtle" 2020 | version = "1.0.0" 2021 | source = "registry+https://github.com/rust-lang/crates.io-index" 2022 | checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" 2023 | 2024 | [[package]] 2025 | name = "syn" 2026 | version = "1.0.71" 2027 | source = "registry+https://github.com/rust-lang/crates.io-index" 2028 | checksum = "ad184cc9470f9117b2ac6817bfe297307418819ba40552f9b3846f05c33d5373" 2029 | dependencies = [ 2030 | "proc-macro2", 2031 | "quote", 2032 | "unicode-xid", 2033 | ] 2034 | 2035 | [[package]] 2036 | name = "synstructure" 2037 | version = "0.12.4" 2038 | source = "registry+https://github.com/rust-lang/crates.io-index" 2039 | checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" 2040 | dependencies = [ 2041 | "proc-macro2", 2042 | "quote", 2043 | "syn", 2044 | "unicode-xid", 2045 | ] 2046 | 2047 | [[package]] 2048 | name = "take_mut" 2049 | version = "0.2.2" 2050 | source = "registry+https://github.com/rust-lang/crates.io-index" 2051 | checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" 2052 | 2053 | [[package]] 2054 | name = "thiserror" 2055 | version = "1.0.24" 2056 | source = "registry+https://github.com/rust-lang/crates.io-index" 2057 | checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" 2058 | dependencies = [ 2059 | "thiserror-impl", 2060 | ] 2061 | 2062 | [[package]] 2063 | name = "thiserror-impl" 2064 | version = "1.0.24" 2065 | source = "registry+https://github.com/rust-lang/crates.io-index" 2066 | checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" 2067 | dependencies = [ 2068 | "proc-macro2", 2069 | "quote", 2070 | "syn", 2071 | ] 2072 | 2073 | [[package]] 2074 | name = "threadpool" 2075 | version = "1.8.1" 2076 | source = "registry+https://github.com/rust-lang/crates.io-index" 2077 | checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" 2078 | dependencies = [ 2079 | "num_cpus", 2080 | ] 2081 | 2082 | [[package]] 2083 | name = "time" 2084 | version = "0.1.44" 2085 | source = "registry+https://github.com/rust-lang/crates.io-index" 2086 | checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" 2087 | dependencies = [ 2088 | "libc", 2089 | "wasi 0.10.0+wasi-snapshot-preview1", 2090 | "winapi 0.3.9", 2091 | ] 2092 | 2093 | [[package]] 2094 | name = "time" 2095 | version = "0.2.26" 2096 | source = "registry+https://github.com/rust-lang/crates.io-index" 2097 | checksum = "08a8cbfbf47955132d0202d1662f49b2423ae35862aee471f3ba4b133358f372" 2098 | dependencies = [ 2099 | "const_fn", 2100 | "libc", 2101 | "standback", 2102 | "stdweb", 2103 | "time-macros", 2104 | "version_check", 2105 | "winapi 0.3.9", 2106 | ] 2107 | 2108 | [[package]] 2109 | name = "time-macros" 2110 | version = "0.1.1" 2111 | source = "registry+https://github.com/rust-lang/crates.io-index" 2112 | checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" 2113 | dependencies = [ 2114 | "proc-macro-hack", 2115 | "time-macros-impl", 2116 | ] 2117 | 2118 | [[package]] 2119 | name = "time-macros-impl" 2120 | version = "0.1.1" 2121 | source = "registry+https://github.com/rust-lang/crates.io-index" 2122 | checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa" 2123 | dependencies = [ 2124 | "proc-macro-hack", 2125 | "proc-macro2", 2126 | "quote", 2127 | "standback", 2128 | "syn", 2129 | ] 2130 | 2131 | [[package]] 2132 | name = "tinyvec" 2133 | version = "1.2.0" 2134 | source = "registry+https://github.com/rust-lang/crates.io-index" 2135 | checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" 2136 | dependencies = [ 2137 | "tinyvec_macros", 2138 | ] 2139 | 2140 | [[package]] 2141 | name = "tinyvec_macros" 2142 | version = "0.1.0" 2143 | source = "registry+https://github.com/rust-lang/crates.io-index" 2144 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 2145 | 2146 | [[package]] 2147 | name = "tokio" 2148 | version = "0.2.25" 2149 | source = "registry+https://github.com/rust-lang/crates.io-index" 2150 | checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" 2151 | dependencies = [ 2152 | "bytes 0.5.6", 2153 | "fnv", 2154 | "futures-core", 2155 | "iovec", 2156 | "lazy_static", 2157 | "libc", 2158 | "memchr", 2159 | "mio", 2160 | "mio-uds", 2161 | "num_cpus", 2162 | "pin-project-lite 0.1.12", 2163 | "signal-hook-registry", 2164 | "slab", 2165 | "tokio-macros", 2166 | "winapi 0.3.9", 2167 | ] 2168 | 2169 | [[package]] 2170 | name = "tokio-macros" 2171 | version = "0.2.6" 2172 | source = "registry+https://github.com/rust-lang/crates.io-index" 2173 | checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" 2174 | dependencies = [ 2175 | "proc-macro2", 2176 | "quote", 2177 | "syn", 2178 | ] 2179 | 2180 | [[package]] 2181 | name = "tokio-rustls" 2182 | version = "0.13.1" 2183 | source = "registry+https://github.com/rust-lang/crates.io-index" 2184 | checksum = "15cb62a0d2770787abc96e99c1cd98fcf17f94959f3af63ca85bdfb203f051b4" 2185 | dependencies = [ 2186 | "futures-core", 2187 | "rustls 0.17.0", 2188 | "tokio", 2189 | "webpki", 2190 | ] 2191 | 2192 | [[package]] 2193 | name = "tokio-rustls" 2194 | version = "0.14.1" 2195 | source = "registry+https://github.com/rust-lang/crates.io-index" 2196 | checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a" 2197 | dependencies = [ 2198 | "futures-core", 2199 | "rustls 0.18.1", 2200 | "tokio", 2201 | "webpki", 2202 | ] 2203 | 2204 | [[package]] 2205 | name = "tokio-util" 2206 | version = "0.3.1" 2207 | source = "registry+https://github.com/rust-lang/crates.io-index" 2208 | checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" 2209 | dependencies = [ 2210 | "bytes 0.5.6", 2211 | "futures-core", 2212 | "futures-sink", 2213 | "log", 2214 | "pin-project-lite 0.1.12", 2215 | "tokio", 2216 | ] 2217 | 2218 | [[package]] 2219 | name = "tower-service" 2220 | version = "0.3.1" 2221 | source = "registry+https://github.com/rust-lang/crates.io-index" 2222 | checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" 2223 | 2224 | [[package]] 2225 | name = "tracing" 2226 | version = "0.1.25" 2227 | source = "registry+https://github.com/rust-lang/crates.io-index" 2228 | checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" 2229 | dependencies = [ 2230 | "cfg-if 1.0.0", 2231 | "log", 2232 | "pin-project-lite 0.2.6", 2233 | "tracing-core", 2234 | ] 2235 | 2236 | [[package]] 2237 | name = "tracing-core" 2238 | version = "0.1.17" 2239 | source = "registry+https://github.com/rust-lang/crates.io-index" 2240 | checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f" 2241 | dependencies = [ 2242 | "lazy_static", 2243 | ] 2244 | 2245 | [[package]] 2246 | name = "tracing-futures" 2247 | version = "0.2.5" 2248 | source = "registry+https://github.com/rust-lang/crates.io-index" 2249 | checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" 2250 | dependencies = [ 2251 | "pin-project 1.0.7", 2252 | "tracing", 2253 | ] 2254 | 2255 | [[package]] 2256 | name = "trust-dns-proto" 2257 | version = "0.19.7" 2258 | source = "registry+https://github.com/rust-lang/crates.io-index" 2259 | checksum = "1cad71a0c0d68ab9941d2fb6e82f8fb2e86d9945b94e1661dd0aaea2b88215a9" 2260 | dependencies = [ 2261 | "async-trait", 2262 | "backtrace", 2263 | "cfg-if 1.0.0", 2264 | "enum-as-inner", 2265 | "futures", 2266 | "idna", 2267 | "lazy_static", 2268 | "log", 2269 | "rand", 2270 | "smallvec", 2271 | "thiserror", 2272 | "tokio", 2273 | "url", 2274 | ] 2275 | 2276 | [[package]] 2277 | name = "trust-dns-resolver" 2278 | version = "0.19.7" 2279 | source = "registry+https://github.com/rust-lang/crates.io-index" 2280 | checksum = "710f593b371175db53a26d0b38ed2978fafb9e9e8d3868b1acd753ea18df0ceb" 2281 | dependencies = [ 2282 | "cfg-if 0.1.10", 2283 | "futures", 2284 | "ipconfig", 2285 | "lazy_static", 2286 | "log", 2287 | "lru-cache", 2288 | "resolv-conf", 2289 | "smallvec", 2290 | "thiserror", 2291 | "tokio", 2292 | "trust-dns-proto", 2293 | ] 2294 | 2295 | [[package]] 2296 | name = "try-lock" 2297 | version = "0.2.3" 2298 | source = "registry+https://github.com/rust-lang/crates.io-index" 2299 | checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" 2300 | 2301 | [[package]] 2302 | name = "typed-builder" 2303 | version = "0.4.1" 2304 | source = "registry+https://github.com/rust-lang/crates.io-index" 2305 | checksum = "dfc955f27acc7a547f328f52f4a5a568986a31efec2fc6de865279f3995787b9" 2306 | dependencies = [ 2307 | "proc-macro2", 2308 | "quote", 2309 | "syn", 2310 | ] 2311 | 2312 | [[package]] 2313 | name = "typenum" 2314 | version = "1.13.0" 2315 | source = "registry+https://github.com/rust-lang/crates.io-index" 2316 | checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" 2317 | 2318 | [[package]] 2319 | name = "unicase" 2320 | version = "2.6.0" 2321 | source = "registry+https://github.com/rust-lang/crates.io-index" 2322 | checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" 2323 | dependencies = [ 2324 | "version_check", 2325 | ] 2326 | 2327 | [[package]] 2328 | name = "unicode-bidi" 2329 | version = "0.3.5" 2330 | source = "registry+https://github.com/rust-lang/crates.io-index" 2331 | checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" 2332 | dependencies = [ 2333 | "matches", 2334 | ] 2335 | 2336 | [[package]] 2337 | name = "unicode-normalization" 2338 | version = "0.1.17" 2339 | source = "registry+https://github.com/rust-lang/crates.io-index" 2340 | checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" 2341 | dependencies = [ 2342 | "tinyvec", 2343 | ] 2344 | 2345 | [[package]] 2346 | name = "unicode-segmentation" 2347 | version = "1.7.1" 2348 | source = "registry+https://github.com/rust-lang/crates.io-index" 2349 | checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" 2350 | 2351 | [[package]] 2352 | name = "unicode-xid" 2353 | version = "0.2.2" 2354 | source = "registry+https://github.com/rust-lang/crates.io-index" 2355 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 2356 | 2357 | [[package]] 2358 | name = "untrusted" 2359 | version = "0.7.1" 2360 | source = "registry+https://github.com/rust-lang/crates.io-index" 2361 | checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" 2362 | 2363 | [[package]] 2364 | name = "url" 2365 | version = "2.2.1" 2366 | source = "registry+https://github.com/rust-lang/crates.io-index" 2367 | checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" 2368 | dependencies = [ 2369 | "form_urlencoded", 2370 | "idna", 2371 | "matches", 2372 | "percent-encoding", 2373 | ] 2374 | 2375 | [[package]] 2376 | name = "uuid" 2377 | version = "0.8.2" 2378 | source = "registry+https://github.com/rust-lang/crates.io-index" 2379 | checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" 2380 | dependencies = [ 2381 | "getrandom 0.2.2", 2382 | ] 2383 | 2384 | [[package]] 2385 | name = "version_check" 2386 | version = "0.9.3" 2387 | source = "registry+https://github.com/rust-lang/crates.io-index" 2388 | checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" 2389 | 2390 | [[package]] 2391 | name = "want" 2392 | version = "0.3.0" 2393 | source = "registry+https://github.com/rust-lang/crates.io-index" 2394 | checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" 2395 | dependencies = [ 2396 | "log", 2397 | "try-lock", 2398 | ] 2399 | 2400 | [[package]] 2401 | name = "wasi" 2402 | version = "0.9.0+wasi-snapshot-preview1" 2403 | source = "registry+https://github.com/rust-lang/crates.io-index" 2404 | checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" 2405 | 2406 | [[package]] 2407 | name = "wasi" 2408 | version = "0.10.0+wasi-snapshot-preview1" 2409 | source = "registry+https://github.com/rust-lang/crates.io-index" 2410 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" 2411 | 2412 | [[package]] 2413 | name = "wasm-bindgen" 2414 | version = "0.2.73" 2415 | source = "registry+https://github.com/rust-lang/crates.io-index" 2416 | checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9" 2417 | dependencies = [ 2418 | "cfg-if 1.0.0", 2419 | "serde", 2420 | "serde_json", 2421 | "wasm-bindgen-macro", 2422 | ] 2423 | 2424 | [[package]] 2425 | name = "wasm-bindgen-backend" 2426 | version = "0.2.73" 2427 | source = "registry+https://github.com/rust-lang/crates.io-index" 2428 | checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae" 2429 | dependencies = [ 2430 | "bumpalo", 2431 | "lazy_static", 2432 | "log", 2433 | "proc-macro2", 2434 | "quote", 2435 | "syn", 2436 | "wasm-bindgen-shared", 2437 | ] 2438 | 2439 | [[package]] 2440 | name = "wasm-bindgen-futures" 2441 | version = "0.4.23" 2442 | source = "registry+https://github.com/rust-lang/crates.io-index" 2443 | checksum = "81b8b767af23de6ac18bf2168b690bed2902743ddf0fb39252e36f9e2bfc63ea" 2444 | dependencies = [ 2445 | "cfg-if 1.0.0", 2446 | "js-sys", 2447 | "wasm-bindgen", 2448 | "web-sys", 2449 | ] 2450 | 2451 | [[package]] 2452 | name = "wasm-bindgen-macro" 2453 | version = "0.2.73" 2454 | source = "registry+https://github.com/rust-lang/crates.io-index" 2455 | checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f" 2456 | dependencies = [ 2457 | "quote", 2458 | "wasm-bindgen-macro-support", 2459 | ] 2460 | 2461 | [[package]] 2462 | name = "wasm-bindgen-macro-support" 2463 | version = "0.2.73" 2464 | source = "registry+https://github.com/rust-lang/crates.io-index" 2465 | checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c" 2466 | dependencies = [ 2467 | "proc-macro2", 2468 | "quote", 2469 | "syn", 2470 | "wasm-bindgen-backend", 2471 | "wasm-bindgen-shared", 2472 | ] 2473 | 2474 | [[package]] 2475 | name = "wasm-bindgen-shared" 2476 | version = "0.2.73" 2477 | source = "registry+https://github.com/rust-lang/crates.io-index" 2478 | checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489" 2479 | 2480 | [[package]] 2481 | name = "web-sys" 2482 | version = "0.3.50" 2483 | source = "registry+https://github.com/rust-lang/crates.io-index" 2484 | checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be" 2485 | dependencies = [ 2486 | "js-sys", 2487 | "wasm-bindgen", 2488 | ] 2489 | 2490 | [[package]] 2491 | name = "webpki" 2492 | version = "0.21.4" 2493 | source = "registry+https://github.com/rust-lang/crates.io-index" 2494 | checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" 2495 | dependencies = [ 2496 | "ring", 2497 | "untrusted", 2498 | ] 2499 | 2500 | [[package]] 2501 | name = "webpki-roots" 2502 | version = "0.18.0" 2503 | source = "registry+https://github.com/rust-lang/crates.io-index" 2504 | checksum = "91cd5736df7f12a964a5067a12c62fa38e1bd8080aff1f80bc29be7c80d19ab4" 2505 | dependencies = [ 2506 | "webpki", 2507 | ] 2508 | 2509 | [[package]] 2510 | name = "webpki-roots" 2511 | version = "0.20.0" 2512 | source = "registry+https://github.com/rust-lang/crates.io-index" 2513 | checksum = "0f20dea7535251981a9670857150d571846545088359b28e4951d350bdaf179f" 2514 | dependencies = [ 2515 | "webpki", 2516 | ] 2517 | 2518 | [[package]] 2519 | name = "widestring" 2520 | version = "0.4.3" 2521 | source = "registry+https://github.com/rust-lang/crates.io-index" 2522 | checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" 2523 | 2524 | [[package]] 2525 | name = "winapi" 2526 | version = "0.2.8" 2527 | source = "registry+https://github.com/rust-lang/crates.io-index" 2528 | checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 2529 | 2530 | [[package]] 2531 | name = "winapi" 2532 | version = "0.3.9" 2533 | source = "registry+https://github.com/rust-lang/crates.io-index" 2534 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2535 | dependencies = [ 2536 | "winapi-i686-pc-windows-gnu", 2537 | "winapi-x86_64-pc-windows-gnu", 2538 | ] 2539 | 2540 | [[package]] 2541 | name = "winapi-build" 2542 | version = "0.1.1" 2543 | source = "registry+https://github.com/rust-lang/crates.io-index" 2544 | checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 2545 | 2546 | [[package]] 2547 | name = "winapi-i686-pc-windows-gnu" 2548 | version = "0.4.0" 2549 | source = "registry+https://github.com/rust-lang/crates.io-index" 2550 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2551 | 2552 | [[package]] 2553 | name = "winapi-x86_64-pc-windows-gnu" 2554 | version = "0.4.0" 2555 | source = "registry+https://github.com/rust-lang/crates.io-index" 2556 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2557 | 2558 | [[package]] 2559 | name = "winreg" 2560 | version = "0.6.2" 2561 | source = "registry+https://github.com/rust-lang/crates.io-index" 2562 | checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" 2563 | dependencies = [ 2564 | "winapi 0.3.9", 2565 | ] 2566 | 2567 | [[package]] 2568 | name = "winreg" 2569 | version = "0.7.0" 2570 | source = "registry+https://github.com/rust-lang/crates.io-index" 2571 | checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" 2572 | dependencies = [ 2573 | "winapi 0.3.9", 2574 | ] 2575 | 2576 | [[package]] 2577 | name = "ws2_32-sys" 2578 | version = "0.2.1" 2579 | source = "registry+https://github.com/rust-lang/crates.io-index" 2580 | checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" 2581 | dependencies = [ 2582 | "winapi 0.2.8", 2583 | "winapi-build", 2584 | ] 2585 | -------------------------------------------------------------------------------- /actix-cocktail-api/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "actix-cocktail-api" 3 | version = "0.1.0" 4 | authors = ["Mark Smith "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | actix-web = "3" 11 | mongodb = "1.2.1" 12 | serde = "1.0" 13 | serde_json = "1.0.64" 14 | futures = "0.3.14" 15 | chrono = { version = "0.4.19", features = ["serde"] } 16 | tokio = "0.2.25" -------------------------------------------------------------------------------- /actix-cocktail-api/README.md: -------------------------------------------------------------------------------- 1 | # Flask Cocktail API 2 | 3 | A simple API for getting cocktail recipes. 4 | 5 | This code was written as part of a [MongoDB Developer Hub blog post](https://developer.mongodb.com/), 6 | it's not really designed to stand alone. 7 | 8 | ## Run the code 9 | 10 | You'll need to set the environment variable `MONGO_URI` to the URL of your MongoDB replicaset. 11 | I use `direnv` to configure this, and put the following line in my `.envrc` file in my project's directory: 12 | 13 | ```bash 14 | export MONGO_URI="mongodb+srv://USERNAME:PASSW0RD@cluster0-abcde.azure.mongodb.net/cocktails?retryWrites=true&w=majority" 15 | ``` 16 | 17 | You can then import the sample data with mongoimport: 18 | 19 | ```bash 20 | mongoimport --uri "$MONGO_URI" --file ../data/recipes.json 21 | ``` 22 | 23 | And now you should be able to run the service like this: 24 | 25 | ```bash 26 | 27 | cargo run 28 | ``` 29 | -------------------------------------------------------------------------------- /actix-cocktail-api/src/main.rs: -------------------------------------------------------------------------------- 1 | mod model; 2 | mod routes; 3 | 4 | use actix_web::{middleware, App, HttpServer}; 5 | use mongodb; 6 | use mongodb::{options::ClientOptions, Client, Collection}; 7 | use std::env; 8 | 9 | #[actix_web::main] 10 | async fn main() -> std::io::Result<()> { 11 | let client_options = ClientOptions::parse( 12 | &env::var("MONGO_URI").expect("The MONGO_URI environment variable must be set."), 13 | ) 14 | .await 15 | .unwrap(); 16 | let client = Client::with_options(client_options).unwrap(); 17 | let recipes: Collection = 18 | client.database("cocktails").collection_with_type("recipes"); 19 | 20 | HttpServer::new(move || { 21 | App::new() 22 | .data(recipes.clone()) 23 | .wrap(middleware::Logger::default()) 24 | .service(routes::list_cocktails) 25 | .service(routes::get_cocktail) 26 | .service(routes::new_cocktail) 27 | .service(routes::update_cocktail) 28 | .service(routes::delete_cocktail) 29 | }) 30 | .bind("127.0.0.1:5000")? 31 | .run() 32 | .await 33 | } 34 | -------------------------------------------------------------------------------- /actix-cocktail-api/src/model.rs: -------------------------------------------------------------------------------- 1 | use chrono::{DateTime, Utc}; 2 | use mongodb::bson::oid::ObjectId; 3 | use serde::{Deserialize, Serialize}; 4 | use serde_json::Value; 5 | use std::convert::TryFrom; 6 | 7 | #[derive(Serialize, Deserialize, Debug, Clone)] 8 | struct Quantity { 9 | #[serde(skip_serializing_if = "Option::is_none")] 10 | value: Option, 11 | #[serde(skip_serializing_if = "Option::is_none")] 12 | unit: Option, 13 | } 14 | 15 | #[derive(Serialize, Deserialize, Debug, Clone)] 16 | struct Ingredient { 17 | name: String, 18 | quantity: Option, 19 | } 20 | 21 | #[derive(Serialize, Deserialize, Debug, Clone)] 22 | pub struct Cocktail { 23 | #[serde(rename = "_id", skip_serializing_if = "Option::is_none")] 24 | id: Option, 25 | slug: String, 26 | name: String, 27 | ingredients: Vec, 28 | instructions: Vec, 29 | #[serde(skip_serializing_if = "Option::is_none")] 30 | pub date_added: Option>, 31 | #[serde(skip_serializing_if = "Option::is_none")] 32 | pub date_updated: Option>, 33 | } 34 | 35 | #[derive(Serialize, Deserialize, Debug, Clone)] 36 | pub struct CocktailJSON { 37 | #[serde(skip_serializing_if = "Option::is_none")] 38 | id: Option, 39 | slug: String, 40 | name: String, 41 | ingredients: Vec, 42 | instructions: Vec, 43 | #[serde(skip_serializing_if = "Option::is_none")] 44 | date_added: Option>, 45 | #[serde(skip_serializing_if = "Option::is_none")] 46 | date_updated: Option>, 47 | } 48 | 49 | impl From for CocktailJSON { 50 | fn from(cocktail: Cocktail) -> Self { 51 | Self { 52 | id: cocktail.id.map(|id| id.to_hex()), 53 | slug: cocktail.slug, 54 | name: cocktail.name, 55 | ingredients: cocktail.ingredients, 56 | instructions: cocktail.instructions, 57 | date_added: cocktail.date_added, 58 | date_updated: cocktail.date_updated, 59 | } 60 | } 61 | } 62 | 63 | impl TryFrom for Cocktail { 64 | type Error = mongodb::bson::oid::Error; 65 | 66 | fn try_from(cocktail: CocktailJSON) -> Result { 67 | let cocktail_oid = match cocktail.id { 68 | Some(id) => Some(ObjectId::with_string(&id)?), 69 | None => None, 70 | }; 71 | 72 | Ok(Self { 73 | id: cocktail_oid, 74 | slug: cocktail.slug, 75 | name: cocktail.name, 76 | ingredients: cocktail.ingredients, 77 | instructions: cocktail.instructions, 78 | date_added: cocktail.date_added, 79 | date_updated: cocktail.date_updated, 80 | }) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /actix-cocktail-api/src/routes.rs: -------------------------------------------------------------------------------- 1 | use std::{cmp::max, convert::TryFrom, time::Duration}; 2 | 3 | use crate::model::{Cocktail, CocktailJSON}; 4 | use actix_web::{ 5 | delete, get, post, put, 6 | web::{self, Json}, 7 | HttpRequest, HttpResponse, Responder, 8 | }; 9 | use futures::stream::StreamExt; 10 | use mongodb; 11 | use mongodb::Collection; 12 | use mongodb::{bson::doc, options::FindOptions}; 13 | use serde::{Deserialize, Serialize}; 14 | use tokio; 15 | 16 | fn default_page() -> i64 { 17 | 1 18 | } 19 | 20 | #[derive(Serialize)] 21 | struct ErrorJSON { 22 | error: String, 23 | } 24 | 25 | impl ErrorJSON { 26 | fn new(message: String) -> Self { 27 | Self { error: message } 28 | } 29 | } 30 | 31 | #[derive(Deserialize)] 32 | struct ListCocktailsParams { 33 | #[serde(default = "default_page")] 34 | page: i64, 35 | } 36 | 37 | #[derive(Serialize)] 38 | struct ListCocktailsResult { 39 | recipes: Vec, 40 | links: Links, 41 | } 42 | 43 | impl ListCocktailsResult { 44 | fn new( 45 | recipes: Vec, 46 | page: i64, 47 | page_size: i64, 48 | cocktail_count: i64, 49 | url_for: fn(i64) -> String, 50 | ) -> Self { 51 | Self { 52 | recipes: recipes.into_iter().map(CocktailJSON::from).collect(), 53 | links: Links::new(page, (cocktail_count / page_size) + 1, url_for), 54 | } 55 | } 56 | } 57 | 58 | #[derive(Serialize)] 59 | struct Link { 60 | href: String, 61 | } 62 | 63 | impl Link { 64 | fn new(href: String) -> Self { 65 | Self { href: href } 66 | } 67 | } 68 | 69 | #[derive(Serialize)] 70 | struct Links { 71 | #[serde(rename = "self")] 72 | this: Link, 73 | first: Link, 74 | last: Link, 75 | #[serde(skip_serializing_if = "Option::is_none")] 76 | prev: Option, 77 | #[serde(skip_serializing_if = "Option::is_none")] 78 | next: Option, 79 | } 80 | 81 | impl Links { 82 | fn new(page: i64, max_page: i64, url_for: fn(i64) -> String) -> Self { 83 | return Links { 84 | this: Link::new(url_for(page)), 85 | first: Link::new(url_for(1)), 86 | last: Link::new(url_for(max_page)), 87 | prev: if page > 1 { 88 | Some(Link::new(url_for(page - 1))) 89 | } else { 90 | None 91 | }, 92 | next: if page < max_page { 93 | Some(Link::new(url_for(page + 1))) 94 | } else { 95 | None 96 | }, 97 | }; 98 | } 99 | } 100 | 101 | #[get("/cocktails/")] 102 | async fn list_cocktails( 103 | request: HttpRequest, 104 | recipes: web::Data>, 105 | web::Query(params): web::Query, 106 | ) -> impl Responder { 107 | const PAGE_SIZE: i64 = 10; 108 | 109 | let page = max(params.page, 1); 110 | 111 | let cocktail_count = match recipes.count_documents(None, None).await { 112 | Ok(cocktail_count) => cocktail_count, 113 | Err(e) => { 114 | println!("Error while listing cocktails: {:?}", e); 115 | return HttpResponse::InternalServerError().finish(); 116 | } 117 | }; 118 | 119 | let result = recipes 120 | .find( 121 | None, 122 | FindOptions::builder() 123 | .sort(doc! { "name": 1 }) 124 | .skip((page - 1) * PAGE_SIZE) 125 | .limit(PAGE_SIZE) 126 | .build(), 127 | ) 128 | .await; 129 | match result { 130 | Ok(cursor) => { 131 | let results: Vec> = cursor.collect().await; 132 | let result: Result, _> = results.into_iter().collect(); 133 | match result { 134 | Ok(cocktails) => { 135 | return HttpResponse::Ok().json(ListCocktailsResult::new( 136 | cocktails, 137 | page, 138 | PAGE_SIZE, 139 | cocktail_count, 140 | |i| format!("/cocktails/?page={}", i), 141 | )) 142 | } 143 | Err(e) => { 144 | println!("Error while listing cocktails: {:?}", e); 145 | return HttpResponse::InternalServerError().finish(); 146 | } 147 | } 148 | } 149 | Err(e) => { 150 | println!("Error while listing cocktails: {:?}", e); 151 | return HttpResponse::InternalServerError().finish(); 152 | } 153 | } 154 | } 155 | 156 | #[post("/cocktails/")] 157 | async fn new_cocktail( 158 | recipes: web::Data>, 159 | Json(cocktail_json): Json, 160 | ) -> impl Responder { 161 | let mut cocktail = match Cocktail::try_from(cocktail_json) { 162 | Ok(doc) => doc, 163 | Err(e) => { 164 | println!("Error parsing cocktail: {:?}", e); 165 | return HttpResponse::InternalServerError().finish(); 166 | } 167 | }; 168 | cocktail.date_added = Some(chrono::Utc::now()); 169 | 170 | let insert_result = match recipes.insert_one(cocktail, None).await { 171 | Ok(insert_result) => insert_result, 172 | Err(e) => { 173 | println!("Error retrieving inserted cocktail: {:?}", e); 174 | return HttpResponse::InternalServerError().finish(); 175 | } 176 | }; 177 | 178 | match recipes 179 | .find_one(doc! {"_id": insert_result.inserted_id}, None) 180 | .await 181 | { 182 | Ok(result) => { 183 | if let Some(recipe) = result { 184 | HttpResponse::Ok().json(CocktailJSON::from(recipe)) 185 | } else { 186 | HttpResponse::NotFound().finish() 187 | } 188 | } 189 | Err(e) => { 190 | println!("Error retrieving saved cocktail {:?}", e); 191 | HttpResponse::InternalServerError().finish() 192 | } 193 | } 194 | } 195 | 196 | #[get("/cocktails/{slug}")] 197 | async fn get_cocktail( 198 | recipes: web::Data>, 199 | web::Path(slug): web::Path, 200 | ) -> impl Responder { 201 | match recipes.find_one(doc! { "slug": slug }, None).await { 202 | Ok(result) => { 203 | if let Some(recipe) = result { 204 | HttpResponse::Ok().json(CocktailJSON::from(recipe)) 205 | } else { 206 | HttpResponse::NotFound().finish() 207 | } 208 | } 209 | Err(e) => { 210 | println!("Error while getting, {:?}", e); 211 | HttpResponse::InternalServerError().finish() 212 | } 213 | } 214 | } 215 | 216 | #[put("/cocktails/{slug}")] 217 | async fn update_cocktail( 218 | recipes: web::Data>, 219 | web::Path(slug): web::Path, 220 | Json(cocktail_json): Json, 221 | ) -> impl Responder { 222 | let mut cocktail = match Cocktail::try_from(cocktail_json) { 223 | Ok(doc) => doc, 224 | Err(e) => { 225 | println!("Error parsing cocktail: {:?}", e); 226 | return HttpResponse::InternalServerError().finish(); 227 | } 228 | }; 229 | cocktail.date_updated = Some(chrono::Utc::now()); 230 | 231 | println!("Cocktail prepared"); 232 | let update_result = match recipes 233 | .update_one( 234 | doc! {"slug": &slug}, 235 | doc! {"$set": mongodb::bson::to_bson(&cocktail).unwrap()}, 236 | None, 237 | ) 238 | .await 239 | { 240 | Ok(update_result) => update_result, 241 | Err(e) => { 242 | println!("Error updating cocktail: {:?}", e); 243 | return HttpResponse::InternalServerError().finish(); 244 | } 245 | }; 246 | println!("Matched cocktails: {}", &update_result.matched_count); 247 | 248 | if update_result.matched_count == 1 { 249 | tokio::time::delay_for(Duration::from_secs(1)).await; 250 | match recipes.find_one(doc! { "slug": &slug }, None).await { 251 | Ok(result) => { 252 | if let Some(recipe) = result { 253 | HttpResponse::Ok().json(CocktailJSON::from(recipe)) 254 | } else { 255 | println!("Cannot retrieve updated document: {}", &slug); 256 | HttpResponse::InternalServerError().finish() 257 | } 258 | } 259 | Err(e) => { 260 | println!("Error while getting, {:?}", e); 261 | HttpResponse::InternalServerError().finish() 262 | } 263 | } 264 | } else { 265 | HttpResponse::NotFound().finish() 266 | } 267 | } 268 | 269 | #[delete("/cocktails/{slug}")] 270 | async fn delete_cocktail( 271 | recipes: web::Data>, 272 | web::Path(slug): web::Path, 273 | ) -> impl Responder { 274 | match recipes 275 | .find_one_and_delete(doc! { "slug": slug }, None) 276 | .await 277 | { 278 | Ok(result) => { 279 | if let Some(recipe) = result { 280 | HttpResponse::Ok().json(CocktailJSON::from(recipe)) 281 | } else { 282 | HttpResponse::NotFound().finish() 283 | } 284 | } 285 | Err(e) => { 286 | println!("Error while getting, {:?}", e); 287 | HttpResponse::InternalServerError().finish() 288 | } 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /data/README.md: -------------------------------------------------------------------------------- 1 | # Sample Data 2 | 3 | This folder contains sample data for the Cocktails API apps. 4 | This data is designed to be used to complement an accompanying blog post. 5 | The data was exported using [mongoexport](https://docs.mongodb.com/v4.0/reference/program/mongoexport/) 6 | and can be imported into your own database using [mongoimport](https://docs.mongodb.com/v4.0/reference/program/mongoimport/). 7 | 8 | Use the following command in this directory to import the collection into your database 9 | (be aware that currently the sample code depends on the database being called "cocktails" and the collection "recipes"). 10 | 11 | ```bash 12 | 13 | mongoimport --uri YOUR-ATLAS-DB-URI --file ./recipes.json 14 | ``` 15 | -------------------------------------------------------------------------------- /data/recipes.json: -------------------------------------------------------------------------------- 1 | {"_id":{"$oid":"5f7b4b54159a7c1dfd96cceb"},"name":"Espresso Martini","ingredients":[{"name":"Vodka","quantity":{"value":30,"unit":"ml"}},{"name":"Espresso","quantity":{"value":30,"unit":"ml"}},{"name":"Kahlúa","quantity":{"value":20,"unit":"ml"}},{"name":"Salt","quantity":{"value":1,"unit":"pinch"}}],"garnish":"3 coffee beans","instructions":["Shake ingredients with ice.","Strain into a coupe or martini glass.","Express 1 lemon twist and discard.","Float 3 coffee beans in the centre."],"slug":"espresso-martini"} 2 | {"_id":{"$oid":"5f7b4b5b8165eba7eac164c8"},"name":"Manhattan","ingredients":[{"name":"Bourbon Whiskey","quantity":{"value":60,"unit":"ml"}},{"name":"Sweet Vermouth","quantity":{"value":30,"unit":"ml"}}],"garnish":"Maraschino Cherry","instructions":["Combine ingredients and stir with ice.","Strain into a coupe or martini glass.","Garnish with a maraschino cherry."],"slug":"manhattan"} 3 | {"_id":{"$oid":"5f7b4b6204799f5cf837b1e1"},"name":"Negroni Sbagliato","ingredients":[{"name":"Campari","quantity":{"value":30,"unit":"ml"}},{"name":"Sweet Vermouth","quantity":{"value":30,"unit":"ml"}},{"name":"Prosecco","quantity":{"value":30,"unit":"ml"}}],"garnish":"Orange Twist","instructions":["Stir Campari & vermouth with ice","Pour into a champagne flute","Add wine & gently combine","Serve with orange twist"],"reviews":[{"rating":4,"when":{"$date":"2020-11-08T16:53:25.905Z"}},{"rating":4,"when":{"$date":"2020-11-08T16:54:15.279Z"}},{"rating":4,"when":{"$date":"2020-11-08T16:54:23.818Z"}},{"rating":4,"when":{"$date":"2020-11-08T16:54:26.744Z"}},{"rating":4,"when":{"$date":"2020-11-08T17:40:26.656Z"}},{"rating":4,"when":{"$date":"2020-11-08T17:51:02.903Z"}}],"slug":"negroni-sbagliato"} 4 | {"_id":{"$oid":"5f7b4b66933b475afc75430e"},"name":"Rye Whisky Old Fashioned","ingredients":[{"name":"Rye Whiskey","quantity":{"value":60,"unit":"ml"}},{"name":"Simple Syrup","quantity":{"value":1,"unit":"barspoon"}},{"name":"Angostura Bitters","quantity":{"value":2,"unit":"dash"}},{"name":"Orange Bitters","quantity":{"value":1,"unit":"dash"}}],"garnish":"Lemon Twist","instructions":["Combine ingredients and stir with ice.","Garnish with lemon twist."],"slug":"rye-whisky-old-fashioned"} 5 | {"_id":{"$oid":"5f7d8d0a0dd78abf4d3b4312"},"name":"Planter's Punch","instructions":["Pour all ingredients, except the bitters, into shaker filled with ice","Shake well","Pour into large glass, filled with ice","Add Angostura bitters, \"on top\"","Garnish with cocktail cherry and pineapple."],"ingredients":[{"name":"Dark rum","quantity":{"quantity":"1","unit":"part"}},{"name":"Orgeat syrup","quantity":{"quantity":"1/2","unit":"part"}},{"name":"Orange juice","quantity":{"quantity":"2","unit":"parts"}},{"name":"Pineapple juice","quantity":{"quantity":"1","unit":"part"}}],"slug":"planter-s-punch"} 6 | {"_id":{"$oid":"5f7daa018ec9dfb536781afa"},"name":"Abilene","instructions":["Pour all of the ingredients into a highball glass almost filled with ice cubes","Stir well."],"ingredients":[{"name":"Dark rum","quantity":{"quantity":"45","unit":"ml"}},{"name":"Peach nectar","quantity":{"quantity":"2","unit":"oz"}},{"name":"Orange juice","quantity":{"quantity":"3","unit":"oz"}}],"slug":"abilene"} 7 | {"_id":{"$oid":"5f7daa028ec9dfb536781afb"},"name":"Pink Lady","instructions":["Shake all ingredients with ice, strain into a cocktail glass, and serve."],"ingredients":[{"name":"Gin","quantity":{"quantity":"1 1/2","unit":"oz"}},{"name":"Grenadine","quantity":{"quantity":"1","unit":"tsp"}},{"name":"Light cream","quantity":{"quantity":"1","unit":"tsp"}},{"name":"Egg white","quantity":{"quantity":"1","unit":null}}],"slug":"pink-lady"} 8 | {"_id":{"$oid":"5f7daa048ec9dfb536781afc"},"name":"Flying Scotchman","instructions":["Shake all ingredients with ice, strain into a cocktail glass, and serve."],"ingredients":[{"name":"Scotch","quantity":{"quantity":"1","unit":"oz"}},{"name":"Sweet Vermouth","quantity":{"quantity":"1","unit":"oz"}},{"name":"Bitters","quantity":{"quantity":"1","unit":"dash"}},{"name":"Sugar syrup","quantity":{"quantity":"1/4","unit":"tsp"}}],"slug":"flying-scotchman"} 9 | {"_id":{"$oid":"5f7daa058ec9dfb536781afd"},"name":"Big Red","instructions":["Pour ingredients into 1 ounce shot glass"],"ingredients":[{"name":"Irish cream","quantity":{"quantity":"1/2","unit":"oz"}},{"name":"Goldschlager","quantity":{"quantity":"1/2","unit":"oz"}}],"slug":"big-red"} 10 | {"_id":{"$oid":"5f7daa068ec9dfb536781afe"},"name":"Frozen Mint Daiquiri","instructions":["Combine all ingredients with 1 cup of crushed ice in an electric blender","Blend at a low speed for a short length of time","Pour into an old-fashioned glass and serve."],"ingredients":[{"name":"Light rum","quantity":{"quantity":"2","unit":"oz"}},{"name":"Lime juice","quantity":{"quantity":"1","unit":"tblsp"}},{"name":"Mint","quantity":{"quantity":"6","unit":null}},{"name":"Sugar","quantity":{"quantity":"1","unit":"tsp"}}],"slug":"frozen-mint-daiquiri"} 11 | {"_id":{"$oid":"5f7daa078ec9dfb536781aff"},"name":"Spiking coffee","instructions":["Incidentally, a pinch of cinnamon is indeed a nice addition to coffee but true heaven is a cardamom seed","Of course, you serve it in a coffee mug."],"ingredients":[{"name":"Coffee"},{"name":"Cinnamon"}],"slug":"spiking-coffee"} 12 | {"_id":{"$oid":"5f7daa088ec9dfb536781b00"},"name":"Sloe Gin Cocktail","instructions":["Stir all ingredients with ice, strain into a cocktail glass, and serve."],"ingredients":[{"name":"Sloe gin","quantity":{"quantity":"2","unit":"oz"}},{"name":"Dry Vermouth","quantity":{"quantity":"1/4","unit":"tsp"}},{"name":"Orange bitters","quantity":{"quantity":"1","unit":"dash"}}],"slug":"sloe-gin-cocktail"} 13 | {"_id":{"$oid":"5f7daa0a8ec9dfb536781b01"},"name":"Scooter","instructions":["Shake all ingredients well with cracked ice, strain into a cocktail glass, and serve."],"ingredients":[{"name":"Brandy","quantity":{"quantity":"1","unit":"oz"}},{"name":"Amaretto","quantity":{"quantity":"1","unit":"oz"}},{"name":"Light cream","quantity":{"quantity":"1","unit":"oz"}}],"slug":"scooter"} 14 | {"_id":{"$oid":"5f7daa0b8ec9dfb536781b02"},"name":"Imperial Fizz","instructions":["Shake all ingredients (except carbonated water) with ice and strain into a highball glass over two ice cubes","Fill with carbonated water, stir, and serve."],"ingredients":[{"name":"Light rum","quantity":{"quantity":"1/2","unit":"oz"}},{"name":"Blended whiskey","quantity":{"quantity":"1 1/2","unit":"oz"}},{"name":"Lemon","quantity":{"quantity":"1/2","unit":null}},{"name":"Powdered sugar","quantity":{"quantity":"1","unit":"tsp"}},{"name":"Carbonated water"}],"slug":"imperial-fizz"} 15 | {"_id":{"$oid":"5f7daa0d8ec9dfb536781b04"},"name":"Highland Fling Cocktail","instructions":["Stir all ingredients (except olive) with ice and strain into a cocktail glass","Add the olive and serve."],"ingredients":[{"name":"Scotch","quantity":{"quantity":"1 1/2","unit":"oz"}},{"name":"Sweet Vermouth","quantity":{"quantity":"3/4","unit":"oz"}},{"name":"Orange bitters","quantity":{"quantity":"2","unit":"dashes"}},{"name":"Olive","quantity":{"quantity":"1","unit":null}}],"slug":"highland-fling-cocktail"} 16 | {"_id":{"$oid":"5f7daa0f8ec9dfb536781b05"},"name":"Abbey Cocktail","instructions":["Shake all ingredients (except for the cherry) with ice and strain into a cocktail glass","Top with the cherry and serve."],"ingredients":[{"name":"Gin","quantity":{"quantity":"1 1/2","unit":"oz"}},{"name":"Orange bitters","quantity":{"quantity":"1","unit":"dash"}},{"name":"Orange","quantity":{"quantity":"1/4","unit":null}},{"name":"Cherry","quantity":{"quantity":"1","unit":null}}],"slug":"abbey-cocktail"} 17 | {"_id":{"$oid":"5f7daa108ec9dfb536781b06"},"name":"Fruit Flip-Flop","instructions":["Place all ingredients in the blender jar - cover and whiz on medium speed until well blended","Pour in one tall, 2 medium or 3 small glasses and drink up."],"ingredients":[{"name":"Yoghurt","quantity":{"quantity":"1","unit":"cup"}},{"name":"Fruit juice","quantity":{"quantity":"1","unit":"cup"}}],"slug":"fruit-flip-flop"} 18 | {"_id":{"$oid":"5f7daa138ec9dfb536781b09"},"name":"Alfie Cocktail","instructions":["Combine and shake all ingredients with ice, strain into a cocktail glass, and serve."],"ingredients":[{"name":"Lemon vodka","quantity":{"quantity":"1 1/2","unit":"oz"}},{"name":"Triple sec","quantity":{"quantity":"1","unit":"dash"}},{"name":"Pineapple juice","quantity":{"quantity":"1","unit":"tblsp"}}],"slug":"alfie-cocktail"} 19 | {"_id":{"$oid":"5f7daa158ec9dfb536781b0a"},"name":"Hunter's Moon","instructions":["Put the Bombay Sapphire, Martini Bianco, sugar syrup & blackberries in a cocktail shaker with lots of ice and shake vigorously before pouring into a balloon glass, topping up with lemonade and garnishing with a wedge of orange."],"ingredients":[{"name":"Vermouth","quantity":{"quantity":"25","unit":"ml"}},{"name":"Maraschino Cherry","quantity":{"quantity":"15","unit":"ml"}},{"name":"Sugar Syrup","quantity":{"quantity":"10","unit":"ml"}},{"name":"Lemonade","quantity":{"quantity":"100","unit":"ml"}},{"name":"Blackberries","quantity":{"quantity":"2","unit":null}}],"slug":"hunter-s-moon"} 20 | {"_id":{"$oid":"5f7daa168ec9dfb536781b0b"},"name":"A midsummernight dream","instructions":["Mix the strawberrys in a blender Pour it together with the vodka,kirch and strawberry liquer over ice in a shaker","Shake well and pour in a highballglass","Fill up with the Russchian water"],"ingredients":[{"name":"Vodka","quantity":{"quantity":"2","unit":"oz"}},{"name":"Kirschwasser","quantity":{"quantity":"1","unit":"oz"}},{"name":"Strawberry liqueur","quantity":{"quantity":"1","unit":"tsp"}},{"name":"Strawberries","quantity":{"quantity":"5","unit":null}},{"name":"Schweppes Russchian"}],"slug":"a-midsummernight-dream"} 21 | {"_id":{"$oid":"5f7daa178ec9dfb536781b0c"},"name":"Quaker's Cocktail","instructions":["Shake all ingredients with ice, strain into a cocktail glass, and serve."],"ingredients":[{"name":"Light rum","quantity":{"quantity":"3/4","unit":"oz"}},{"name":"Brandy","quantity":{"quantity":"3/4","unit":"oz"}},{"name":"Lemon","quantity":{"quantity":"1/4","unit":null}},{"name":"Raspberry syrup","quantity":{"quantity":"2","unit":"tsp"}}],"slug":"quaker-s-cocktail"} 22 | {"_id":{"$oid":"5f7daa198ec9dfb536781b0d"},"name":"Monkey Wrench","instructions":["Pour all of the ingredients into an old-fashioned glass almost filled with ice cubes","Stir well."],"ingredients":[{"name":"Light rum","quantity":{"quantity":"1 1/2","unit":"oz"}},{"name":"Grapefruit juice","quantity":{"quantity":"3","unit":"oz"}},{"name":"Bitters","quantity":{"quantity":"1","unit":"dash"}}],"slug":"monkey-wrench"} 23 | {"_id":{"$oid":"5f7daa1a8ec9dfb536781b0e"},"name":"Bruised Heart","instructions":["Pour all ingredients in a mixing tin over ice, stir, and strain into shot glass"],"ingredients":[{"name":"Vodka","quantity":{"quantity":"1/2","unit":"oz"}},{"name":"Chambord raspberry liqueur","quantity":{"quantity":"1/2","unit":"oz"}},{"name":"Peachtree schnapps","quantity":{"quantity":"1/2","unit":"oz"}},{"name":"Cranberry juice","quantity":{"quantity":"1/2","unit":"oz"}}],"slug":"bruised-heart"} 24 | {"_id":{"$oid":"5f7daa1b8ec9dfb536781b0f"},"name":"Sweet Tooth","instructions":["Put 2 shots Godiva Liquour into a glass, add as much or as little milk as you would like."],"ingredients":[{"name":"Godiva liqueur","quantity":{"quantity":"2","unit":"shots"}},{"name":"Milk"}],"slug":"sweet-tooth"} 25 | {"_id":{"$oid":"5f7daa1c8ec9dfb536781b10"},"name":"Oatmeal Cookie","instructions":["Just mix it all together.\r\nIt's meant to be a shot, but it works just fine as a proper adult-sized drink over lots of ice.\r\n\r\nTastes like an oatmeal cookie."],"ingredients":[{"name":"Kahlua","quantity":{"quantity":"2","unit":"parts"}},{"name":"Bailey","quantity":{"quantity":"2","unit":"parts"}},{"name":"Butterscotch schnapps","quantity":{"quantity":"4","unit":"parts"}},{"name":"Jagermeister","quantity":{"quantity":"1","unit":"part"}},{"name":"Goldschlager","quantity":{"quantity":"1/2","unit":"part"}}],"slug":"oatmeal-cookie"} 26 | {"_id":{"$oid":"5f7daa1e8ec9dfb536781b11"},"name":"B-52","instructions":["Layer ingredients into a shot glass","Serve with a stirrer."],"ingredients":[{"name":"Baileys irish cream","quantity":{"quantity":"1/3","unit":null}},{"name":"Grand Marnier","quantity":{"quantity":"1/3","unit":null}},{"name":"Kahlua","quantity":{"quantity":"1/4","unit":null}}],"slug":"b-52"} 27 | {"_id":{"$oid":"5f7daa1f8ec9dfb536781b12"},"name":"Long Island Tea","instructions":["Combine all ingredients (except cola) and pour over ice in a highball glass","Add the splash of cola for color","Decorate with a slice of lemon and serve."],"ingredients":[{"name":"Vodka","quantity":{"quantity":"1/2","unit":"oz"}},{"name":"Light rum","quantity":{"quantity":"1/2","unit":"oz"}},{"name":"Gin","quantity":{"quantity":"1/2","unit":"oz"}},{"name":"Tequila","quantity":{"quantity":"1/2","unit":"oz"}},{"name":"Lemon","quantity":{"quantity":"1/2","unit":null}},{"name":"Coca-Cola","quantity":{"quantity":"1","unit":"splash"}}],"slug":"long-island-tea"} 28 | {"_id":{"$oid":"5f7daa208ec9dfb536781b13"},"name":"Lord And Lady","instructions":["Pour the rum and Tia Maria into an old-fashioned glass almost filled with ice cubes","Stir well."],"ingredients":[{"name":"Dark rum","quantity":{"quantity":"1 1/2","unit":"oz"}},{"name":"Tia maria","quantity":{"quantity":"1/2","unit":"oz"}}],"slug":"lord-and-lady"} 29 | {"_id":{"$oid":"5f7daa218ec9dfb536781b14"},"name":"Dragonfly","instructions":["In a highball glass almost filled with ice cubes, combine the gin and ginger ale","Stir well","Garnish with the lime wedge."],"ingredients":[{"name":"Gin","quantity":{"quantity":"1 1/2","unit":"oz"}},{"name":"Ginger ale","quantity":{"quantity":"4","unit":"oz"}},{"name":"Lime","quantity":{"quantity":"1","unit":null}}],"slug":"dragonfly"} 30 | {"_id":{"$oid":"5f7daa228ec9dfb536781b15"},"name":"Applecar","instructions":["Shake all ingredients with ice, strain into a cocktail glass, and serve."],"ingredients":[{"name":"Applejack","quantity":{"quantity":"1","unit":"oz"}},{"name":"Triple sec","quantity":{"quantity":"1","unit":"oz"}},{"name":"Lemon juice","quantity":{"quantity":"1","unit":"oz"}}],"slug":"applecar"} 31 | {"_id":{"$oid":"5f7daa238ec9dfb536781b16"},"name":"Cuba Libre","instructions":["Build all ingredients in a Collins glass filled with ice","Garnish with lime wedge."],"ingredients":[{"name":"Light rum","quantity":{"quantity":"2","unit":"oz"}},{"name":"Lime","quantity":{"quantity":"1/2","unit":null}},{"name":"Coca-Cola"}],"slug":"cuba-libre"} 32 | {"_id":{"$oid":"5f7daa258ec9dfb536781b17"},"name":"White Russian","instructions":["Pour vodka and coffee liqueur over ice cubes in an old-fashioned glass","Fill with light cream and serve."],"ingredients":[{"name":"Vodka","quantity":{"quantity":"2","unit":"oz"}},{"name":"Coffee liqueur","quantity":{"quantity":"1","unit":"oz"}},{"name":"Light cream"}],"slug":"white-russian"} 33 | {"_id":{"$oid":"5f7daa268ec9dfb536781b18"},"name":"Vodka Fizz","instructions":["Blend all ingredients, save nutmeg","Pour into large white wine glass and sprinkle nutmeg on top."],"ingredients":[{"name":"Vodka","quantity":{"quantity":"2","unit":"oz"}},{"name":"Half-and-half","quantity":{"quantity":"2","unit":"oz"}},{"name":"Limeade","quantity":{"quantity":"2","unit":"oz"}},{"name":"Ice"},{"name":"Nutmeg"}],"slug":"vodka-fizz"} 34 | {"_id":{"$oid":"5f7daa288ec9dfb536781b19"},"name":"Between The Sheets","instructions":["Pour all ingredients into shaker with ice cubes, shake, strain into chilled cocktail glass."],"ingredients":[{"name":"Brandy","quantity":{"quantity":"1","unit":"oz"}},{"name":"Light rum","quantity":{"quantity":"1","unit":"oz"}},{"name":"Triple sec","quantity":{"quantity":"1","unit":"oz"}},{"name":"Lemon juice","quantity":{"quantity":"1","unit":"oz"}}],"slug":"between-the-sheets"} 35 | {"_id":{"$oid":"5f7daa298ec9dfb536781b1a"},"name":"Boston Sidecar","instructions":["Shake all ingredients with ice, strain into a cocktail glass, and serve."],"ingredients":[{"name":"Light rum","quantity":{"quantity":"3/4","unit":"oz"}},{"name":"Brandy","quantity":{"quantity":"3/4","unit":"oz"}},{"name":"Triple sec","quantity":{"quantity":"3/4","unit":"oz"}},{"name":"Lime","quantity":{"quantity":"1/2","unit":null}}],"slug":"boston-sidecar"} 36 | {"_id":{"$oid":"5f7daa2a8ec9dfb536781b1b"},"name":"Amaretto Sweet & Sour","instructions":["Fill the blender with 3/4 ice","Add sweet & sour mix to the top of the ice","Add about 1\" of pineapple juice, 1/2\" of melon liqeur, and 1/2 to 1/4\" of amaretto","Then blend the mix until it is of margaritta consistency or thinner."],"ingredients":[{"name":"Amaretto"},{"name":"Sweet and sour"},{"name":"Midori melon liqueur"},{"name":"Pineapple juice"}],"slug":"amaretto-sweet-sour"} 37 | {"_id":{"$oid":"5f7daa2b8ec9dfb536781b1c"},"name":"Apple Slammer","instructions":["pour into a shot glass and present to consumer, they are expected to cover the top of the shotglass with thier palm, raise the glass, slam it on the bar and the swallow quickly."],"ingredients":[{"name":"7-Up","quantity":{"quantity":"1","unit":"part"}},{"name":"Apple schnapps","quantity":{"quantity":"1","unit":"part"}}],"slug":"apple-slammer"} 38 | {"_id":{"$oid":"5f7daa2c8ec9dfb536781b1d"},"name":"Pink Gin","instructions":["Pour the bitters into a wine glass","Swirl the glass to coat the inside with the bitters, shake out the excess","Pour the gin into the glass","Do not add ice."],"ingredients":[{"name":"Bitters","quantity":{"quantity":"3","unit":"dashes"}},{"name":"Gin","quantity":{"quantity":"2","unit":"oz"}}],"slug":"pink-gin"} 39 | {"_id":{"$oid":"5f7daa2e8ec9dfb536781b1e"},"name":"Mississippi Planters Punch","instructions":["Shake all ingredients (except carbonated water) with ice and strain into a collins glass over ice cubes","Fill with carbonated water, stir, and serve."],"ingredients":[{"name":"Brandy","quantity":{"quantity":"1","unit":"oz"}},{"name":"Light rum","quantity":{"quantity":"1/2","unit":"oz"}},{"name":"Bourbon","quantity":{"quantity":"1/2","unit":"oz"}},{"name":"Lemon","quantity":{"quantity":"1/2","unit":null}},{"name":"Powdered sugar","quantity":{"quantity":"1","unit":"tblsp"}},{"name":"Carbonated water"}],"slug":"mississippi-planters-punch"} 40 | {"_id":{"$oid":"5f7daa2f8ec9dfb536781b1f"},"name":"Strawberry Daiquiri","instructions":["Pour all ingredients into shaker with ice cubes","Shake well","Strain in chilled cocktail glass."],"ingredients":[{"name":"Strawberry schnapps","quantity":{"quantity":"1/2","unit":"oz"}},{"name":"Light rum","quantity":{"quantity":"1","unit":"oz"}},{"name":"Lime juice","quantity":{"quantity":"1","unit":"oz"}},{"name":"Powdered sugar","quantity":{"quantity":"1","unit":"tsp"}},{"name":"Strawberries","quantity":{"quantity":"1","unit":"oz"}}],"slug":"strawberry-daiquiri"} 41 | {"_id":{"$oid":"5f7daa308ec9dfb536781b20"},"name":"English Highball","instructions":["Pour brandy, gin, and sweet vermouth into a highball glass over ice cubes","Fill with carbonated water","Add the twist of lemon peel, stir, and serve","(Ginger ale may be substituted for carbonated water, if preferred.)"],"ingredients":[{"name":"Brandy","quantity":{"quantity":"3/4","unit":"oz"}},{"name":"Gin","quantity":{"quantity":"3/4","unit":"oz"}},{"name":"Sweet Vermouth","quantity":{"quantity":"3/4","unit":"oz"}},{"name":"Carbonated water"},{"name":"Lemon peel"}],"slug":"english-highball"} 42 | {"_id":{"$oid":"5f7daa328ec9dfb536781b21"},"name":"Black and Brown","instructions":["CAREFULLY to avoid explosive head formation: Pour Beer glass half full of favorite rootbeer and top off with Guinness."],"ingredients":[{"name":"Guinness stout","quantity":{"quantity":"1/2","unit":null}},{"name":"Root beer","quantity":{"quantity":"1/2","unit":null}}],"slug":"black-and-brown"} 43 | {"_id":{"$oid":"5f7daa338ec9dfb536781b22"},"name":"After Dinner Cocktail","instructions":["Shake all ingredients (except lime wedge) with ice and strain into a cocktail glass","Add the wedge of lime and serve."],"ingredients":[{"name":"Apricot brandy","quantity":{"quantity":"1","unit":"oz"}},{"name":"Triple sec","quantity":{"quantity":"1","unit":"oz"}},{"name":"Lime","quantity":{"quantity":"1","unit":null}},{"name":"Lime","quantity":{"quantity":"1","unit":null}}],"slug":"after-dinner-cocktail"} 44 | {"_id":{"$oid":"5f7daa358ec9dfb536781b23"},"name":"Sidecar Cocktail","instructions":["Shake all ingredients with ice, strain into a cocktail glass, and serve."],"ingredients":[{"name":"Brandy","quantity":{"quantity":"1","unit":"oz"}},{"name":"Triple sec","quantity":{"quantity":"1/2","unit":"oz"}},{"name":"Lemon","quantity":{"quantity":"1/4","unit":null}}],"slug":"sidecar-cocktail"} 45 | {"_id":{"$oid":"5f7daa378ec9dfb536781b24"},"name":"Addison","instructions":["Shake together all the ingredients and strain into a cold glass."],"ingredients":[{"name":"Gin","quantity":{"quantity":"1 1/2","unit":"shot"}},{"name":"Vermouth","quantity":{"quantity":"1 1/2","unit":"shot"}}],"slug":"addison"} 46 | {"_id":{"$oid":"5f7f81ac0014b0ca00679317"},"name":"Dodgy Cocktail","ingredients":[{"name":"Water","quantity":{"unit":"ml","amount":30}}],"instructions":["Pour yourself some water from the tap."],"slug":"dodgy-cocktail"} 47 | {"_id":{"$oid":"608b92ba0059661100daf517"},"slug":"whiskey-new-fashioned","name":"Whiskey New-Fashioned","ingredients":[{"name":"New Whiskey","quantity":null},{"name":"Sugar Syrup","quantity":null},{"name":"Angostura Bitters","quantity":null}],"instructions":["Stir the ingredients over ice.","Express the orange peel over the drink."],"date_added":"2021-04-30T05:16:42.827178400Z","date_updated":"2021-04-30T05:16:46.509448100Z"} 48 | -------------------------------------------------------------------------------- /flask-cocktail-api/.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /flask-cocktail-api/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/python,osx,windows 3 | # Edit at https://www.gitignore.io/?templates=python,osx,windows 4 | 5 | ### OSX ### 6 | # General 7 | .DS_Store 8 | .AppleDouble 9 | .LSOverride 10 | 11 | # Icon must end with two \r 12 | Icon 13 | 14 | # Thumbnails 15 | ._* 16 | 17 | # Files that might appear in the root of a volume 18 | .DocumentRevisions-V100 19 | .fseventsd 20 | .Spotlight-V100 21 | .TemporaryItems 22 | .Trashes 23 | .VolumeIcon.icns 24 | .com.apple.timemachine.donotpresent 25 | 26 | # Directories potentially created on remote AFP share 27 | .AppleDB 28 | .AppleDesktop 29 | Network Trash Folder 30 | Temporary Items 31 | .apdisk 32 | 33 | ### Python ### 34 | # Byte-compiled / optimized / DLL files 35 | __pycache__/ 36 | *.py[cod] 37 | *$py.class 38 | 39 | # C extensions 40 | *.so 41 | 42 | # Distribution / packaging 43 | .Python 44 | build/ 45 | develop-eggs/ 46 | dist/ 47 | downloads/ 48 | eggs/ 49 | .eggs/ 50 | lib/ 51 | lib64/ 52 | parts/ 53 | sdist/ 54 | var/ 55 | wheels/ 56 | pip-wheel-metadata/ 57 | share/python-wheels/ 58 | *.egg-info/ 59 | .installed.cfg 60 | *.egg 61 | MANIFEST 62 | 63 | # PyInstaller 64 | # Usually these files are written by a python script from a template 65 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 66 | *.manifest 67 | *.spec 68 | 69 | # Installer logs 70 | pip-log.txt 71 | pip-delete-this-directory.txt 72 | 73 | # Unit test / coverage reports 74 | htmlcov/ 75 | .tox/ 76 | .nox/ 77 | .coverage 78 | .coverage.* 79 | .cache 80 | nosetests.xml 81 | coverage.xml 82 | *.cover 83 | .hypothesis/ 84 | .pytest_cache/ 85 | 86 | # Translations 87 | *.mo 88 | *.pot 89 | 90 | # Scrapy stuff: 91 | .scrapy 92 | 93 | # Sphinx documentation 94 | docs/_build/ 95 | 96 | # PyBuilder 97 | target/ 98 | 99 | # pyenv 100 | .python-version 101 | 102 | # pipenv 103 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 104 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 105 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 106 | # install all needed dependencies. 107 | #Pipfile.lock 108 | 109 | # celery beat schedule file 110 | celerybeat-schedule 111 | 112 | # SageMath parsed files 113 | *.sage.py 114 | 115 | # Spyder project settings 116 | .spyderproject 117 | .spyproject 118 | 119 | # Rope project settings 120 | .ropeproject 121 | 122 | # Mr Developer 123 | .mr.developer.cfg 124 | .project 125 | .pydevproject 126 | 127 | # mkdocs documentation 128 | /site 129 | 130 | # mypy 131 | .mypy_cache/ 132 | .dmypy.json 133 | dmypy.json 134 | 135 | # Pyre type checker 136 | .pyre/ 137 | 138 | ### Windows ### 139 | # Windows thumbnail cache files 140 | Thumbs.db 141 | Thumbs.db:encryptable 142 | ehthumbs.db 143 | ehthumbs_vista.db 144 | 145 | # Dump file 146 | *.stackdump 147 | 148 | # Folder config file 149 | [Dd]esktop.ini 150 | 151 | # Recycle Bin used on file shares 152 | $RECYCLE.BIN/ 153 | 154 | # Windows Installer files 155 | *.cab 156 | *.msi 157 | *.msix 158 | *.msm 159 | *.msp 160 | 161 | # Windows shortcuts 162 | *.lnk 163 | 164 | # End of https://www.gitignore.io/api/python,osx,windows 165 | -------------------------------------------------------------------------------- /flask-cocktail-api/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | @echo "dev - Install development dependencies" 3 | @echo "test - Run tests" 4 | @echo "clean - Delete generated files" 5 | @echo "dist - Build distribution artifacts" 6 | @echo "release - Build distribution and release to PyPI." 7 | 8 | test: 9 | python -m pytest 10 | 11 | clean: 12 | rm -rf build dist src/*.egg-info .tox .pytest_cache pip-wheel-metadata .DS_Store 13 | find src -name '__pycache__' | xargs rm -rf 14 | find tests -name '__pycache__' | xargs rm -rf 15 | 16 | dev: 17 | python -m pip install -e .[dev] 18 | 19 | install: 20 | python -m pip install -e . 21 | 22 | run: 23 | FLASK_DEBUG=true FLASK_APP=cocktailapi flask run 24 | 25 | .PHONY: all install clean dev -------------------------------------------------------------------------------- /flask-cocktail-api/README.md: -------------------------------------------------------------------------------- 1 | # Flask Cocktail API 2 | 3 | A simple API for getting cocktail recipes. 4 | 5 | This code was written as part of a [blog post](https://developer.mongodb.com/), 6 | it's not really designed to stand alone. 7 | 8 | ## Run the code 9 | 10 | First create and activate your virtualenv - with the `venv` package on OSX or Linux, this will be: 11 | 12 | ```bash 13 | python3 -m venv venv 14 | source venv/bin/activate 15 | ``` 16 | 17 | With your virtualenv active, install the project locally: 18 | 19 | ```bash 20 | pip install -e . 21 | ``` 22 | 23 | You'll need to set the environment variable `MONGO_URI` to the URL of your MongoDB replicaset. 24 | I use `direnv` to configure this, and put the following line in my `.envrc` file in my project's directory: 25 | 26 | ```bash 27 | export MONGO_URI="mongodb+srv://USERNAME:PASSW0RD@cluster0-abcde.azure.mongodb.net/cocktails?retryWrites=true&w=majority" 28 | ``` 29 | 30 | You can then import the sample data with mongoimport: 31 | 32 | ```bash 33 | mongoimport --uri "$MONGO_URI" --file ../data/recipes.json 34 | ``` 35 | 36 | And now you should be able to run the service like this: 37 | 38 | ```bash 39 | FLASK_APP=cocktailapi flask run 40 | ``` 41 | 42 | ## Developing 43 | 44 | Run the following to install the project (and dev dependencies) into your active virtualenv: 45 | 46 | ```bash 47 | pip install -e .[dev] 48 | ``` 49 | 50 | You can run the tests with: 51 | 52 | ```bash 53 | pytest 54 | ``` 55 | -------------------------------------------------------------------------------- /flask-cocktail-api/add_slug.py: -------------------------------------------------------------------------------- 1 | from enum import unique 2 | import os 3 | import re 4 | 5 | from pymongo import MongoClient 6 | from bson import ObjectId 7 | 8 | client = MongoClient(os.environ["MONGO_URI"]) 9 | 10 | db = client.get_default_database() 11 | recipes = db.get_collection("recipes") 12 | recipes.create_index("slug", unique=True) 13 | 14 | 15 | def slugify(name): 16 | return re.sub(r"[^a-z0-9]+", "-", name.lower()) 17 | 18 | 19 | for recipe in recipes.find(): 20 | print(recipe["name"], slugify(recipe["name"])) 21 | recipes.update_one( 22 | {"_id": recipe["_id"]}, 23 | {"$set": {"slug": slugify(recipe["name"])}}, 24 | ) 25 | -------------------------------------------------------------------------------- /flask-cocktail-api/prospector.yaml: -------------------------------------------------------------------------------- 1 | %YAML 1.2 2 | --- 3 | ignore-paths: 4 | - venv 5 | - dist 6 | - build -------------------------------------------------------------------------------- /flask-cocktail-api/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.coverage.run] 2 | parallel = true 3 | branch = true 4 | source = ["cocktailapi"] 5 | 6 | [tool.coverage.paths] 7 | source = ["src", ".tox/*/site-packages"] 8 | 9 | [tool.coverage.report] 10 | show_missing = true 11 | -------------------------------------------------------------------------------- /flask-cocktail-api/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | EXTRAS_REQUIRE = { 4 | "tests": [ 5 | "pytest", 6 | "coverage[toml]>=5.0.2", 7 | ], 8 | } 9 | EXTRAS_REQUIRE["dev"] = EXTRAS_REQUIRE["tests"] + [ 10 | "black", 11 | "twine", 12 | "wheel", 13 | "prospector[with_everything]", 14 | ] 15 | 16 | setup( 17 | name="flask-cocktail-api", 18 | description="A small API for getting cocktail recipes.", 19 | version="0.0.0", 20 | author="Mark Smith", 21 | author_email="mark.smith@mongodb.com", 22 | packages=find_packages(where="src"), 23 | package_dir={"": "src"}, 24 | install_requires=[ 25 | "fastapi == 0.63.0", 26 | "Flask == 1.1.4", 27 | "Flask-PyMongo==2.3.0", 28 | "pymongo[srv] == 3.11.3", 29 | "pydantic == 1.8.1", 30 | "MarkupSafe == 2.0.1" 31 | ], 32 | extras_require=EXTRAS_REQUIRE, 33 | ) -------------------------------------------------------------------------------- /flask-cocktail-api/src/cocktailapi/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | cocktailapi - A small API for managing cocktail recipes. 3 | """ 4 | 5 | from datetime import datetime 6 | import os 7 | 8 | from pymongo.collection import Collection, ReturnDocument 9 | 10 | import flask 11 | from flask import Flask, request, url_for, jsonify 12 | from flask_pymongo import PyMongo 13 | from pymongo.errors import DuplicateKeyError 14 | 15 | from .model import Cocktail 16 | from .objectid import PydanticObjectId 17 | 18 | # Configure Flask & Flask-PyMongo: 19 | app = Flask(__name__) 20 | app.config["MONGO_URI"] = os.getenv("MONGO_URI") 21 | pymongo = PyMongo(app) 22 | 23 | # Get a reference to the recipes collection. 24 | # Uses a type-hint, so that your IDE knows what's happening! 25 | recipes: Collection = pymongo.db.recipes 26 | 27 | 28 | @app.errorhandler(404) 29 | def resource_not_found(e): 30 | """ 31 | An error-handler to ensure that 404 errors are returned as JSON. 32 | """ 33 | return jsonify(error=str(e)), 404 34 | 35 | 36 | @app.errorhandler(DuplicateKeyError) 37 | def resource_not_found(e): 38 | """ 39 | An error-handler to ensure that MongoDB duplicate key errors are returned as JSON. 40 | """ 41 | return jsonify(error=f"Duplicate key error."), 400 42 | 43 | 44 | @app.route("/cocktails/") 45 | def list_cocktails(): 46 | """ 47 | GET a list of cocktail recipes. 48 | 49 | The results are paginated using the `page` parameter. 50 | """ 51 | 52 | page = int(request.args.get("page", 1)) 53 | per_page = 10 # A const value. 54 | 55 | # For pagination, it's necessary to sort by name, 56 | # then skip the number of docs that earlier pages would have displayed, 57 | # and then to limit to the fixed page size, ``per_page``. 58 | cursor = recipes.find().sort("name").skip(per_page * (page - 1)).limit(per_page) 59 | 60 | cocktail_count = recipes.count_documents({}) 61 | 62 | links = { 63 | "self": {"href": url_for(".list_cocktails", page=page, _external=True)}, 64 | "last": { 65 | "href": url_for( 66 | ".list_cocktails", page=(cocktail_count // per_page) + 1, _external=True 67 | ) 68 | }, 69 | } 70 | # Add a 'prev' link if it's not on the first page: 71 | if page > 1: 72 | links["prev"] = { 73 | "href": url_for(".list_cocktails", page=page - 1, _external=True) 74 | } 75 | # Add a 'next' link if it's not on the last page: 76 | if page - 1 < cocktail_count // per_page: 77 | links["next"] = { 78 | "href": url_for(".list_cocktails", page=page + 1, _external=True) 79 | } 80 | 81 | return { 82 | "recipes": [Cocktail(**doc).to_json() for doc in cursor], 83 | "_links": links, 84 | } 85 | 86 | 87 | @app.route("/cocktails/", methods=["POST"]) 88 | def new_cocktail(): 89 | raw_cocktail = request.get_json() 90 | raw_cocktail["date_added"] = datetime.utcnow() 91 | 92 | cocktail = Cocktail(**raw_cocktail) 93 | insert_result = recipes.insert_one(cocktail.to_bson()) 94 | cocktail.id = PydanticObjectId(str(insert_result.inserted_id)) 95 | print(cocktail) 96 | 97 | return cocktail.to_json() 98 | 99 | 100 | @app.route("/cocktails/", methods=["GET"]) 101 | def get_cocktail(slug): 102 | recipe = recipes.find_one_or_404({"slug": slug}) 103 | return Cocktail(**recipe).to_json() 104 | 105 | 106 | @app.route("/cocktails/", methods=["PUT"]) 107 | def update_cocktail(slug): 108 | cocktail = Cocktail(**request.get_json()) 109 | cocktail.date_updated = datetime.utcnow() 110 | updated_doc = recipes.find_one_and_update( 111 | {"slug": slug}, 112 | {"$set": cocktail.to_bson()}, 113 | return_document=ReturnDocument.AFTER, 114 | ) 115 | if updated_doc: 116 | return Cocktail(**updated_doc).to_json() 117 | else: 118 | flask.abort(404, "Cocktail not found") 119 | 120 | 121 | @app.route("/cocktails/", methods=["DELETE"]) 122 | def delete_cocktail(slug): 123 | deleted_cocktail = recipes.find_one_and_delete( 124 | {"slug": slug}, 125 | ) 126 | if deleted_cocktail: 127 | return Cocktail(**deleted_cocktail).to_json() 128 | else: 129 | flask.abort(404, "Cocktail not found") 130 | -------------------------------------------------------------------------------- /flask-cocktail-api/src/cocktailapi/model.py: -------------------------------------------------------------------------------- 1 | # FastAPI's jsonable_encoder handles converting various non-JSON types, 2 | # such as datetime between JSON types and native Python types. 3 | from fastapi.encoders import jsonable_encoder 4 | 5 | # Pydantic, and Python's built-in typing are used to define a schema 6 | # that defines the structure and types of the different objects stored 7 | # in the recipes collection, and managed by this API. 8 | from pydantic import BaseModel, Field 9 | from typing import List, Optional, Union 10 | from datetime import datetime 11 | 12 | from .objectid import PydanticObjectId 13 | 14 | 15 | class Quantity(BaseModel): 16 | quantity: Optional[Union[str, int, float]] 17 | unit: Optional[str] 18 | 19 | 20 | class Ingredient(BaseModel): 21 | name: str 22 | quantity: Optional[Quantity] 23 | 24 | 25 | class Cocktail(BaseModel): 26 | id: Optional[PydanticObjectId] = Field(None, alias="_id") 27 | slug: str 28 | name: str 29 | ingredients: List[Ingredient] 30 | instructions: List[str] 31 | date_added: Optional[datetime] 32 | date_updated: Optional[datetime] 33 | 34 | def to_json(self): 35 | return jsonable_encoder(self, exclude_none=True) 36 | 37 | def to_bson(self): 38 | data = self.dict(by_alias=True, exclude_none=True) 39 | if data.get("_id") is None: 40 | data.pop("_id", None) 41 | return data -------------------------------------------------------------------------------- /flask-cocktail-api/src/cocktailapi/objectid.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Roman Korolev 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # This code was extracted and modified from the Beanie ODM at 16 | # 17 | # https://github.com/roman-right/beanie 18 | 19 | 20 | from bson import ObjectId 21 | from pydantic.json import ENCODERS_BY_TYPE 22 | 23 | 24 | class PydanticObjectId(ObjectId): 25 | """ 26 | Object Id field. Compatible with Pydantic. 27 | """ 28 | 29 | @classmethod 30 | def __get_validators__(cls): 31 | yield cls.validate 32 | 33 | @classmethod 34 | def validate(cls, v): 35 | return PydanticObjectId(v) 36 | 37 | @classmethod 38 | def __modify_schema__(cls, field_schema: dict): 39 | field_schema.update( 40 | type="string", 41 | examples=["5eb7cf5a86d9755df3a6c593", "5eb7cfb05e32e07750a1756a"], 42 | ) 43 | 44 | 45 | ENCODERS_BY_TYPE[PydanticObjectId] = str -------------------------------------------------------------------------------- /flask-cocktail-api/tests/test_flaskcocktailapi.py: -------------------------------------------------------------------------------- 1 | import cocktailapi 2 | 3 | 4 | def test_main(): 5 | assert cocktailapi.app is None 6 | -------------------------------------------------------------------------------- /flask-cocktail-api/tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py36,py37,py38,report 3 | 4 | [tool:pytest] 5 | testpaths = tests 6 | addopts = 7 | --cov-report=term-missing 8 | 9 | [testenv] 10 | extras = {env:TOX_AP_TEST_EXTRAS:tests} 11 | commands = coverage run -m pytest {posargs} 12 | depends = 13 | {py36,py37,py38}: clean 14 | report: py36,py37,py38 15 | 16 | [testenv:report] 17 | deps = coverage[toml]>=5.0.2 18 | skip_install = true 19 | commands = 20 | coverage combine 21 | coverage report 22 | coverage html -------------------------------------------------------------------------------- /test_scripts/README.md: -------------------------------------------------------------------------------- 1 | # Cocktail API Test Scripts 2 | 3 | This folder contains some short shell scripts which use curl to test the various endpoints of the Cocktail API, 4 | either the service written in Python or the one in Rust. 5 | 6 | The scripts are designed to be run in sequence: 7 | 8 | new_cocktail.sh 9 | 10 | | Step | Script | Description | 11 | |------|--------------------|-------------| 12 | | 1 | new_cocktail.sh | Create a new cocktail with the slug `whiskey-old-fashioned` | 13 | | 2 | get_cocktail.sh | Retrieve the `whiskey-old-fashioned` from the service. | 14 | | 3 | update_cocktail.sh | Modify the slug and name of the `whiskey-old-fashioned`, making it a `whiskey-new-fashioned` | 15 | | 4 | delete_cocktail.sh | Delete the `whiskey-new-fashioned` | 16 | | 5 | list_cocktail.sh | List page 4 of the cocktail recipes. | 17 | 18 | Be aware that if you attempt to run most of these scripts twice you'll either get a duplicate key error, because you're attempting to re-use the slug, or a 404 because you're attempting to access a document that's already been deleted. -------------------------------------------------------------------------------- /test_scripts/cocktail.json: -------------------------------------------------------------------------------- 1 | { 2 | "slug": "whiskey-old-fashioned", 3 | "name": "Whiskey Old-Fashioned", 4 | "ingredients": [ 5 | { 6 | "name": "Whiskey" 7 | }, 8 | { 9 | "name": "Sugar Syrup" 10 | }, 11 | { 12 | "name": "Angostura Bitters" 13 | } 14 | ], 15 | "instructions": [ 16 | "Stir the ingredients over ice.", 17 | "Express the orange peel over the drink." 18 | ] 19 | } -------------------------------------------------------------------------------- /test_scripts/delete_cocktail.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl -i --request 'DELETE' 'http://localhost:5000/cocktails/whiskey-new-fashioned' -------------------------------------------------------------------------------- /test_scripts/get_cocktail.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl -i 'http://localhost:5000/cocktails/whiskey-old-fashioned' -------------------------------------------------------------------------------- /test_scripts/list_cocktails.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl -i 'http://localhost:5000/cocktails/?page=4' -------------------------------------------------------------------------------- /test_scripts/new_cocktail.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl -i \ 3 | -H "Content-Type: application/json" \ 4 | --request 'POST' \ 5 | --data '{ 6 | "slug": "whiskey-old-fashioned", 7 | "name": "Whiskey Old-Fashioned", 8 | "ingredients": [ 9 | { 10 | "name": "Whiskey" 11 | }, 12 | { 13 | "name": "Sugar Syrup" 14 | }, 15 | { 16 | "name": "Angostura Bitters" 17 | } 18 | ], 19 | "instructions": [ 20 | "Stir the ingredients over ice.", 21 | "Express the orange peel over the drink." 22 | ] 23 | }' \ 24 | 'http://localhost:5000/cocktails/' 25 | -------------------------------------------------------------------------------- /test_scripts/update_cocktail.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl -i \ 3 | -H "Content-Type: application/json" \ 4 | --request 'PUT' \ 5 | --data '{ 6 | "slug": "whiskey-new-fashioned", 7 | "name": "Whiskey New-Fashioned", 8 | "ingredients": [ 9 | { 10 | "name": "New Whiskey" 11 | }, 12 | { 13 | "name": "Sugar Syrup" 14 | }, 15 | { 16 | "name": "Angostura Bitters" 17 | } 18 | ], 19 | "instructions": [ 20 | "Stir the ingredients over ice.", 21 | "Express the orange peel over the drink." 22 | ] 23 | }' \ 24 | 'http://localhost:5000/cocktails/whiskey-old-fashioned' --------------------------------------------------------------------------------