├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── enable-ssl.md ├── misc └── screenshot.png ├── public └── index.html └── src ├── health_checker.rs ├── main.rs ├── routes.rs └── url_value.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /spo2.db 3 | **/*.rs.bk 4 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "arraydeque" 5 | version = "0.4.5" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | 8 | [[package]] 9 | name = "arrayvec" 10 | version = "0.4.12" 11 | source = "registry+https://github.com/rust-lang/crates.io-index" 12 | dependencies = [ 13 | "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", 14 | ] 15 | 16 | [[package]] 17 | name = "ascii" 18 | version = "0.8.7" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | 21 | [[package]] 22 | name = "autocfg" 23 | version = "0.1.7" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | 26 | [[package]] 27 | name = "backtrace" 28 | version = "0.3.40" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | dependencies = [ 31 | "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", 32 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 33 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 34 | "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", 35 | ] 36 | 37 | [[package]] 38 | name = "backtrace-sys" 39 | version = "0.1.32" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | dependencies = [ 42 | "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", 43 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 44 | ] 45 | 46 | [[package]] 47 | name = "bincode" 48 | version = "1.2.0" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | dependencies = [ 51 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 52 | "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 53 | "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", 54 | ] 55 | 56 | [[package]] 57 | name = "bitflags" 58 | version = "1.2.1" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | 61 | [[package]] 62 | name = "block-buffer" 63 | version = "0.7.3" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | dependencies = [ 66 | "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 67 | "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 68 | "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 69 | "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", 70 | ] 71 | 72 | [[package]] 73 | name = "block-padding" 74 | version = "0.1.5" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | dependencies = [ 77 | "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 78 | ] 79 | 80 | [[package]] 81 | name = "byte-tools" 82 | version = "0.3.1" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | 85 | [[package]] 86 | name = "bytecount" 87 | version = "0.4.0" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | 90 | [[package]] 91 | name = "byteorder" 92 | version = "1.3.2" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | 95 | [[package]] 96 | name = "bytes" 97 | version = "0.4.12" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | dependencies = [ 100 | "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 101 | "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 102 | ] 103 | 104 | [[package]] 105 | name = "c2-chacha" 106 | version = "0.2.3" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | dependencies = [ 109 | "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 110 | ] 111 | 112 | [[package]] 113 | name = "cargo_metadata" 114 | version = "0.6.4" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | dependencies = [ 117 | "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", 118 | "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 119 | "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", 120 | "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", 121 | "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", 122 | ] 123 | 124 | [[package]] 125 | name = "cc" 126 | version = "1.0.47" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | 129 | [[package]] 130 | name = "cfg-if" 131 | version = "0.1.10" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | 134 | [[package]] 135 | name = "chrono" 136 | version = "0.4.9" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | dependencies = [ 139 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 140 | "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", 141 | "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 142 | "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", 143 | ] 144 | 145 | [[package]] 146 | name = "chunked_transfer" 147 | version = "0.3.1" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | 150 | [[package]] 151 | name = "cloudabi" 152 | version = "0.0.3" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | dependencies = [ 155 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 156 | ] 157 | 158 | [[package]] 159 | name = "crc32fast" 160 | version = "1.2.0" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | dependencies = [ 163 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 164 | ] 165 | 166 | [[package]] 167 | name = "crossbeam-channel" 168 | version = "0.3.9" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | dependencies = [ 171 | "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 172 | ] 173 | 174 | [[package]] 175 | name = "crossbeam-epoch" 176 | version = "0.7.2" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | dependencies = [ 179 | "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", 180 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 181 | "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 182 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 183 | "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", 184 | "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 185 | ] 186 | 187 | [[package]] 188 | name = "crossbeam-utils" 189 | version = "0.6.6" 190 | source = "registry+https://github.com/rust-lang/crates.io-index" 191 | dependencies = [ 192 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 193 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 194 | ] 195 | 196 | [[package]] 197 | name = "curl" 198 | version = "0.4.25" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | dependencies = [ 201 | "curl-sys 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", 202 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 203 | "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 204 | "openssl-sys 0.9.52 (registry+https://github.com/rust-lang/crates.io-index)", 205 | "schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", 206 | "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", 207 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 208 | ] 209 | 210 | [[package]] 211 | name = "curl-sys" 212 | version = "0.4.24" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | dependencies = [ 215 | "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", 216 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 217 | "libnghttp2-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 218 | "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", 219 | "openssl-sys 0.9.52 (registry+https://github.com/rust-lang/crates.io-index)", 220 | "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", 221 | "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", 222 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 223 | ] 224 | 225 | [[package]] 226 | name = "digest" 227 | version = "0.8.1" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | dependencies = [ 230 | "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", 231 | ] 232 | 233 | [[package]] 234 | name = "error-chain" 235 | version = "0.12.1" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | dependencies = [ 238 | "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", 239 | "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 240 | ] 241 | 242 | [[package]] 243 | name = "fake-simd" 244 | version = "0.1.2" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | 247 | [[package]] 248 | name = "fnv" 249 | version = "1.0.6" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | 252 | [[package]] 253 | name = "fs2" 254 | version = "0.4.3" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | dependencies = [ 257 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 258 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 259 | ] 260 | 261 | [[package]] 262 | name = "fuchsia-cprng" 263 | version = "0.1.1" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | 266 | [[package]] 267 | name = "fuchsia-zircon" 268 | version = "0.3.3" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | dependencies = [ 271 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 272 | "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 273 | ] 274 | 275 | [[package]] 276 | name = "fuchsia-zircon-sys" 277 | version = "0.3.3" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | 280 | [[package]] 281 | name = "futures-channel-preview" 282 | version = "0.3.0-alpha.19" 283 | source = "registry+https://github.com/rust-lang/crates.io-index" 284 | dependencies = [ 285 | "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 286 | "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 287 | ] 288 | 289 | [[package]] 290 | name = "futures-core-preview" 291 | version = "0.3.0-alpha.19" 292 | source = "registry+https://github.com/rust-lang/crates.io-index" 293 | 294 | [[package]] 295 | name = "futures-executor-preview" 296 | version = "0.3.0-alpha.19" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | dependencies = [ 299 | "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 300 | "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 301 | "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 302 | ] 303 | 304 | [[package]] 305 | name = "futures-io-preview" 306 | version = "0.3.0-alpha.19" 307 | source = "registry+https://github.com/rust-lang/crates.io-index" 308 | 309 | [[package]] 310 | name = "futures-preview" 311 | version = "0.3.0-alpha.19" 312 | source = "registry+https://github.com/rust-lang/crates.io-index" 313 | dependencies = [ 314 | "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 315 | "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 316 | "futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 317 | "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 318 | "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 319 | "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 320 | ] 321 | 322 | [[package]] 323 | name = "futures-sink-preview" 324 | version = "0.3.0-alpha.19" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | 327 | [[package]] 328 | name = "futures-stream-batch" 329 | version = "0.2.0" 330 | source = "git+https://github.com/Kerollmops/futures-stream-batch.git#62a6b8beab86755b1640f5fb812f769b8122d15d" 331 | dependencies = [ 332 | "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 333 | "futures-timer 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 334 | "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", 335 | "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", 336 | ] 337 | 338 | [[package]] 339 | name = "futures-timer" 340 | version = "0.4.0" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | dependencies = [ 343 | "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 344 | "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 345 | "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", 346 | ] 347 | 348 | [[package]] 349 | name = "futures-timer" 350 | version = "1.0.3" 351 | source = "registry+https://github.com/rust-lang/crates.io-index" 352 | dependencies = [ 353 | "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 354 | "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", 355 | ] 356 | 357 | [[package]] 358 | name = "futures-util-preview" 359 | version = "0.3.0-alpha.19" 360 | source = "registry+https://github.com/rust-lang/crates.io-index" 361 | dependencies = [ 362 | "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 363 | "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 364 | "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 365 | "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 366 | "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 367 | "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", 368 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 369 | ] 370 | 371 | [[package]] 372 | name = "fxhash" 373 | version = "0.2.1" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | dependencies = [ 376 | "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 377 | ] 378 | 379 | [[package]] 380 | name = "generic-array" 381 | version = "0.12.3" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | dependencies = [ 384 | "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", 385 | ] 386 | 387 | [[package]] 388 | name = "getrandom" 389 | version = "0.1.13" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | dependencies = [ 392 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 393 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 394 | "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 395 | ] 396 | 397 | [[package]] 398 | name = "glob" 399 | version = "0.2.11" 400 | source = "registry+https://github.com/rust-lang/crates.io-index" 401 | 402 | [[package]] 403 | name = "hermit-abi" 404 | version = "0.1.3" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | dependencies = [ 407 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 408 | ] 409 | 410 | [[package]] 411 | name = "http" 412 | version = "0.1.19" 413 | source = "registry+https://github.com/rust-lang/crates.io-index" 414 | dependencies = [ 415 | "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", 416 | "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 417 | "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 418 | ] 419 | 420 | [[package]] 421 | name = "httparse" 422 | version = "1.3.4" 423 | source = "registry+https://github.com/rust-lang/crates.io-index" 424 | 425 | [[package]] 426 | name = "idna" 427 | version = "0.1.5" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | dependencies = [ 430 | "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 431 | "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 432 | "unicode-normalization 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 433 | ] 434 | 435 | [[package]] 436 | name = "idna" 437 | version = "0.2.0" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | dependencies = [ 440 | "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 441 | "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 442 | "unicode-normalization 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 443 | ] 444 | 445 | [[package]] 446 | name = "iovec" 447 | version = "0.1.4" 448 | source = "registry+https://github.com/rust-lang/crates.io-index" 449 | dependencies = [ 450 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 451 | ] 452 | 453 | [[package]] 454 | name = "isahc" 455 | version = "0.7.6" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | dependencies = [ 458 | "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", 459 | "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", 460 | "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 461 | "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 462 | "curl 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", 463 | "curl-sys 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", 464 | "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 465 | "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 466 | "http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", 467 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 468 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 469 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 470 | "sluice 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 471 | ] 472 | 473 | [[package]] 474 | name = "itoa" 475 | version = "0.4.4" 476 | source = "registry+https://github.com/rust-lang/crates.io-index" 477 | 478 | [[package]] 479 | name = "kernel32-sys" 480 | version = "0.2.2" 481 | source = "registry+https://github.com/rust-lang/crates.io-index" 482 | dependencies = [ 483 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 484 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 485 | ] 486 | 487 | [[package]] 488 | name = "lazy_static" 489 | version = "1.4.0" 490 | source = "registry+https://github.com/rust-lang/crates.io-index" 491 | 492 | [[package]] 493 | name = "lazycell" 494 | version = "1.2.1" 495 | source = "registry+https://github.com/rust-lang/crates.io-index" 496 | 497 | [[package]] 498 | name = "libc" 499 | version = "0.2.65" 500 | source = "registry+https://github.com/rust-lang/crates.io-index" 501 | 502 | [[package]] 503 | name = "libnghttp2-sys" 504 | version = "0.1.2" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | dependencies = [ 507 | "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", 508 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 509 | ] 510 | 511 | [[package]] 512 | name = "libz-sys" 513 | version = "1.0.25" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | dependencies = [ 516 | "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", 517 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 518 | "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", 519 | "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", 520 | ] 521 | 522 | [[package]] 523 | name = "lock_api" 524 | version = "0.3.1" 525 | source = "registry+https://github.com/rust-lang/crates.io-index" 526 | dependencies = [ 527 | "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 528 | ] 529 | 530 | [[package]] 531 | name = "log" 532 | version = "0.4.8" 533 | source = "registry+https://github.com/rust-lang/crates.io-index" 534 | dependencies = [ 535 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 536 | ] 537 | 538 | [[package]] 539 | name = "matches" 540 | version = "0.1.8" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | 543 | [[package]] 544 | name = "maybe-uninit" 545 | version = "2.0.0" 546 | source = "registry+https://github.com/rust-lang/crates.io-index" 547 | 548 | [[package]] 549 | name = "memchr" 550 | version = "2.2.1" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | 553 | [[package]] 554 | name = "memoffset" 555 | version = "0.5.3" 556 | source = "registry+https://github.com/rust-lang/crates.io-index" 557 | dependencies = [ 558 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 559 | ] 560 | 561 | [[package]] 562 | name = "mio" 563 | version = "0.6.19" 564 | source = "registry+https://github.com/rust-lang/crates.io-index" 565 | dependencies = [ 566 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 567 | "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 568 | "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 569 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 570 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 571 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 572 | "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 573 | "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 574 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 575 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 576 | ] 577 | 578 | [[package]] 579 | name = "mio-extras" 580 | version = "2.0.5" 581 | source = "registry+https://github.com/rust-lang/crates.io-index" 582 | dependencies = [ 583 | "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 584 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 585 | "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", 586 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 587 | ] 588 | 589 | [[package]] 590 | name = "miow" 591 | version = "0.2.1" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | dependencies = [ 594 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 595 | "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 596 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 597 | "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 598 | ] 599 | 600 | [[package]] 601 | name = "net2" 602 | version = "0.2.33" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | dependencies = [ 605 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 606 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 607 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 608 | ] 609 | 610 | [[package]] 611 | name = "nodrop" 612 | version = "0.1.14" 613 | source = "registry+https://github.com/rust-lang/crates.io-index" 614 | 615 | [[package]] 616 | name = "num-integer" 617 | version = "0.1.41" 618 | source = "registry+https://github.com/rust-lang/crates.io-index" 619 | dependencies = [ 620 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 621 | "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 622 | ] 623 | 624 | [[package]] 625 | name = "num-traits" 626 | version = "0.2.8" 627 | source = "registry+https://github.com/rust-lang/crates.io-index" 628 | dependencies = [ 629 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 630 | ] 631 | 632 | [[package]] 633 | name = "num_cpus" 634 | version = "1.11.0" 635 | source = "registry+https://github.com/rust-lang/crates.io-index" 636 | dependencies = [ 637 | "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 638 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 639 | ] 640 | 641 | [[package]] 642 | name = "once_cell" 643 | version = "1.2.0" 644 | source = "registry+https://github.com/rust-lang/crates.io-index" 645 | 646 | [[package]] 647 | name = "opaque-debug" 648 | version = "0.2.3" 649 | source = "registry+https://github.com/rust-lang/crates.io-index" 650 | 651 | [[package]] 652 | name = "openssl-probe" 653 | version = "0.1.2" 654 | source = "registry+https://github.com/rust-lang/crates.io-index" 655 | 656 | [[package]] 657 | name = "openssl-sys" 658 | version = "0.9.52" 659 | source = "registry+https://github.com/rust-lang/crates.io-index" 660 | dependencies = [ 661 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 662 | "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", 663 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 664 | "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", 665 | "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", 666 | ] 667 | 668 | [[package]] 669 | name = "pagecache" 670 | version = "0.19.4" 671 | source = "registry+https://github.com/rust-lang/crates.io-index" 672 | dependencies = [ 673 | "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 674 | "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 675 | "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 676 | "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 677 | "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 678 | "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 679 | "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 680 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 681 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 682 | "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 683 | "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", 684 | ] 685 | 686 | [[package]] 687 | name = "parking_lot" 688 | version = "0.9.0" 689 | source = "registry+https://github.com/rust-lang/crates.io-index" 690 | dependencies = [ 691 | "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 692 | "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", 693 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 694 | ] 695 | 696 | [[package]] 697 | name = "parking_lot_core" 698 | version = "0.6.2" 699 | source = "registry+https://github.com/rust-lang/crates.io-index" 700 | dependencies = [ 701 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 702 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 703 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 704 | "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", 705 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 706 | "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", 707 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 708 | ] 709 | 710 | [[package]] 711 | name = "percent-encoding" 712 | version = "1.0.1" 713 | source = "registry+https://github.com/rust-lang/crates.io-index" 714 | 715 | [[package]] 716 | name = "percent-encoding" 717 | version = "2.1.0" 718 | source = "registry+https://github.com/rust-lang/crates.io-index" 719 | 720 | [[package]] 721 | name = "pin-utils" 722 | version = "0.1.0-alpha.4" 723 | source = "registry+https://github.com/rust-lang/crates.io-index" 724 | 725 | [[package]] 726 | name = "pkg-config" 727 | version = "0.3.17" 728 | source = "registry+https://github.com/rust-lang/crates.io-index" 729 | 730 | [[package]] 731 | name = "ppv-lite86" 732 | version = "0.2.6" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | 735 | [[package]] 736 | name = "proc-macro2" 737 | version = "1.0.6" 738 | source = "registry+https://github.com/rust-lang/crates.io-index" 739 | dependencies = [ 740 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 741 | ] 742 | 743 | [[package]] 744 | name = "pulldown-cmark" 745 | version = "0.2.0" 746 | source = "registry+https://github.com/rust-lang/crates.io-index" 747 | dependencies = [ 748 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 749 | ] 750 | 751 | [[package]] 752 | name = "quote" 753 | version = "1.0.2" 754 | source = "registry+https://github.com/rust-lang/crates.io-index" 755 | dependencies = [ 756 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 757 | ] 758 | 759 | [[package]] 760 | name = "rand" 761 | version = "0.4.6" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | dependencies = [ 764 | "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 765 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 766 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 767 | "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 768 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 769 | ] 770 | 771 | [[package]] 772 | name = "rand" 773 | version = "0.7.2" 774 | source = "registry+https://github.com/rust-lang/crates.io-index" 775 | dependencies = [ 776 | "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 777 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 778 | "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 779 | "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 780 | "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 781 | ] 782 | 783 | [[package]] 784 | name = "rand_chacha" 785 | version = "0.2.1" 786 | source = "registry+https://github.com/rust-lang/crates.io-index" 787 | dependencies = [ 788 | "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 789 | "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 790 | ] 791 | 792 | [[package]] 793 | name = "rand_core" 794 | version = "0.3.1" 795 | source = "registry+https://github.com/rust-lang/crates.io-index" 796 | dependencies = [ 797 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 798 | ] 799 | 800 | [[package]] 801 | name = "rand_core" 802 | version = "0.4.2" 803 | source = "registry+https://github.com/rust-lang/crates.io-index" 804 | 805 | [[package]] 806 | name = "rand_core" 807 | version = "0.5.1" 808 | source = "registry+https://github.com/rust-lang/crates.io-index" 809 | dependencies = [ 810 | "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 811 | ] 812 | 813 | [[package]] 814 | name = "rand_hc" 815 | version = "0.2.0" 816 | source = "registry+https://github.com/rust-lang/crates.io-index" 817 | dependencies = [ 818 | "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 819 | ] 820 | 821 | [[package]] 822 | name = "rdrand" 823 | version = "0.4.0" 824 | source = "registry+https://github.com/rust-lang/crates.io-index" 825 | dependencies = [ 826 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 827 | ] 828 | 829 | [[package]] 830 | name = "redox_syscall" 831 | version = "0.1.56" 832 | source = "registry+https://github.com/rust-lang/crates.io-index" 833 | 834 | [[package]] 835 | name = "remove_dir_all" 836 | version = "0.5.2" 837 | source = "registry+https://github.com/rust-lang/crates.io-index" 838 | dependencies = [ 839 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 840 | ] 841 | 842 | [[package]] 843 | name = "rustc-demangle" 844 | version = "0.1.16" 845 | source = "registry+https://github.com/rust-lang/crates.io-index" 846 | 847 | [[package]] 848 | name = "rustc_version" 849 | version = "0.2.3" 850 | source = "registry+https://github.com/rust-lang/crates.io-index" 851 | dependencies = [ 852 | "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 853 | ] 854 | 855 | [[package]] 856 | name = "ryu" 857 | version = "1.0.2" 858 | source = "registry+https://github.com/rust-lang/crates.io-index" 859 | 860 | [[package]] 861 | name = "same-file" 862 | version = "1.0.5" 863 | source = "registry+https://github.com/rust-lang/crates.io-index" 864 | dependencies = [ 865 | "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 866 | ] 867 | 868 | [[package]] 869 | name = "schannel" 870 | version = "0.1.16" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | dependencies = [ 873 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 874 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 875 | ] 876 | 877 | [[package]] 878 | name = "scopeguard" 879 | version = "1.0.0" 880 | source = "registry+https://github.com/rust-lang/crates.io-index" 881 | 882 | [[package]] 883 | name = "semver" 884 | version = "0.9.0" 885 | source = "registry+https://github.com/rust-lang/crates.io-index" 886 | dependencies = [ 887 | "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 888 | "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", 889 | ] 890 | 891 | [[package]] 892 | name = "semver-parser" 893 | version = "0.7.0" 894 | source = "registry+https://github.com/rust-lang/crates.io-index" 895 | 896 | [[package]] 897 | name = "serde" 898 | version = "1.0.102" 899 | source = "registry+https://github.com/rust-lang/crates.io-index" 900 | dependencies = [ 901 | "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", 902 | ] 903 | 904 | [[package]] 905 | name = "serde_bytes" 906 | version = "0.11.2" 907 | source = "registry+https://github.com/rust-lang/crates.io-index" 908 | dependencies = [ 909 | "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", 910 | ] 911 | 912 | [[package]] 913 | name = "serde_derive" 914 | version = "1.0.102" 915 | source = "registry+https://github.com/rust-lang/crates.io-index" 916 | dependencies = [ 917 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 918 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 919 | "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", 920 | ] 921 | 922 | [[package]] 923 | name = "serde_json" 924 | version = "1.0.41" 925 | source = "registry+https://github.com/rust-lang/crates.io-index" 926 | dependencies = [ 927 | "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 928 | "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 929 | "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", 930 | ] 931 | 932 | [[package]] 933 | name = "sha-1" 934 | version = "0.8.1" 935 | source = "registry+https://github.com/rust-lang/crates.io-index" 936 | dependencies = [ 937 | "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", 938 | "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", 939 | "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 940 | "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 941 | ] 942 | 943 | [[package]] 944 | name = "skeptic" 945 | version = "0.13.4" 946 | source = "registry+https://github.com/rust-lang/crates.io-index" 947 | dependencies = [ 948 | "bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 949 | "cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", 950 | "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", 951 | "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 952 | "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 953 | "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", 954 | "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 955 | "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", 956 | ] 957 | 958 | [[package]] 959 | name = "slab" 960 | version = "0.4.2" 961 | source = "registry+https://github.com/rust-lang/crates.io-index" 962 | 963 | [[package]] 964 | name = "sled" 965 | version = "0.28.0" 966 | source = "registry+https://github.com/rust-lang/crates.io-index" 967 | dependencies = [ 968 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 969 | "pagecache 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)", 970 | "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 971 | "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", 972 | "serde_bytes 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", 973 | ] 974 | 975 | [[package]] 976 | name = "sluice" 977 | version = "0.4.2" 978 | source = "registry+https://github.com/rust-lang/crates.io-index" 979 | dependencies = [ 980 | "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 981 | "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 982 | "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 983 | ] 984 | 985 | [[package]] 986 | name = "smallvec" 987 | version = "0.6.13" 988 | source = "registry+https://github.com/rust-lang/crates.io-index" 989 | dependencies = [ 990 | "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 991 | ] 992 | 993 | [[package]] 994 | name = "socket2" 995 | version = "0.3.11" 996 | source = "registry+https://github.com/rust-lang/crates.io-index" 997 | dependencies = [ 998 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 999 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 1000 | "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", 1001 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 1002 | ] 1003 | 1004 | [[package]] 1005 | name = "spo2" 1006 | version = "0.1.0" 1007 | dependencies = [ 1008 | "arraydeque 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", 1009 | "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 1010 | "futures-stream-batch 0.2.0 (git+https://github.com/Kerollmops/futures-stream-batch.git)", 1011 | "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1012 | "isahc 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", 1013 | "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1014 | "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", 1015 | "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", 1016 | "sled 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", 1017 | "subslice 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 1018 | "tiny_http 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", 1019 | "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1020 | "ws 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", 1021 | ] 1022 | 1023 | [[package]] 1024 | name = "subslice" 1025 | version = "0.2.2" 1026 | source = "registry+https://github.com/rust-lang/crates.io-index" 1027 | dependencies = [ 1028 | "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 1029 | ] 1030 | 1031 | [[package]] 1032 | name = "syn" 1033 | version = "1.0.8" 1034 | source = "registry+https://github.com/rust-lang/crates.io-index" 1035 | dependencies = [ 1036 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 1037 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1038 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1039 | ] 1040 | 1041 | [[package]] 1042 | name = "tempdir" 1043 | version = "0.3.7" 1044 | source = "registry+https://github.com/rust-lang/crates.io-index" 1045 | dependencies = [ 1046 | "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 1047 | "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 1048 | ] 1049 | 1050 | [[package]] 1051 | name = "time" 1052 | version = "0.1.42" 1053 | source = "registry+https://github.com/rust-lang/crates.io-index" 1054 | dependencies = [ 1055 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 1056 | "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", 1057 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 1058 | ] 1059 | 1060 | [[package]] 1061 | name = "tiny_http" 1062 | version = "0.6.2" 1063 | source = "registry+https://github.com/rust-lang/crates.io-index" 1064 | dependencies = [ 1065 | "ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", 1066 | "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", 1067 | "chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 1068 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 1069 | "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 1070 | ] 1071 | 1072 | [[package]] 1073 | name = "typenum" 1074 | version = "1.11.2" 1075 | source = "registry+https://github.com/rust-lang/crates.io-index" 1076 | 1077 | [[package]] 1078 | name = "unicode-bidi" 1079 | version = "0.3.4" 1080 | source = "registry+https://github.com/rust-lang/crates.io-index" 1081 | dependencies = [ 1082 | "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 1083 | ] 1084 | 1085 | [[package]] 1086 | name = "unicode-normalization" 1087 | version = "0.1.9" 1088 | source = "registry+https://github.com/rust-lang/crates.io-index" 1089 | dependencies = [ 1090 | "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", 1091 | ] 1092 | 1093 | [[package]] 1094 | name = "unicode-xid" 1095 | version = "0.2.0" 1096 | source = "registry+https://github.com/rust-lang/crates.io-index" 1097 | 1098 | [[package]] 1099 | name = "url" 1100 | version = "1.7.2" 1101 | source = "registry+https://github.com/rust-lang/crates.io-index" 1102 | dependencies = [ 1103 | "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 1104 | "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 1105 | "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1106 | ] 1107 | 1108 | [[package]] 1109 | name = "url" 1110 | version = "2.1.0" 1111 | source = "registry+https://github.com/rust-lang/crates.io-index" 1112 | dependencies = [ 1113 | "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1114 | "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 1115 | "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1116 | "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", 1117 | ] 1118 | 1119 | [[package]] 1120 | name = "vcpkg" 1121 | version = "0.2.7" 1122 | source = "registry+https://github.com/rust-lang/crates.io-index" 1123 | 1124 | [[package]] 1125 | name = "version_check" 1126 | version = "0.1.5" 1127 | source = "registry+https://github.com/rust-lang/crates.io-index" 1128 | 1129 | [[package]] 1130 | name = "walkdir" 1131 | version = "2.2.9" 1132 | source = "registry+https://github.com/rust-lang/crates.io-index" 1133 | dependencies = [ 1134 | "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 1135 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 1136 | "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 1137 | ] 1138 | 1139 | [[package]] 1140 | name = "wasi" 1141 | version = "0.7.0" 1142 | source = "registry+https://github.com/rust-lang/crates.io-index" 1143 | 1144 | [[package]] 1145 | name = "winapi" 1146 | version = "0.2.8" 1147 | source = "registry+https://github.com/rust-lang/crates.io-index" 1148 | 1149 | [[package]] 1150 | name = "winapi" 1151 | version = "0.3.8" 1152 | source = "registry+https://github.com/rust-lang/crates.io-index" 1153 | dependencies = [ 1154 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1155 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1156 | ] 1157 | 1158 | [[package]] 1159 | name = "winapi-build" 1160 | version = "0.1.1" 1161 | source = "registry+https://github.com/rust-lang/crates.io-index" 1162 | 1163 | [[package]] 1164 | name = "winapi-i686-pc-windows-gnu" 1165 | version = "0.4.0" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | 1168 | [[package]] 1169 | name = "winapi-util" 1170 | version = "0.1.2" 1171 | source = "registry+https://github.com/rust-lang/crates.io-index" 1172 | dependencies = [ 1173 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 1174 | ] 1175 | 1176 | [[package]] 1177 | name = "winapi-x86_64-pc-windows-gnu" 1178 | version = "0.4.0" 1179 | source = "registry+https://github.com/rust-lang/crates.io-index" 1180 | 1181 | [[package]] 1182 | name = "ws" 1183 | version = "0.9.1" 1184 | source = "registry+https://github.com/rust-lang/crates.io-index" 1185 | dependencies = [ 1186 | "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 1187 | "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", 1188 | "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 1189 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 1190 | "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", 1191 | "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 1192 | "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 1193 | "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", 1194 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 1195 | "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1196 | ] 1197 | 1198 | [[package]] 1199 | name = "ws2_32-sys" 1200 | version = "0.2.1" 1201 | source = "registry+https://github.com/rust-lang/crates.io-index" 1202 | dependencies = [ 1203 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 1204 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 1205 | ] 1206 | 1207 | [metadata] 1208 | "checksum arraydeque 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0ffd3d69bd89910509a5d31d1f1353f38ccffdd116dd0099bbd6627f7bd8ad8" 1209 | "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" 1210 | "checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14" 1211 | "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" 1212 | "checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" 1213 | "checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" 1214 | "checksum bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ab639324e3ee8774d296864fbc0dbbb256cf1a41c490b94cba90c082915f92" 1215 | "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 1216 | "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" 1217 | "checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" 1218 | "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" 1219 | "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" 1220 | "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" 1221 | "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" 1222 | "checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" 1223 | "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" 1224 | "checksum cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8" 1225 | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 1226 | "checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" 1227 | "checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" 1228 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 1229 | "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" 1230 | "checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" 1231 | "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" 1232 | "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" 1233 | "checksum curl 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)" = "06aa71e9208a54def20792d877bc663d6aae0732b9852e612c4a933177c31283" 1234 | "checksum curl-sys 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "f659f3ffac9582d6177bb86d1d2aa649f4eb9d0d4de9d03ccc08b402832ea340" 1235 | "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" 1236 | "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" 1237 | "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" 1238 | "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" 1239 | "checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" 1240 | "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" 1241 | "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" 1242 | "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" 1243 | "checksum futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a" 1244 | "checksum futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" 1245 | "checksum futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "75236e88bd9fe88e5e8bfcd175b665d0528fe03ca4c5207fabc028c8f9d93e98" 1246 | "checksum futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f4914ae450db1921a56c91bde97a27846287d062087d4a652efc09bb3a01ebda" 1247 | "checksum futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "3b1dce2a0267ada5c6ff75a8ba864b4e679a9e2aa44262af7a3b5516d530d76e" 1248 | "checksum futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec" 1249 | "checksum futures-stream-batch 0.2.0 (git+https://github.com/Kerollmops/futures-stream-batch.git)" = "" 1250 | "checksum futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "878f1d2fc31355fa02ed2372e741b0c17e58373341e6a122569b4623a14a7d33" 1251 | "checksum futures-timer 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7946248e9429ff093345d3e8fdf4eb0f9b2d79091611c9c14f744971a6f8be45" 1252 | "checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d" 1253 | "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" 1254 | "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" 1255 | "checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" 1256 | "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" 1257 | "checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" 1258 | "checksum http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d7e06e336150b178206af098a055e3621e8336027e2b4d126bda0bc64824baaf" 1259 | "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" 1260 | "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" 1261 | "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" 1262 | "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" 1263 | "checksum isahc 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "17b77027f12e53ae59a379f7074259d32eb10867e6183388020e922832d9c3fb" 1264 | "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" 1265 | "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 1266 | "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 1267 | "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" 1268 | "checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" 1269 | "checksum libnghttp2-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02254d44f4435dd79e695f2c2b83cd06a47919adea30216ceaf0c57ca0a72463" 1270 | "checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" 1271 | "checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" 1272 | "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 1273 | "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" 1274 | "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" 1275 | "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" 1276 | "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" 1277 | "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" 1278 | "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" 1279 | "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" 1280 | "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" 1281 | "checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" 1282 | "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" 1283 | "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" 1284 | "checksum num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "155394f924cdddf08149da25bfb932d226b4a593ca7468b08191ff6335941af5" 1285 | "checksum once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891f486f630e5c5a4916c7e16c4b24a53e78c860b646e9f8e005e4f16847bfed" 1286 | "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" 1287 | "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" 1288 | "checksum openssl-sys 0.9.52 (registry+https://github.com/rust-lang/crates.io-index)" = "c977d08e1312e2f7e4b86f9ebaa0ed3b19d1daff75fae88bbb88108afbd801fc" 1289 | "checksum pagecache 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3a3cb2f80e81d64e087e9de0dedd9d95c4360aae2822917d5e4994bf1b2e0070" 1290 | "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" 1291 | "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" 1292 | "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" 1293 | "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 1294 | "checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" 1295 | "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" 1296 | "checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" 1297 | "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" 1298 | "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" 1299 | "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" 1300 | "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" 1301 | "checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" 1302 | "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" 1303 | "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" 1304 | "checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" 1305 | "checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" 1306 | "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" 1307 | "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" 1308 | "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" 1309 | "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" 1310 | "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" 1311 | "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 1312 | "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" 1313 | "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" 1314 | "checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" 1315 | "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" 1316 | "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 1317 | "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 1318 | "checksum serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4b39bd9b0b087684013a792c59e3e07a46a01d2322518d8a1104641a0b1be0" 1319 | "checksum serde_bytes 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "45af0182ff64abaeea290235eb67da3825a576c5d53e642c4d5b652e12e6effc" 1320 | "checksum serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "ca13fc1a832f793322228923fbb3aba9f3f44444898f835d31ad1b74fa0a2bf8" 1321 | "checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" 1322 | "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" 1323 | "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" 1324 | "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" 1325 | "checksum sled 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3d0ffdcb80d10203517641c514b205d89541b001149df43ae6e902bc19809d" 1326 | "checksum sluice 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7d06dfb3e8743bc19e6de8a302277471d08077d68946b307280496dc5a3531" 1327 | "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" 1328 | "checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" 1329 | "checksum subslice 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "63e487c3d5eff5fd5f8641dd21e8a83ebfead68557b3b3aebea0fab44b1c4875" 1330 | "checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92" 1331 | "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" 1332 | "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" 1333 | "checksum tiny_http 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1661fa0a44c95d01604bd05c66732a446c657efb62b5164a7a083a3b552b4951" 1334 | "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" 1335 | "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" 1336 | "checksum unicode-normalization 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "09c8070a9942f5e7cfccd93f490fdebd230ee3c3c9f107cb25bad5351ef671cf" 1337 | "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 1338 | "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" 1339 | "checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" 1340 | "checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" 1341 | "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" 1342 | "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" 1343 | "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" 1344 | "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 1345 | "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" 1346 | "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 1347 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1348 | "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" 1349 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1350 | "checksum ws 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a2c47b5798ccc774ffb93ff536aec7c4275d722fd9c740c83cdd1af1f2d94" 1351 | "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" 1352 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "spo2" 3 | version = "0.1.0" 4 | authors = ["Clément Renault "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | arraydeque = "0.4.5" 9 | futures-preview = "0.3.0-alpha.19" 10 | futures-timer = "0.4.0" 11 | once_cell = "1.0.2" 12 | isahc = "0.7.5" 13 | serde = { version = "1.0.100", features = ["derive"] } 14 | serde_json = "1.0.40" 15 | sled = "0.28.0" 16 | subslice = "0.2.2" 17 | tiny_http = "0.6.2" 18 | url = { version = "2.1.0", features = ["serde"] } 19 | ws = "0.9.0" 20 | 21 | [dependencies.futures-stream-batch] 22 | git = "https://github.com/Kerollmops/futures-stream-batch.git" 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Clément Renault 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SpO₂ 2 | 3 | SpO₂ is a monitor for any program using the HTTP protocol. For more detail and background, see the [blog post announcing the release of the project](https://blog.meilisearch.com/spo2-the-little-dynamic-monitoring-tool/). 4 | 5 | (In medicine, SpO₂ refers to oxygen saturation levels in blood and is used as a measure of a person's health. O₂ is the scientific designation for an oxygen atom.) 6 | 7 | This project uses [sled](https://github.com/spacejam/sled) to permanently save the health checked URLs. 8 | It provides a websocket API that returns the changing status of the health checked URLs. 9 | 10 | SpO₂ doesn't support SSL out of the box, if you need [you can setup an Nginx server as we do][1]. 11 | 12 | [1]: /enable-ssl.md 13 | 14 | ![SpO2 dashboard screenshot](/misc/screenshot.png) 15 | 16 | ## Usage 17 | 18 | You must have [installed Rust](https://rustup.rs/) on your computer first. 19 | 20 | ```bash 21 | # to try it in debug mode 22 | cargo run 23 | 24 | # or in release mode 25 | cargo run --release 26 | 27 | # you can also change the listen addrs with env variables 28 | export HTTP_LISTEN_ADDR='127.0.0.1:8000' 29 | export WS_LISTEN_ADDR='127.0.0.1:8001' 30 | cargo run --release 31 | 32 | # with the previous settings the HTTP and the WebSocket server will be 33 | # available on http://127.0.0.1:8000/ and ws://127.0.0.1:8001/ respectively 34 | 35 | # to enable the slack notifier you must set the corresponding env variable 36 | export SLACK_HOOK_URL='Your Slack Webhook URL' 37 | cargo run --release 38 | ``` 39 | 40 | ### Add or Update a new URL to health check 41 | 42 | Calling this route is "kind of" idenpotent, it means that it will not run another health checker on this URL but the custom json data will be updated. 43 | 44 | ```bash 45 | curl -i -X PUT 'http://127.0.0.1:8000/?url=http%3A%2F%2Flocalhost%2Fhealth' -d '"your custom json data"' 46 | 47 | # Note that 'http%3A%2F%2Flocalhost%2Fhealth' is the url to health check 48 | # but it is url encoded and correspond to 'http://localhost/health' 49 | ``` 50 | 51 | ### Remove an health checked URL 52 | 53 | Calling this route will remove the URL from the health check pool and return you the custom json data associated with it. 54 | 55 | ```bash 56 | curl -i -X DELETE 'http://127.0.0.1:8000/?url=http%3A%2F%2Flocalhost%2Fhealth' 57 | ``` 58 | 59 | ### Get an health checked URL data 60 | 61 | Will return the associated data of an already health checked URL. 62 | 63 | ```bash 64 | curl -i -X GET 'http://127.0.0.1:8000/?url=http%3A%2F%2Flocalhost%2Fhealth' 65 | ``` 66 | 67 | ### Get all the health checked URLs 68 | 69 | Will return the list of all the health checked URLs aloang with the data associated with them. 70 | 71 | ```bash 72 | curl -i -X GET 'http://127.0.0.1:8000/all' 73 | ``` 74 | -------------------------------------------------------------------------------- /enable-ssl.md: -------------------------------------------------------------------------------- 1 | # How to enable SSL for SpO₂ 2 | 3 | SpO₂ Doesn't support SSL by itself, it is why we used an ngninx on top of it. 4 | Configuring an Nginx to SSL encrypt the HTTP server was easy but the hard part was to encrypt WebSockets. 5 | 6 | To make it work you must install CertBot first, it will generate certificates and auto renew them. 7 | Once you have installed CertBot it will automatically manage your certificates and make your domain access secure. 8 | 9 | https://certbot.eff.org/lets-encrypt/debianbuster-nginx 10 | 11 | Here is an example of our own Nginx configuration after CertBot have been installed: 12 | 13 | ```Nginx 14 | server { 15 | listen 80; 16 | return 301 https://$host$request_uri; 17 | } 18 | 19 | server { 20 | listen 443; 21 | server_name spo2.yourdomainname.com; 22 | ssl_certificate /etc/letsencrypt/live/spo2.yourdomainname.com/fullchain.pem; # managed by Certbot 23 | ssl_certificate_key /etc/letsencrypt/live/spo2.yourdomainname.com/privkey.pem; # managed by Certbot 24 | 25 | ssl on; 26 | ssl_session_cache builtin:1000 shared:SSL:10m; 27 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 28 | ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4; 29 | ssl_prefer_server_ciphers on; 30 | 31 | access_log /var/log/nginx/spo2.access.log; 32 | 33 | location / { 34 | auth_basic "Please enter the secret password"; 35 | auth_basic_user_file /etc/apache2/.htpasswd; 36 | 37 | proxy_set_header Host $host; 38 | proxy_set_header X-Real-IP $remote_addr; 39 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 40 | proxy_set_header X-Forwarded-Proto $scheme; 41 | 42 | proxy_pass http://localhost:8000; 43 | proxy_read_timeout 90; 44 | 45 | proxy_redirect http://localhost:8000 https://spo2.yourdomainname.com; 46 | } 47 | 48 | } 49 | 50 | upstream appserver { 51 | server localhost:8001; 52 | } 53 | 54 | server { 55 | listen 8888; 56 | # server_name spo2.yourdomainname.com; 57 | 58 | ssl on; 59 | ssl_certificate /etc/letsencrypt/live/spo2.yourdomainname.com/fullchain.pem; # managed by Certbot 60 | ssl_certificate_key /etc/letsencrypt/live/spo2.yourdomainname.com/privkey.pem; # managed by Certbot 61 | 62 | access_log /var/log/nginx/spo2.access.log; 63 | 64 | location / { 65 | proxy_pass http://appserver; 66 | proxy_read_timeout 90; 67 | 68 | proxy_http_version 1.1; 69 | proxy_set_header Upgrade $http_upgrade; 70 | proxy_set_header Connection "upgrade"; 71 | } 72 | } 73 | ``` 74 | -------------------------------------------------------------------------------- /misc/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kerollmops/spo2/3bdf820ab793ca4fd2698515fab98dccbfc1599b/misc/screenshot.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SpO₂ - Dashboard 6 | 7 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 37 | 38 | 39 | 40 | 41 | 42 | 178 | 179 | 180 | 181 | 387 | 388 | 389 | 390 |
391 |
392 |
393 | 394 | 395 |
396 | 397 | 398 | -------------------------------------------------------------------------------- /src/health_checker.rs: -------------------------------------------------------------------------------- 1 | use std::time::{Duration, Instant}; 2 | 3 | use futures::channel::mpsc::Sender; 4 | use futures::sink::SinkExt; 5 | use futures_timer::Delay; 6 | use isahc::prelude::*; 7 | use url::Url; 8 | 9 | use crate::url_value::{Report, UrlValue}; 10 | use crate::url_value::Status::{Healthy, Unhealthy, Unreacheable}; 11 | 12 | const STILL_UNHEALTHY_TIMEOUT: Duration = Duration::from_secs(15 * 60); // 15 minutes 13 | const TIMEOUT: Duration = Duration::from_secs(5); 14 | const NORMAL_PING: Duration = Duration::from_secs(3); 15 | const FAST_PING: Duration = Duration::from_millis(800); 16 | 17 | type ArrayDeque10 = arraydeque::ArrayDeque<[T; 10], arraydeque::Wrapping>; 18 | 19 | pub async fn health_checker( 20 | url: Url, 21 | mut report_sender: Sender, 22 | event_sender: ws::Sender, 23 | database: sled::Db, 24 | ) { 25 | let mut last_status = ArrayDeque10::new(); 26 | let mut in_bad_state_since = None; 27 | 28 | loop { 29 | let request = Request::get(url.as_str()).timeout(TIMEOUT).body(()).unwrap(); 30 | let (status, reason) = match isahc::send_async(request).await { 31 | Ok(ref resp) if resp.status().is_success() => { 32 | (Healthy, resp.status().to_string()) 33 | }, 34 | Ok(resp) => (Unhealthy, resp.status().to_string()), 35 | Err(e) => (Unreacheable, e.to_string()), 36 | }; 37 | 38 | last_status.push_front(status); 39 | 40 | // update this value but do not erase the user custom data updates 41 | let result = database.update_and_fetch(url.as_str(), |old| { 42 | let old = old?; 43 | let mut value: UrlValue = serde_json::from_slice(old).unwrap(); 44 | value.status = status; 45 | value.reason = reason.clone(); 46 | Some(serde_json::to_vec(&value).unwrap()) 47 | }); 48 | 49 | // retrieve the new value and deserialize it 50 | // assign the current url this way it can be send in notifications 51 | let value = match result { 52 | Ok(Some(value)) => { 53 | let mut value: UrlValue = serde_json::from_slice(&value).unwrap(); 54 | value.url = Some(url.to_string()); 55 | value 56 | }, 57 | Ok(None) => break, 58 | Err(e) => { eprintln!("{}: {}", url, e); return }, 59 | }; 60 | 61 | let cap = last_status.capacity() as f32; 62 | let bads = last_status.iter().filter(|s| !s.is_good()).count() as f32; 63 | let ratio = bads / cap; 64 | 65 | if ratio >= 0.5 && in_bad_state_since.is_none() { 66 | in_bad_state_since = Some((status, Instant::now())); 67 | 68 | let report = Report { url: url.clone(), status, still: false, reason: reason.clone() }; 69 | let _ = report_sender.send(report).await; 70 | 71 | let message = serde_json::to_string(&value).unwrap(); 72 | let _ = event_sender.send(message); 73 | } 74 | 75 | if ratio == 0.0 && in_bad_state_since.is_some() { 76 | in_bad_state_since = None; 77 | 78 | let report = Report { url: url.clone(), status, still: false, reason: reason.clone() }; 79 | let _ = report_sender.send(report).await; 80 | 81 | let message = serde_json::to_string(&value).unwrap(); 82 | let _ = event_sender.send(message); 83 | } 84 | 85 | if (in_bad_state_since.is_some() || !status.is_good() || ratio >= 0.5) && ratio != 1.0 { 86 | let _ = Delay::new(FAST_PING).await; 87 | } else { 88 | let _ = Delay::new(NORMAL_PING).await; 89 | } 90 | 91 | if let Some((status, since)) = in_bad_state_since { 92 | if since.elapsed() > STILL_UNHEALTHY_TIMEOUT { 93 | let report = Report { url: url.clone(), status, still: true, reason }; 94 | let _ = report_sender.send(report).await; 95 | 96 | let message = serde_json::to_string(&value).unwrap(); 97 | let _ = event_sender.send(message); 98 | 99 | in_bad_state_since = Some((status, Instant::now())); 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod health_checker; 2 | mod routes; 3 | mod url_value; 4 | 5 | use std::cmp::Reverse; 6 | use std::fmt::Write; 7 | use std::str::FromStr; 8 | use std::time::Duration; 9 | use std::{env, io, str, thread}; 10 | 11 | use futures::channel::mpsc::{self, Sender}; 12 | use futures::executor::ThreadPool; 13 | use futures::stream::StreamExt; 14 | use futures_stream_batch::ChunksTimeoutStreamExt; 15 | use isahc::prelude::*; 16 | use subslice::SubsliceExt; 17 | use tiny_http::{Response, Method, Header}; 18 | use url::Url; 19 | 20 | use self::health_checker::health_checker; 21 | use self::routes::{update_url, read_url, delete_url, get_all_urls}; 22 | use self::url_value::Report; 23 | 24 | const HTTP_LISTEN_ADDR: &str = "HTTP_LISTEN_ADDR"; 25 | const WS_LISTEN_ADDR: &str = "WS_LISTEN_ADDR"; 26 | const SLACK_HOOK_URL: &str = "SLACK_HOOK_URL"; 27 | const DATABASE_PATH: &str = "DATABASE_PATH"; 28 | 29 | const HTML_CONTENT: &str = include_str!("../public/index.html"); 30 | 31 | pub struct State { 32 | runtime: ThreadPool, 33 | notifier_sender: Sender, 34 | event_sender: ws::Sender, 35 | database: sled::Db, 36 | } 37 | 38 | fn main() -> Result<(), io::Error> { 39 | let ws_listen_addr = match env::var(WS_LISTEN_ADDR) { 40 | Ok(addr) => addr, 41 | Err(e) => { 42 | eprintln!("{}: {}", WS_LISTEN_ADDR, e); 43 | String::from("127.0.0.1:8001") 44 | }, 45 | }; 46 | 47 | let http_listen_addr = match env::var(HTTP_LISTEN_ADDR) { 48 | Ok(addr) => addr, 49 | Err(e) => { 50 | eprintln!("{}: {}", HTTP_LISTEN_ADDR, e); 51 | String::from("127.0.0.1:8000") 52 | }, 53 | }; 54 | 55 | let database_path = match env::var(DATABASE_PATH) { 56 | Ok(path) => path, 57 | Err(e) => { 58 | eprintln!("{}: {}", DATABASE_PATH, e); 59 | String::from("spo2.db") 60 | }, 61 | }; 62 | 63 | let runtime = ThreadPool::new().unwrap(); 64 | let (notifier_sender, receiver) = mpsc::channel(100); 65 | let database = sled::Db::open(database_path).unwrap(); 66 | 67 | // initialize the notifier sender 68 | runtime.spawn_ok(async move { 69 | let slack_hook_url = match env::var(SLACK_HOOK_URL) { 70 | Ok(url) => url, 71 | Err(e) => { 72 | eprintln!("{}: {}", SLACK_HOOK_URL, e); 73 | return 74 | } 75 | }; 76 | 77 | let mut receiver = receiver.chunks_timeout(40, Duration::new(10, 0)); 78 | while let Some(mut reports) = receiver.next().await { 79 | // remove subsequent urls status for the same url 80 | reports.sort_by_key(|r: &Report| Reverse(r.url.clone())); 81 | reports.dedup_by_key(|r| r.url.clone()); 82 | 83 | let mut body = String::new(); 84 | 85 | // if reports contain newly detected bad status 86 | if reports.iter().any(|r| !r.still && !r.status.is_good()) { 87 | let _ = writeln!(&mut body, ""); 88 | } 89 | 90 | for Report { url, status, still, reason } in reports { 91 | let _ = if still { 92 | writeln!(&mut body, "{} is still {:?}", url, status) 93 | } else if status.is_good() { 94 | writeln!(&mut body, "{} is now {:?} 🎉", url, status) 95 | } else { 96 | writeln!(&mut body, "{} reported {:?} ({})", url, status, reason) 97 | }; 98 | } 99 | 100 | let body = serde_json::json!({ "text": body }); 101 | let request = Request::post(&slack_hook_url) 102 | .header("content-type", "application/json") 103 | .body(serde_json::to_vec(&body).unwrap()) 104 | .unwrap(); 105 | 106 | if let Err(e) = isahc::send_async(request).await { 107 | eprintln!("{}", e); 108 | } 109 | } 110 | }); 111 | 112 | // initialize the websocket listener 113 | let builder = ws::Builder::new(); 114 | let ws = builder.build(|_| |_| Ok(())).unwrap(); 115 | let event_sender = ws.broadcaster(); 116 | 117 | // run the websocket listener 118 | println!("Websocket server is listening on: ws://{}", ws_listen_addr); 119 | let _ = thread::spawn(|| { 120 | ws.listen(ws_listen_addr).expect("websocket listen error") 121 | }); 122 | 123 | // run health checking for every url saved 124 | for result in database.iter() { 125 | let key = match result { 126 | Ok((key, _)) => key, 127 | Err(e) => { eprintln!("{}", e); continue }, 128 | }; 129 | 130 | let string = str::from_utf8(&key).unwrap(); 131 | let url = Url::parse(string).unwrap(); 132 | 133 | let notifier_sender = notifier_sender.clone(); 134 | let database = database.clone(); 135 | let event_sender = event_sender.clone(); 136 | 137 | runtime.spawn_ok(async { 138 | health_checker(url, notifier_sender, event_sender, database).await 139 | }); 140 | } 141 | 142 | let state = State { runtime, notifier_sender, event_sender, database }; 143 | 144 | let server = tiny_http::Server::http(http_listen_addr).unwrap(); 145 | let http_listen_addr = server.server_addr(); 146 | eprintln!("Listening on {}", http_listen_addr); 147 | 148 | let base_url = format!("http://{}", http_listen_addr); 149 | let base_url = Url::parse(&base_url).unwrap(); 150 | 151 | loop { 152 | let request = match server.recv() { 153 | Ok(request) => request, 154 | Err(e) => { eprintln!("{}", e); continue } 155 | }; 156 | 157 | let method = request.method(); 158 | let url = match base_url.join(request.url()) { 159 | Ok(url) => url, 160 | Err(error) => { 161 | let message = error.to_string(); 162 | let response = Response::from_string(message).with_status_code(400); 163 | if let Err(e) = request.respond(response) { eprintln!("{}", e) } 164 | continue; 165 | } 166 | }; 167 | 168 | fn accept_text_html(header: &Header) -> bool { 169 | header.field.equiv("accept") && header.value.as_bytes().find(b"text/html").is_some() 170 | } 171 | 172 | let result = match (url.path(), method) { 173 | ("/all", &Method::Get) => get_all_urls(url, request, &state), 174 | ("/", &Method::Get) => { 175 | if request.headers().iter().any(accept_text_html) { 176 | let response = Response::from_string(HTML_CONTENT) 177 | .with_header(Header::from_str("Content-Type: text/html; charset=utf-8").unwrap()) 178 | .with_status_code(200); 179 | request.respond(response).map_err(Into::into) 180 | } else { 181 | read_url(url, request, &state) 182 | } 183 | }, 184 | ("/", &Method::Post) => update_url(url, request, &state), 185 | ("/", &Method::Put) => update_url(url, request, &state), 186 | ("/", &Method::Delete) => delete_url(url, request, &state), 187 | (_path, _method) => request.respond(Response::empty(404)).map_err(Into::into), 188 | }; 189 | 190 | if let Err(e) = result { 191 | eprintln!("{}", e); 192 | } 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /src/routes.rs: -------------------------------------------------------------------------------- 1 | use std::io::{Cursor, Empty}; 2 | use std::{str, fmt}; 3 | use std::str::FromStr; 4 | 5 | use url::Url; 6 | use serde_json::Value; 7 | use tiny_http::{Request, Response, Header}; 8 | 9 | use crate::health_checker::health_checker; 10 | use crate::State; 11 | use crate::url_value::UrlValue; 12 | use crate::url_value::Status::{Healthy, Removed}; 13 | 14 | type BoxError = Box; 15 | 16 | pub fn into_json(data: Vec) -> Response>> { 17 | Response::from_data(data) 18 | .with_header(Header::from_str("Content-Type: application/json").unwrap()) 19 | } 20 | 21 | pub fn into_internal_error(e: E) -> Response>> { 22 | Response::from_string(e.to_string()) 23 | .with_status_code(500) 24 | } 25 | 26 | pub fn into_bad_request(e: E) -> Response>> { 27 | Response::from_string(e.to_string()) 28 | .with_status_code(400) 29 | } 30 | 31 | pub fn not_found() -> Response { 32 | Response::empty(404) 33 | } 34 | 35 | fn is_valid_url(url: &Url) -> bool { 36 | if url.cannot_be_a_base() { 37 | return false 38 | } 39 | 40 | match url.scheme() { 41 | "http" | "https" => true, 42 | _ => false, 43 | } 44 | } 45 | 46 | pub fn update_url(url: Url, mut request: Request, state: &State) -> Result<(), BoxError> { 47 | let url = match url.query_pairs().find(|(k, _)| k == "url") { 48 | Some((_, url)) => match Url::parse(&url) { 49 | Ok(url) => url, 50 | Err(e) => return request.respond(into_bad_request(e)).map_err(Into::into), 51 | }, 52 | None => { 53 | return request.respond(into_bad_request("missing url parameter")).map_err(Into::into) 54 | }, 55 | }; 56 | 57 | if !is_valid_url(&url) { 58 | return request.respond(into_bad_request("Invalid url, must be an http/s url")).map_err(Into::into) 59 | } 60 | 61 | let mut body = String::new(); 62 | if let Err(e) = request.as_reader().read_to_string(&mut body) { 63 | return request.respond(into_bad_request(e)).map_err(Into::into) 64 | } 65 | 66 | let user_data = if body.is_empty() { 67 | Value::Null 68 | } else { 69 | match serde_json::from_slice(body.as_bytes()) { 70 | Ok(value) => value, 71 | Err(e) => return request.respond(into_bad_request(e)).map_err(Into::into), 72 | } 73 | }; 74 | 75 | let mut value = UrlValue { 76 | url: None, 77 | status: Healthy, 78 | reason: String::new(), 79 | data: user_data.clone(), 80 | }; 81 | let mut value_bytes = match serde_json::to_vec(&value) { 82 | Ok(value_bytes) => value_bytes, 83 | Err(e) => return request.respond(into_internal_error(e)).map_err(Into::into), 84 | }; 85 | 86 | let pool = &state.runtime; 87 | let database = state.database.clone(); 88 | let notifier_sender = state.notifier_sender.clone(); 89 | let event_sender = state.event_sender.clone(); 90 | 91 | // update this value but do not erase 92 | // the last status written by the health checker 93 | let result = database.fetch_and_update(url.as_str(), |old| { 94 | match old { 95 | Some(old) => { 96 | value = serde_json::from_slice(old).unwrap(); 97 | value.data = user_data.clone(); 98 | value_bytes = serde_json::to_vec(&value).unwrap(); 99 | Some(value_bytes.clone()) 100 | }, 101 | None => Some(value_bytes.clone()), 102 | } 103 | }); 104 | 105 | match result { 106 | Ok(None) => { 107 | // send the initial healthy message when an url is added 108 | value.url = Some(url.to_string()); 109 | let message = match serde_json::to_string(&value) { 110 | Ok(message) => message, 111 | Err(e) => return request.respond(into_internal_error(e)).map_err(Into::into), 112 | }; 113 | let _ = event_sender.send(message); 114 | 115 | pool.spawn_ok(async { 116 | health_checker(url, notifier_sender, event_sender, database).await 117 | }); 118 | 119 | request.respond(into_json(value_bytes)).map_err(Into::into) 120 | }, 121 | Ok(Some(_)) => request.respond(into_json(value_bytes)).map_err(Into::into), 122 | Err(e) => Err(e.into()), 123 | } 124 | } 125 | 126 | pub fn read_url(url: Url, request: Request, state: &State) -> Result<(), BoxError> { 127 | let url = match url.query_pairs().find(|(k, _)| k == "url") { 128 | Some((_, url)) => match Url::parse(&url) { 129 | Ok(url) => url, 130 | Err(e) => return request.respond(into_bad_request(e)).map_err(Into::into), 131 | }, 132 | None => { 133 | return request.respond(into_bad_request("missing url parameter")).map_err(Into::into) 134 | }, 135 | }; 136 | 137 | let database = &state.database; 138 | match database.get(url.as_str()) { 139 | Ok(Some(value)) => request.respond(into_json(value.to_vec())).map_err(Into::into), 140 | Ok(None) => request.respond(not_found()).map_err(Into::into), 141 | Err(e) => request.respond(into_internal_error(e)).map_err(Into::into), 142 | } 143 | } 144 | 145 | pub fn delete_url(url: Url, request: Request, state: &State) -> Result<(), BoxError> { 146 | let url = match url.query_pairs().find(|(k, _)| k == "url") { 147 | Some((_, url)) => match Url::parse(&url) { 148 | Ok(url) => url, 149 | Err(e) => return request.respond(into_bad_request(e)).map_err(Into::into), 150 | }, 151 | None => { 152 | return request.respond(into_bad_request("missing url parameter")).map_err(Into::into) 153 | }, 154 | }; 155 | 156 | let database = &state.database; 157 | let event_sender = &state.event_sender; 158 | 159 | match database.remove(url.as_str()) { 160 | Ok(Some(value_bytes)) => { 161 | let mut value: UrlValue = match serde_json::from_slice(&value_bytes) { 162 | Ok(value) => value, 163 | Err(e) => return request.respond(into_internal_error(e)).map_err(Into::into), 164 | }; 165 | value.status = Removed; 166 | value.url = Some(url.to_string()); 167 | 168 | let message = match serde_json::to_string(&value) { 169 | Ok(message) => message, 170 | Err(e) => return request.respond(into_internal_error(e)).map_err(Into::into), 171 | }; 172 | let _ = event_sender.send(message); 173 | 174 | request.respond(into_json(value_bytes.to_vec())).map_err(Into::into) 175 | }, 176 | Ok(None) => request.respond(not_found()).map_err(Into::into), 177 | Err(e) => request.respond(into_internal_error(e)).map_err(Into::into), 178 | } 179 | } 180 | 181 | pub fn get_all_urls(_url: Url, request: Request, state: &State) -> Result<(), BoxError> { 182 | let database = &state.database; 183 | 184 | let mut urls = Vec::new(); 185 | for result in database.iter() { 186 | let (key, value) = match result { 187 | Ok(pair) => pair, 188 | Err(e) => return request.respond(into_internal_error(e)).map_err(Into::into), 189 | }; 190 | 191 | let string = match str::from_utf8(&key) { 192 | Ok(string) => string, 193 | Err(e) => return request.respond(into_internal_error(e)).map_err(Into::into), 194 | }; 195 | let url = match Url::parse(&string) { 196 | Ok(url) => url, 197 | Err(e) => return request.respond(into_internal_error(e)).map_err(Into::into), 198 | }; 199 | 200 | let mut value: UrlValue = match serde_json::from_slice(&value) { 201 | Ok(value) => value, 202 | Err(e) => return request.respond(into_internal_error(e)).map_err(Into::into), 203 | }; 204 | value.url = Some(url.to_string()); 205 | 206 | urls.push(value); 207 | } 208 | 209 | let urls = match serde_json::to_vec(&urls) { 210 | Ok(urls) => urls, 211 | Err(e) => return request.respond(into_internal_error(e)).map_err(Into::into), 212 | }; 213 | 214 | request.respond(into_json(urls)).map_err(Into::into) 215 | } 216 | -------------------------------------------------------------------------------- /src/url_value.rs: -------------------------------------------------------------------------------- 1 | use serde::{Serialize, Deserialize}; 2 | use url::Url; 3 | 4 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] 5 | pub enum Status { 6 | Healthy, 7 | Unhealthy, 8 | Unreacheable, 9 | Removed, 10 | } 11 | 12 | impl Status { 13 | pub fn is_good(&self) -> bool { 14 | *self == Status::Healthy 15 | } 16 | } 17 | 18 | #[derive(Debug)] 19 | pub struct Report { 20 | pub url: Url, 21 | pub status: Status, 22 | pub still: bool, 23 | pub reason: String, 24 | } 25 | 26 | #[derive(Debug, Clone, Serialize, Deserialize)] 27 | pub struct UrlValue { 28 | #[serde(skip_serializing_if = "Option::is_none")] 29 | pub url: Option, 30 | 31 | pub status: Status, 32 | 33 | #[serde(default, skip_serializing_if = "String::is_empty")] 34 | pub reason: String, 35 | 36 | /// This is the client custom data 37 | pub data: serde_json::Value, 38 | } 39 | --------------------------------------------------------------------------------