├── .circleci └── config.yml ├── .gitignore ├── .rustup ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── Makefile ├── README.md ├── Rocket.toml ├── ci-speed.png ├── docker-compose.yml ├── env.sh ├── migrations ├── .gitkeep ├── 00000000000000_diesel_initial_setup │ ├── down.sql │ └── up.sql └── 2017-10-14-194709_create_post │ ├── down.sql │ └── up.sql ├── src ├── main.rs ├── models.rs ├── pool.rs ├── routes.rs └── schema.rs └── test.sh /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | docker_login: &docker_login 4 | run: 5 | name: authentication 6 | command: | 7 | docker --version 8 | docker-compose --version 9 | docker login -u "$DOCKER_USER" -p "$DOCKER_PASS" 10 | 11 | postgres_env: &postgres_env 12 | environment: 13 | # The defined vars the postgres containers use 14 | - POSTGRES_USER: clux 15 | - POSTGRES_DB: postgres 16 | - POSTGRES_PASSWORD: foobar 17 | - POSTGRES_DB_URL: 0.0.0.0 18 | 19 | workflows: 20 | version: 2 21 | flow: 22 | jobs: 23 | - musl_build 24 | - unit_test 25 | - integration_test: 26 | requires: 27 | - musl_build 28 | - docker_push: 29 | requires: 30 | - musl_build 31 | #- integration_test 32 | filters: 33 | branches: 34 | only: 35 | - master 36 | jobs: 37 | musl_build: 38 | docker: 39 | - image: clux/muslrust:nightly 40 | working_directory: /volume 41 | steps: 42 | - checkout 43 | - run: echo 'export CACHE_VERSION="12' >> $BASH_ENV 44 | - restore_cache: 45 | keys: 46 | - cargo.registry.release-{{ .Environment.CACHE_VERSION }} 47 | - restore_cache: 48 | keys: 49 | - target.release-{{ .Environment.CACHE_VERSION }} 50 | - run: cargo build --release 51 | - save_cache: 52 | key: target.release-{{ .Environment.CACHE_VERSION }} 53 | paths: 54 | - target 55 | - save_cache: 56 | key: cargo.registry.release-{{ .Environment.CACHE_VERSION }} 57 | paths: 58 | - /root/.cargo 59 | - persist_to_workspace: 60 | root: target/x86_64-unknown-linux-musl/release/ 61 | paths: 62 | - webapp 63 | 64 | unit_test: 65 | docker: 66 | - image: clux/muslrust:nightly 67 | working_directory: /volume 68 | steps: 69 | - checkout 70 | - run: echo 'export CACHE_VERSION="12' >> $BASH_ENV 71 | - restore_cache: 72 | keys: 73 | - cargo.registry.debug-{{ .Environment.CACHE_VERSION }} 74 | - restore_cache: 75 | keys: 76 | - target.debug-{{ .Environment.CACHE_VERSION }} 77 | - run: cargo test 78 | - run: cargo doc --no-deps 79 | - save_cache: 80 | key: target.debug-{{ .Environment.CACHE_VERSION }} 81 | paths: 82 | - target 83 | - save_cache: 84 | key: cargo.registry.debug-{{ .Environment.CACHE_VERSION }} 85 | paths: 86 | - /root/.cargo 87 | 88 | integration_test: 89 | machine: 90 | enabled: true 91 | docker_layer_caching: true 92 | <<: *postgres_env 93 | steps: 94 | - checkout 95 | - attach_workspace: 96 | at: . 97 | - run: make compose 98 | - run: make test 99 | - run: 100 | name: Debug 101 | when: on_fail 102 | command: docker-compose logs 103 | 104 | docker_push: 105 | machine: 106 | enabled: true 107 | docker_layer_caching: true 108 | steps: 109 | - checkout 110 | - attach_workspace: 111 | at: . 112 | - <<: *docker_login 113 | - run: make tag-latest 114 | - run: make tag-semver 115 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | **/*.rs.bk 3 | /target/ 4 | **/*.rs.bk 5 | webapp 6 | -------------------------------------------------------------------------------- /.rustup: -------------------------------------------------------------------------------- 1 | nightly-2018-10-10 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "antidote" 3 | version = "1.0.0" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "arrayvec" 8 | version = "0.4.7" 9 | source = "registry+https://github.com/rust-lang/crates.io-index" 10 | dependencies = [ 11 | "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 12 | ] 13 | 14 | [[package]] 15 | name = "base64" 16 | version = "0.6.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | dependencies = [ 19 | "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 20 | "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 21 | ] 22 | 23 | [[package]] 24 | name = "base64" 25 | version = "0.9.3" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | dependencies = [ 28 | "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 29 | "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 30 | ] 31 | 32 | [[package]] 33 | name = "bitflags" 34 | version = "1.0.4" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | 37 | [[package]] 38 | name = "byteorder" 39 | version = "1.2.6" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | 42 | [[package]] 43 | name = "cfg-if" 44 | version = "0.1.5" 45 | source = "registry+https://github.com/rust-lang/crates.io-index" 46 | 47 | [[package]] 48 | name = "cookie" 49 | version = "0.9.2" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | dependencies = [ 52 | "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 53 | "ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 54 | "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 55 | "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 56 | ] 57 | 58 | [[package]] 59 | name = "crossbeam-deque" 60 | version = "0.2.0" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | dependencies = [ 63 | "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 64 | "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 65 | ] 66 | 67 | [[package]] 68 | name = "crossbeam-epoch" 69 | version = "0.3.1" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | dependencies = [ 72 | "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", 73 | "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 74 | "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 75 | "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 76 | "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 77 | "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 78 | "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 79 | ] 80 | 81 | [[package]] 82 | name = "crossbeam-utils" 83 | version = "0.2.2" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | dependencies = [ 86 | "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 87 | ] 88 | 89 | [[package]] 90 | name = "diesel" 91 | version = "1.3.3" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | dependencies = [ 94 | "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 95 | "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 96 | "diesel_derives 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 97 | "pq-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 98 | ] 99 | 100 | [[package]] 101 | name = "diesel_derives" 102 | version = "1.3.0" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | dependencies = [ 105 | "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 106 | "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 107 | "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", 108 | ] 109 | 110 | [[package]] 111 | name = "diesel_migrations" 112 | version = "1.3.0" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | dependencies = [ 115 | "migrations_internals 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 116 | "migrations_macros 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 117 | ] 118 | 119 | [[package]] 120 | name = "gcc" 121 | version = "0.3.55" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | 124 | [[package]] 125 | name = "httparse" 126 | version = "1.3.3" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | 129 | [[package]] 130 | name = "hyper" 131 | version = "0.10.13" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | dependencies = [ 134 | "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 135 | "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 136 | "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 137 | "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 138 | "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 139 | "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 140 | "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 141 | "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 142 | "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 143 | "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 144 | "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 145 | ] 146 | 147 | [[package]] 148 | name = "idna" 149 | version = "0.1.5" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | dependencies = [ 152 | "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 153 | "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 154 | "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 155 | ] 156 | 157 | [[package]] 158 | name = "isatty" 159 | version = "0.1.9" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | dependencies = [ 162 | "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 163 | "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", 164 | "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 165 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 166 | ] 167 | 168 | [[package]] 169 | name = "itoa" 170 | version = "0.4.3" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | 173 | [[package]] 174 | name = "language-tags" 175 | version = "0.2.2" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | 178 | [[package]] 179 | name = "lazy_static" 180 | version = "0.2.11" 181 | source = "registry+https://github.com/rust-lang/crates.io-index" 182 | 183 | [[package]] 184 | name = "lazy_static" 185 | version = "1.1.0" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | dependencies = [ 188 | "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 189 | ] 190 | 191 | [[package]] 192 | name = "libc" 193 | version = "0.2.43" 194 | source = "registry+https://github.com/rust-lang/crates.io-index" 195 | 196 | [[package]] 197 | name = "log" 198 | version = "0.3.9" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | dependencies = [ 201 | "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", 202 | ] 203 | 204 | [[package]] 205 | name = "log" 206 | version = "0.4.5" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | dependencies = [ 209 | "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 210 | ] 211 | 212 | [[package]] 213 | name = "matches" 214 | version = "0.1.8" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | 217 | [[package]] 218 | name = "memchr" 219 | version = "2.1.0" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | dependencies = [ 222 | "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 223 | "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", 224 | "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 225 | ] 226 | 227 | [[package]] 228 | name = "memoffset" 229 | version = "0.2.1" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | 232 | [[package]] 233 | name = "migrations_internals" 234 | version = "1.3.0" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | dependencies = [ 237 | "diesel 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 238 | ] 239 | 240 | [[package]] 241 | name = "migrations_macros" 242 | version = "1.3.0" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | dependencies = [ 245 | "migrations_internals 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 246 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", 247 | "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", 248 | ] 249 | 250 | [[package]] 251 | name = "mime" 252 | version = "0.2.6" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | dependencies = [ 255 | "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 256 | ] 257 | 258 | [[package]] 259 | name = "nodrop" 260 | version = "0.1.12" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | 263 | [[package]] 264 | name = "num_cpus" 265 | version = "1.8.0" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | dependencies = [ 268 | "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", 269 | ] 270 | 271 | [[package]] 272 | name = "ordermap" 273 | version = "0.2.13" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | 276 | [[package]] 277 | name = "pear" 278 | version = "0.0.20" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | 281 | [[package]] 282 | name = "pear_codegen" 283 | version = "0.0.20" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | dependencies = [ 286 | "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 287 | "yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 288 | ] 289 | 290 | [[package]] 291 | name = "percent-encoding" 292 | version = "1.0.1" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | 295 | [[package]] 296 | name = "pq-sys" 297 | version = "0.4.6" 298 | source = "registry+https://github.com/rust-lang/crates.io-index" 299 | dependencies = [ 300 | "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 301 | ] 302 | 303 | [[package]] 304 | name = "proc-macro2" 305 | version = "0.3.8" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | dependencies = [ 308 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 309 | ] 310 | 311 | [[package]] 312 | name = "proc-macro2" 313 | version = "0.4.20" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | dependencies = [ 316 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 317 | ] 318 | 319 | [[package]] 320 | name = "quote" 321 | version = "0.3.15" 322 | source = "registry+https://github.com/rust-lang/crates.io-index" 323 | 324 | [[package]] 325 | name = "quote" 326 | version = "0.5.2" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | dependencies = [ 329 | "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 330 | ] 331 | 332 | [[package]] 333 | name = "quote" 334 | version = "0.6.8" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | dependencies = [ 337 | "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", 338 | ] 339 | 340 | [[package]] 341 | name = "r2d2" 342 | version = "0.8.2" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | dependencies = [ 345 | "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 346 | "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", 347 | "scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 348 | ] 349 | 350 | [[package]] 351 | name = "r2d2-diesel" 352 | version = "1.0.0" 353 | source = "registry+https://github.com/rust-lang/crates.io-index" 354 | dependencies = [ 355 | "diesel 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 356 | "r2d2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", 357 | ] 358 | 359 | [[package]] 360 | name = "rayon" 361 | version = "0.7.1" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | dependencies = [ 364 | "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 365 | ] 366 | 367 | [[package]] 368 | name = "rayon-core" 369 | version = "1.4.1" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | dependencies = [ 372 | "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 373 | "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 374 | "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", 375 | "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 376 | ] 377 | 378 | [[package]] 379 | name = "redox_syscall" 380 | version = "0.1.40" 381 | source = "registry+https://github.com/rust-lang/crates.io-index" 382 | 383 | [[package]] 384 | name = "ring" 385 | version = "0.11.0" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | dependencies = [ 388 | "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", 389 | "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 390 | "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", 391 | "rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 392 | "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 393 | ] 394 | 395 | [[package]] 396 | name = "rocket" 397 | version = "0.3.17" 398 | source = "registry+https://github.com/rust-lang/crates.io-index" 399 | dependencies = [ 400 | "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", 401 | "cookie 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", 402 | "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", 403 | "isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 404 | "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 405 | "memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 406 | "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 407 | "ordermap 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", 408 | "pear 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", 409 | "pear_codegen 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", 410 | "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 411 | "state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 412 | "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 413 | "toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 414 | "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 415 | "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 416 | "yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 417 | ] 418 | 419 | [[package]] 420 | name = "rocket_codegen" 421 | version = "0.3.17" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | dependencies = [ 424 | "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 425 | "rocket 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", 426 | "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 427 | "yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 428 | ] 429 | 430 | [[package]] 431 | name = "rocket_contrib" 432 | version = "0.3.17" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | dependencies = [ 435 | "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 436 | "rocket 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", 437 | "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", 438 | "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", 439 | ] 440 | 441 | [[package]] 442 | name = "ryu" 443 | version = "0.2.6" 444 | source = "registry+https://github.com/rust-lang/crates.io-index" 445 | 446 | [[package]] 447 | name = "safemem" 448 | version = "0.2.0" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | 451 | [[package]] 452 | name = "safemem" 453 | version = "0.3.0" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | 456 | [[package]] 457 | name = "scheduled-thread-pool" 458 | version = "0.2.0" 459 | source = "registry+https://github.com/rust-lang/crates.io-index" 460 | dependencies = [ 461 | "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 462 | ] 463 | 464 | [[package]] 465 | name = "scopeguard" 466 | version = "0.3.3" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | 469 | [[package]] 470 | name = "serde" 471 | version = "1.0.79" 472 | source = "registry+https://github.com/rust-lang/crates.io-index" 473 | 474 | [[package]] 475 | name = "serde_derive" 476 | version = "1.0.79" 477 | source = "registry+https://github.com/rust-lang/crates.io-index" 478 | dependencies = [ 479 | "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", 480 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", 481 | "syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)", 482 | ] 483 | 484 | [[package]] 485 | name = "serde_json" 486 | version = "1.0.32" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | dependencies = [ 489 | "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 490 | "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 491 | "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", 492 | ] 493 | 494 | [[package]] 495 | name = "smallvec" 496 | version = "0.6.5" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | dependencies = [ 499 | "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 500 | ] 501 | 502 | [[package]] 503 | name = "state" 504 | version = "0.4.1" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | 507 | [[package]] 508 | name = "syn" 509 | version = "0.11.11" 510 | source = "registry+https://github.com/rust-lang/crates.io-index" 511 | dependencies = [ 512 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", 513 | "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", 514 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 515 | ] 516 | 517 | [[package]] 518 | name = "syn" 519 | version = "0.13.11" 520 | source = "registry+https://github.com/rust-lang/crates.io-index" 521 | dependencies = [ 522 | "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 523 | "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 524 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 525 | ] 526 | 527 | [[package]] 528 | name = "syn" 529 | version = "0.15.9" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | dependencies = [ 532 | "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", 533 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", 534 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 535 | ] 536 | 537 | [[package]] 538 | name = "synom" 539 | version = "0.11.3" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | dependencies = [ 542 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 543 | ] 544 | 545 | [[package]] 546 | name = "time" 547 | version = "0.1.40" 548 | source = "registry+https://github.com/rust-lang/crates.io-index" 549 | dependencies = [ 550 | "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", 551 | "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 552 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 553 | ] 554 | 555 | [[package]] 556 | name = "toml" 557 | version = "0.4.8" 558 | source = "registry+https://github.com/rust-lang/crates.io-index" 559 | dependencies = [ 560 | "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", 561 | ] 562 | 563 | [[package]] 564 | name = "traitobject" 565 | version = "0.1.0" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | 568 | [[package]] 569 | name = "typeable" 570 | version = "0.1.2" 571 | source = "registry+https://github.com/rust-lang/crates.io-index" 572 | 573 | [[package]] 574 | name = "unicase" 575 | version = "1.4.2" 576 | source = "registry+https://github.com/rust-lang/crates.io-index" 577 | dependencies = [ 578 | "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 579 | ] 580 | 581 | [[package]] 582 | name = "unicode-bidi" 583 | version = "0.3.4" 584 | source = "registry+https://github.com/rust-lang/crates.io-index" 585 | dependencies = [ 586 | "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 587 | ] 588 | 589 | [[package]] 590 | name = "unicode-normalization" 591 | version = "0.1.7" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | 594 | [[package]] 595 | name = "unicode-xid" 596 | version = "0.0.4" 597 | source = "registry+https://github.com/rust-lang/crates.io-index" 598 | 599 | [[package]] 600 | name = "unicode-xid" 601 | version = "0.1.0" 602 | source = "registry+https://github.com/rust-lang/crates.io-index" 603 | 604 | [[package]] 605 | name = "unreachable" 606 | version = "1.0.0" 607 | source = "registry+https://github.com/rust-lang/crates.io-index" 608 | dependencies = [ 609 | "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 610 | ] 611 | 612 | [[package]] 613 | name = "untrusted" 614 | version = "0.5.1" 615 | source = "registry+https://github.com/rust-lang/crates.io-index" 616 | 617 | [[package]] 618 | name = "url" 619 | version = "1.7.1" 620 | source = "registry+https://github.com/rust-lang/crates.io-index" 621 | dependencies = [ 622 | "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 623 | "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 624 | "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 625 | ] 626 | 627 | [[package]] 628 | name = "vcpkg" 629 | version = "0.2.6" 630 | source = "registry+https://github.com/rust-lang/crates.io-index" 631 | 632 | [[package]] 633 | name = "version_check" 634 | version = "0.1.5" 635 | source = "registry+https://github.com/rust-lang/crates.io-index" 636 | 637 | [[package]] 638 | name = "void" 639 | version = "1.0.2" 640 | source = "registry+https://github.com/rust-lang/crates.io-index" 641 | 642 | [[package]] 643 | name = "webapp" 644 | version = "0.2.0" 645 | dependencies = [ 646 | "diesel 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 647 | "diesel_migrations 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 648 | "r2d2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", 649 | "r2d2-diesel 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 650 | "rocket 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", 651 | "rocket_codegen 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", 652 | "rocket_contrib 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", 653 | "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", 654 | "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", 655 | "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", 656 | ] 657 | 658 | [[package]] 659 | name = "winapi" 660 | version = "0.3.6" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | dependencies = [ 663 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 664 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 665 | ] 666 | 667 | [[package]] 668 | name = "winapi-i686-pc-windows-gnu" 669 | version = "0.4.0" 670 | source = "registry+https://github.com/rust-lang/crates.io-index" 671 | 672 | [[package]] 673 | name = "winapi-x86_64-pc-windows-gnu" 674 | version = "0.4.0" 675 | source = "registry+https://github.com/rust-lang/crates.io-index" 676 | 677 | [[package]] 678 | name = "yansi" 679 | version = "0.4.0" 680 | source = "registry+https://github.com/rust-lang/crates.io-index" 681 | 682 | [metadata] 683 | "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" 684 | "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" 685 | "checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" 686 | "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" 687 | "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" 688 | "checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781" 689 | "checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" 690 | "checksum cookie 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "477eb650753e319be2ae77ec368a58c638f9f0c4d941c39bad95e950fb1d1d0d" 691 | "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" 692 | "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" 693 | "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" 694 | "checksum diesel 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "164080ac16a4d1d80a50f0a623e4ddef41cb2779eee85bcc76907d340dfc98cc" 695 | "checksum diesel_derives 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03bcaf77491f53e400d5ee3bdd57142ea4e1c47fe9217b3361ff9a76ca0e3d37" 696 | "checksum diesel_migrations 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b42c35d1ce9e8d57a3e7001b4127f2bc1b073a89708bb7019f5be27c991c28" 697 | "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" 698 | "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" 699 | "checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2" 700 | "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" 701 | "checksum isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e31a8281fc93ec9693494da65fbf28c0c2aa60a2eaec25dc58e2f31952e95edc" 702 | "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" 703 | "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" 704 | "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" 705 | "checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" 706 | "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" 707 | "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" 708 | "checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f" 709 | "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" 710 | "checksum memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b3629fe9fdbff6daa6c33b90f7c08355c1aca05a3d01fa8063b822fcf185f3b" 711 | "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" 712 | "checksum migrations_internals 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8cf7c8c4f83fa9f47440c0b4af99973502de55e6e7b875f693bd263e03f93e7e" 713 | "checksum migrations_macros 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79f12499ef7353bdeca2d081bc61edd8351dac09a33af845952009b5a3d68c1a" 714 | "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" 715 | "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" 716 | "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" 717 | "checksum ordermap 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b81cf3b8cb96aa0e73bbedfcdc9708d09fec2854ba8d474be4e6f666d7379e8b" 718 | "checksum pear 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "353fe88ff7a430c0f39ca4ec19e1f8fa0062f696370e8df3080ac40139a63301" 719 | "checksum pear_codegen 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0f3ef1db2d855e0c00fad8e5a8216a70df6d9c1c7f7a7ac9f1cf50675142b7" 720 | "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" 721 | "checksum pq-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac25eee5a0582f45a67e837e350d784e7003bd29a5f460796772061ca49ffda" 722 | "checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" 723 | "checksum proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7b7eaaa90b4a90a932a9ea6666c95a389e424eff347f0f793979289429feee" 724 | "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" 725 | "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" 726 | "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" 727 | "checksum r2d2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f9078ca6a8a5568ed142083bb2f7dc9295b69d16f867ddcc9849e51b17d8db46" 728 | "checksum r2d2-diesel 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9c29bad92da76d02bc2c020452ebc3a3fe6fa74cfab91e711c43116e4fb1a3" 729 | "checksum rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a77c51c07654ddd93f6cb543c7a849863b03abc7e82591afda6dc8ad4ac3ac4a" 730 | "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" 731 | "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" 732 | "checksum ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2a6dc7fc06a05e6de183c5b97058582e9da2de0c136eafe49609769c507724" 733 | "checksum rocket 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "a61d746c68f1d357f6e011985570474c4af368aa81900320074098d34ed0c64e" 734 | "checksum rocket_codegen 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7873d65adfa3e440ac373a28240341853da170913aad7e4207c0198389e5d0e9" 735 | "checksum rocket_contrib 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2348e3b2458e173203f1e51f3b2e00495a092b70bd9506d2ce2ac64e129d14" 736 | "checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" 737 | "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" 738 | "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" 739 | "checksum scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a2ff3fc5223829be817806c6441279c676e454cc7da608faf03b0ccc09d3889" 740 | "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" 741 | "checksum serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "84257ccd054dc351472528c8587b4de2dbf0dc0fe2e634030c1a90bfdacebaa9" 742 | "checksum serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "31569d901045afbff7a9479f793177fe9259819aff10ab4f89ef69bbc5f567fe" 743 | "checksum serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "43344e7ce05d0d8280c5940cabb4964bea626aa58b1ec0e8c73fa2a8512a38ce" 744 | "checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" 745 | "checksum state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7345c971d1ef21ffdbd103a75990a15eb03604fc8b8852ca8cb418ee1a099028" 746 | "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" 747 | "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" 748 | "checksum syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b10ee269228fb723234fce98e9aac0eaed2bd5f1ad2f6930e8d5b93f04445a1a" 749 | "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" 750 | "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" 751 | "checksum toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4a2ecc31b0351ea18b3fe11274b8db6e4d82bce861bbb22e6dbed40417902c65" 752 | "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" 753 | "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" 754 | "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" 755 | "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" 756 | "checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" 757 | "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" 758 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 759 | "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" 760 | "checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" 761 | "checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" 762 | "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" 763 | "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" 764 | "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 765 | "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" 766 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 767 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 768 | "checksum yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d60c3b48c9cdec42fb06b3b84b5b087405e1fa1c644a1af3930e4dfafe93de48" 769 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["clux"] 3 | name = "webapp" 4 | version = "0.2.0" 5 | 6 | [[bin]] 7 | doc = false 8 | name = "webapp" 9 | path = "src/main.rs" 10 | 11 | [dependencies] 12 | diesel_migrations = "1.3.0" 13 | r2d2 = "0.8.2" 14 | r2d2-diesel = "1.0.0" 15 | rocket = "0.3.3" 16 | rocket_codegen = "0.3.6" 17 | rocket_contrib = "0.3.6" 18 | serde = "1.0.27" 19 | serde_derive = "1.0.27" 20 | serde_json = "1.0.10" 21 | 22 | [dependencies.diesel] 23 | features = ["postgres"] 24 | version = "1.1.1" 25 | 26 | 27 | [profile.release] 28 | lto = true 29 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:latest 2 | RUN apk --no-cache add ca-certificates 3 | COPY ./webapp /bin/ 4 | COPY ./Rocket.toml . 5 | ENV ROCKET_ENV development 6 | EXPOSE 8000 7 | ENTRYPOINT ["/bin/webapp"] 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | NAME=webapp-rs 2 | VERSION=$(shell git rev-parse HEAD) 3 | SEMVER_VERSION=$(shell grep version Cargo.toml | awk -F"\"" '{print $$2}' | head -n 1) 4 | REPO=clux 5 | SHELL := /bin/bash 6 | 7 | has_secrets: 8 | @[[ $$POSTGRES_DB ]] || (echo "source env.sh first"; exit 2) 9 | 10 | no_postgres: 11 | @[ -z "$$(docker ps -q -f ancestor="postgres:9.6")" ] || (echo "db running"; exit 2) 12 | has_postgres: 13 | @[ -n "$$(docker ps -q -f ancestor="postgres:9.6")" ] || (echo "db not running"; exit 2) 14 | 15 | db: has_secrets no_postgres 16 | @echo "Starting postgres container" 17 | docker run --rm -d \ 18 | -p "5432:5432" \ 19 | --expose 5432 \ 20 | -e POSTGRES_DB="$$POSTGRES_DB" \ 21 | -e POSTGRES_PASSWORD="$$POSTGRES_PASSWORD" \ 22 | -e POSTGRES_USER="$$POSTGRES_USER" \ 23 | -it postgres:9.6 24 | 25 | stop: 26 | @docker ps -aq | xargs -r docker rm -f 27 | @pkill webapp || true 28 | 29 | setup: 30 | cargo install diesel_cli --no-default-features --features postgres 31 | rustup override set $$(cat .rustup) 32 | 33 | test: 34 | ./test.sh 35 | 36 | compose: has_secrets 37 | docker-compose up -d db 38 | @echo "Waiting for postgres" 39 | if hash psql 2> /dev/null; then \ 40 | until [[ $$RETRIES -ge 10 ]] || PGPASSWORD=$${POSTGRES_PASSWORD} psql -h $${POSTGRES_DB_URL} -U $$POSTGRES_USER -d $${POSTGRES_DB} -c "select 1" > /dev/null ; do \ 41 | echo "$$((RETRIES++))"; \ 42 | sleep 1; \ 43 | done \ 44 | else \ 45 | sleep 10 ;\ 46 | fi 47 | docker-compose up -d web 48 | docker-compose logs web 49 | 50 | run: has_secrets has_postgres 51 | cargo run 52 | 53 | compile: 54 | docker run --rm \ 55 | -v cargo-cache:/root/.cargo \ 56 | -v $$PWD:/volume \ 57 | -w /volume \ 58 | -it clux/muslrust:nightly \ 59 | cargo build --release 60 | sudo chown $$USER:$$USER -R target 61 | strip target/x86_64-unknown-linux-musl/release/webapp 62 | mv target/x86_64-unknown-linux-musl/release/webapp . 63 | 64 | build: 65 | @echo "Reusing built binary in current directory from make compile" 66 | @ls -lah ./webapp 67 | docker build -t $(REPO)/$(NAME):$(VERSION) . 68 | 69 | tag-latest: build 70 | docker tag $(REPO)/$(NAME):$(VERSION) $(REPO)/$(NAME):latest 71 | docker push $(REPO)/$(NAME):latest 72 | 73 | tag-semver: build 74 | if curl -sSL https://registry.hub.docker.com/v1/repositories/$(REPO)/$(NAME)/tags | jq -r ".[].name" | grep -q $(SEMVER_VERSION); then \ 75 | echo "Tag $(SEMVER_VERSION) already exists - not publishing" ; \ 76 | else \ 77 | docker tag $(REPO)/$(NAME):$(VERSION) $(REPO)/$(NAME):$(SEMVER_VERSION) ; \ 78 | docker push $(REPO)/$(NAME):$(SEMVER_VERSION) ; \ 79 | fi 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rust microservice setup with rocket and postgres diesel 2 | [![CircleCI](https://circleci.com/gh/clux/webapp-rs/tree/master.svg?style=shield)](https://circleci.com/gh/clux/webapp-rs/tree/master) 3 | [![docker pulls](https://img.shields.io/docker/pulls/clux/webapp-rs.svg)]( 4 | https://hub.docker.com/r/clux/webapp-rs/) 5 | [![docker image info](https://images.microbadger.com/badges/image/clux/webapp-rs.svg)](http://microbadger.com/images/clux/webapp-rs) 6 | [![docker tag](https://images.microbadger.com/badges/version/clux/webapp-rs.svg)](https://hub.docker.com/r/clux/webapp-rs/tags/) 7 | 8 | A JSON API microservice with database backing all running from a [<7MB container](./Dockerfile). 9 | 10 | ## Developing Easily 11 | Install dependencies, setup `rustup` env, then start a dev postgres with credentials: 12 | 13 | ```sh 14 | sudo pacman -S postgresql-libs # or distro equivalent 15 | make setup 16 | source env.sh 17 | make db # runs postgres in a container 18 | ``` 19 | 20 | then run and test in parallel with: 21 | 22 | ```sh 23 | make run 24 | make test 25 | ``` 26 | 27 | This workflow is the fastest as it does not require waiting for docker builds, nor deal with a local installations of postgres. You just need to install `docker`, `postgresql-libs` to manage migrations in a container, and run against it with what's essentially `cargo run`. 28 | 29 | ## Using docker-compose 30 | You can develop and test production equivalents without rust, without local postgres, without postgres libs, and without diesel-cli locally. 31 | 32 | This is the production equivalent flow: 33 | 34 | ```sh 35 | # Build the app with clux/muslrust 36 | make compile 37 | # Put the built binary into a container and compose with a db. 38 | # Then, once the db is up, use clux/diesel-cli to run migrations: 39 | source env.sh 40 | make compose 41 | # Verify 42 | make test 43 | ``` 44 | 45 | ## CI 46 | Runs unit tests, musl build, intergration tests with docker compose and pushes to docker hub, all in <2 minutes (using a cache of rust target + registy directories). 47 | 48 | ![Continuous Integration layout and timing](./ci-speed.png) 49 | 50 | ## Using Kubernetes 51 | Port to your templated wall of yaml of choice if you know what you are doing. 52 | 53 | ## Caveats 54 | **NB:** With `docker-compose` our migration would have to wait for postgres to initialize, either via a sleep or a `psql` "select 1" attempt. See `make compose` for more info. 55 | 56 | **NB:** The compile step is required before any build step, so `docker-compose up` would fail without it. It's possible to fix this by using a multistep docker build for the app, but it makes local build caching harder. 57 | -------------------------------------------------------------------------------- /Rocket.toml: -------------------------------------------------------------------------------- 1 | [development] 2 | address = "0.0.0.0" 3 | port = 8000 4 | workers = 4 5 | log = "normal" 6 | 7 | [staging] 8 | address = "0.0.0.0" 9 | port = 8000 10 | workers = 4 11 | log = "normal" 12 | 13 | [production] 14 | address = "0.0.0.0" 15 | port = 8000 16 | workers = 4 17 | log = "critical" 18 | -------------------------------------------------------------------------------- /ci-speed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clux/webapp-rs/17e0cbee6f87f85d8605fe50fc99d3a1ad684b0b/ci-speed.png -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | db: 5 | environment: 6 | POSTGRES_USER: "${POSTGRES_USER}" 7 | POSTGRES_DB: "${POSTGRES_DB}" 8 | POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}" 9 | image: postgres:9.6-alpine 10 | ports: 11 | - "5432:5432" 12 | web: 13 | restart: on-failure 14 | depends_on: 15 | - db 16 | build: . 17 | environment: 18 | ROCKET_ENV: development 19 | DATABASE_URL: "postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db/${POSTGRES_DB}" 20 | ports: 21 | - "8000:8000" 22 | -------------------------------------------------------------------------------- /env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export POSTGRES_USER=clux 4 | export POSTGRES_PASSWORD=foobar 5 | export POSTGRES_DB_URL=0.0.0.0 6 | export POSTGRES_DB=postgres 7 | export DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_DB_URL}/${POSTGRES_DB}" 8 | 9 | # We need to bind to 0.0.0.0 inside the container 10 | # ROCKET_ENV production already forces this in the image normally 11 | export ROCKET_ADDRESS=0.0.0.0 12 | -------------------------------------------------------------------------------- /migrations/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clux/webapp-rs/17e0cbee6f87f85d8605fe50fc99d3a1ad684b0b/migrations/.gitkeep -------------------------------------------------------------------------------- /migrations/00000000000000_diesel_initial_setup/down.sql: -------------------------------------------------------------------------------- 1 | DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass); 2 | DROP FUNCTION IF EXISTS diesel_set_updated_at(); 3 | -------------------------------------------------------------------------------- /migrations/00000000000000_diesel_initial_setup/up.sql: -------------------------------------------------------------------------------- 1 | -- This file was automatically created by Diesel to setup helper functions 2 | -- and other internal bookkeeping. This file is safe to edit, any future 3 | -- changes will be added to existing projects as new migrations. 4 | 5 | 6 | 7 | 8 | -- Sets up a trigger for the given table to automatically set a column called 9 | -- `updated_at` whenever the row is modified (unless `updated_at` was included 10 | -- in the modified columns) 11 | -- 12 | -- # Example 13 | -- 14 | -- ```sql 15 | -- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW()); 16 | -- 17 | -- SELECT diesel_manage_updated_at('users'); 18 | -- ``` 19 | CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$ 20 | BEGIN 21 | EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s 22 | FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl); 23 | END; 24 | $$ LANGUAGE plpgsql; 25 | 26 | CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$ 27 | BEGIN 28 | IF ( 29 | NEW IS DISTINCT FROM OLD AND 30 | NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at 31 | ) THEN 32 | NEW.updated_at := current_timestamp; 33 | END IF; 34 | RETURN NEW; 35 | END; 36 | $$ LANGUAGE plpgsql; 37 | -------------------------------------------------------------------------------- /migrations/2017-10-14-194709_create_post/down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE posts 2 | -------------------------------------------------------------------------------- /migrations/2017-10-14-194709_create_post/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE posts ( 2 | id SERIAL PRIMARY KEY, 3 | title VARCHAR NOT NULL, 4 | body TEXT NOT NULL, 5 | published BOOLEAN NOT NULL DEFAULT 'f' 6 | ) 7 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(plugin)] 2 | #![plugin(rocket_codegen)] 3 | extern crate rocket; 4 | extern crate rocket_contrib; 5 | 6 | #[macro_use] 7 | extern crate diesel; 8 | #[macro_use] 9 | extern crate diesel_migrations; 10 | embed_migrations!("./migrations"); 11 | 12 | extern crate serde; 13 | extern crate serde_json; 14 | #[macro_use] 15 | extern crate serde_derive; 16 | 17 | extern crate r2d2_diesel; 18 | extern crate r2d2; 19 | 20 | mod schema; 21 | mod models; 22 | mod pool; 23 | mod routes; 24 | 25 | use self::routes::*; 26 | 27 | // ---------------------------------------------------------------------------- 28 | 29 | fn main() { 30 | let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set"); 31 | let p = pool::init(&database_url); 32 | embedded_migrations::run(&*p.clone().get().expect("connection instance")) 33 | .expect("Could run migrations"); 34 | rocket::ignite() 35 | .manage(p) 36 | .mount("/", routes![health, get_posts, get_post, create_post, delete_post, update_post]) 37 | .launch(); 38 | } 39 | -------------------------------------------------------------------------------- /src/models.rs: -------------------------------------------------------------------------------- 1 | use schema::posts; 2 | 3 | #[derive(Queryable, Serialize)] 4 | pub struct Post { 5 | pub id: i32, 6 | pub title: String, 7 | pub body: String, 8 | pub published: bool, 9 | } 10 | 11 | // apparently this can be done without heap storage, but lifetimes spread far.. 12 | #[derive(Insertable, Deserialize)] 13 | #[table_name="posts"] 14 | pub struct NewPost { 15 | pub title: String, 16 | pub body: String, 17 | } 18 | -------------------------------------------------------------------------------- /src/pool.rs: -------------------------------------------------------------------------------- 1 | use diesel; 2 | use r2d2; 3 | 4 | // for request guard 5 | use std::ops::Deref; 6 | use rocket::http::Status; 7 | use rocket::request::{self, FromRequest}; 8 | use rocket::{Request, State, Outcome}; 9 | 10 | // Master database selector (all others are features in Cargo.toml) 11 | type DbType = diesel::pg::PgConnection; 12 | 13 | use r2d2_diesel::ConnectionManager; 14 | type Pool = r2d2::Pool>; 15 | type PoolConn = r2d2::PooledConnection>; 16 | 17 | // Connection request guard type: a wrapper around an r2d2 pooled connection. 18 | // NB: cannot implement FromRequest on PoolConn directly, so this is necessary 19 | pub struct DbConn(pub PoolConn); 20 | 21 | // For the convenience of using an &DbConn as a &DbType. 22 | impl Deref for DbConn { 23 | type Target = DbType; 24 | fn deref(&self) -> &Self::Target { &self.0 } 25 | } 26 | 27 | /// Attempts to retrieve a single connection from the managed database pool. If 28 | /// no pool is currently managed, fails with an `InternalServerError` status. If 29 | /// no connections are available, fails with a `ServiceUnavailable` status. 30 | impl<'a, 'r> FromRequest<'a, 'r> for DbConn { 31 | type Error = (); 32 | 33 | fn from_request(request: &'a Request<'r>) -> request::Outcome { 34 | let pool = request.guard::>()?; 35 | match pool.get() { 36 | Ok(conn) => Outcome::Success(DbConn(conn)), 37 | Err(_) => Outcome::Failure((Status::ServiceUnavailable, ())) 38 | } 39 | } 40 | } 41 | 42 | /// Initializes a database pool via r2d2 43 | pub fn init(database_url: &str) -> Pool { 44 | let manager = ConnectionManager::::new(database_url); 45 | r2d2::Pool::new(manager).expect("db pool") 46 | } 47 | -------------------------------------------------------------------------------- /src/routes.rs: -------------------------------------------------------------------------------- 1 | use diesel; 2 | use rocket_contrib::Json; 3 | use diesel::prelude::*; 4 | 5 | use super::pool::DbConn; 6 | use super::models::*; 7 | use super::schema::posts::dsl::*; 8 | use super::schema::posts; 9 | 10 | // ---------------------------------------------------------------------------- 11 | // crud routes 12 | // ---------------------------------------------------------------------------- 13 | 14 | #[get("/posts")] 15 | pub fn get_posts(conn: DbConn) -> QueryResult>> { 16 | posts.filter(published.eq(true)) 17 | .order(id.desc()) 18 | .limit(5) 19 | .load::(&*conn) 20 | .map(|xs| Json(xs)) 21 | } 22 | 23 | #[get("/posts/")] 24 | pub fn get_post(postid: i32, conn: DbConn) -> QueryResult> { 25 | posts.find(postid) 26 | .get_result::(&*conn) 27 | .map(|x| Json(x)) 28 | } 29 | 30 | #[put("/posts/")] 31 | pub fn update_post(postid: i32, conn: DbConn) -> QueryResult> { 32 | diesel::update(posts.find(postid)) 33 | .set(published.eq(true)) 34 | .get_result::(&*conn) 35 | .map(|x| Json(x)) 36 | } 37 | 38 | #[post("/posts", data="")] 39 | pub fn create_post(newpost: Json, conn: DbConn) -> QueryResult> { 40 | diesel::insert_into(posts::table) 41 | .values(&newpost.into_inner()) 42 | .get_result(&*conn) 43 | .map(|x| Json(x)) 44 | } 45 | 46 | #[delete("/posts/")] 47 | pub fn delete_post(postid: i32, conn: DbConn) -> QueryResult> { 48 | diesel::delete(posts.filter(id.eq(postid))) 49 | .execute(&*conn) 50 | .map(|x| Json(x)) 51 | } 52 | 53 | #[get("/health")] 54 | pub fn health() -> Json<()> { 55 | Json(()) 56 | } 57 | -------------------------------------------------------------------------------- /src/schema.rs: -------------------------------------------------------------------------------- 1 | table! { 2 | posts (id) { 3 | id -> Int4, 4 | title -> Varchar, 5 | body -> Text, 6 | published -> Bool, 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | res=$(curl -s -X POST http://0.0.0.0:8000/posts -H "Content-Type: application/json" \ 5 | -d '{"title": "my life", "body": "memes"}') 6 | 7 | lastid="$(echo "${res}" | jq ".id")" 8 | 9 | # can get it individually 10 | curl -s -X GET "http://0.0.0.0:8000/posts/${lastid}" 11 | 12 | # post not published yet 13 | curl -s -X GET http://0.0.0.0:8000/posts | grep -v "${lastid}" 14 | 15 | # publish 16 | curl -s -X PUT "http://0.0.0.0:8000/posts/${lastid}" 17 | 18 | # post now published 19 | curl -s -X GET http://0.0.0.0:8000/posts | grep "${lastid}" 20 | 21 | # delete post 22 | curl -s -X DELETE "http://0.0.0.0:8000/posts/${lastid}" 23 | --------------------------------------------------------------------------------