Merge branch 'develop'
commit
c6518a33b1
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# This hook checks if the commit message ends with an issue number, and if not,
|
||||
# tries to derive that number from the branch name
|
||||
|
||||
branch=`git rev-parse --abbrev-ref HEAD`
|
||||
|
||||
# This check doesn't need to run when commiting to develop/master
|
||||
[[ "$branch" =~ ^master|develop$ ]] && exit 0
|
||||
|
||||
issue_num=`echo "$branch" | grep -Po '^[0-9]+(?=-)'`
|
||||
|
||||
# Check if issue number is already present
|
||||
if ! grep -q '([0-9]\+)$' "$1"; then
|
||||
# Error out if we can't derive issue number
|
||||
[[ -z "$issue_num" ]] && {
|
||||
>&2 echo "Couldn't derive issue number from branch. Please add one manually.";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
# Append issue number, and remove all comments
|
||||
echo "[#$issue_num]" "$(cat "$1")" > "$1"
|
||||
fi
|
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# This hook lints the code, and if we're on develop or master, also forces the tests to pass.
|
||||
make lint &> /dev/null 2>&1 || {
|
||||
>&2 echo "Format check failed, use 'make lint' for more information.";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
branch=`git rev-parse --abbrev-ref HEAD`
|
||||
|
||||
# TODO should we add release branches here as well?
|
||||
if [[ "$branch" =~ ^master|develop$ ]]; then
|
||||
make test > /dev/null 2>&1 || {
|
||||
>&2 echo "Tests failed. check 'make test' for more info.";
|
||||
exit 1;
|
||||
}
|
||||
fi
|
|
@ -56,6 +56,15 @@ dependencies = [
|
|||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
|
@ -73,6 +82,12 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "base-x"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.9.3"
|
||||
|
@ -118,9 +133,9 @@ checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
|
|||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.2"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
|
@ -146,6 +161,29 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time 0.1.44",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono-tz"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2554a3155fec064362507487171dcc4edc3df60cb10f3a1fb10ed8094822b120"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"parse-zoneinfo",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.2.5"
|
||||
|
@ -155,6 +193,12 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const_fn"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.11.4"
|
||||
|
@ -168,7 +212,34 @@ dependencies = [
|
|||
"percent-encoding 2.1.0",
|
||||
"rand",
|
||||
"sha2",
|
||||
"time",
|
||||
"time 0.1.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.14.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951"
|
||||
dependencies = [
|
||||
"percent-encoding 2.1.0",
|
||||
"time 0.2.26",
|
||||
"version_check 0.9.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cookie_store"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3818dfca4b0cb5211a659bbcbb94225b7127407b2b135e650d717bfb78ab10d3"
|
||||
dependencies = [
|
||||
"cookie 0.14.4",
|
||||
"idna 0.2.2",
|
||||
"log 0.4.14",
|
||||
"publicsuffix",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"time 0.2.26",
|
||||
"url 2.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -259,6 +330,12 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "discard"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.28"
|
||||
|
@ -268,6 +345,19 @@ dependencies = [
|
|||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fej"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"chrono-tz",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"rocket",
|
||||
"rocket_contrib",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.14"
|
||||
|
@ -401,7 +491,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check 0.9.2",
|
||||
"version_check 0.9.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -498,12 +588,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2861bd27ee074e5ee891e8b539837a9430012e249d7f0ca2d795650f579c1994"
|
||||
checksum = "5dfb77c123b4e2f72a2069aeae0b4b4949cc7e966df277813fc16347e7549737"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -530,7 +621,7 @@ dependencies = [
|
|||
"log 0.3.9",
|
||||
"mime 0.2.6",
|
||||
"num_cpus",
|
||||
"time",
|
||||
"time 0.1.44",
|
||||
"traitobject",
|
||||
"typeable",
|
||||
"unicase",
|
||||
|
@ -598,9 +689,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.6.1"
|
||||
version = "1.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b"
|
||||
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
|
@ -649,9 +740,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
|||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.48"
|
||||
version = "0.3.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78"
|
||||
checksum = "dc15e39392125075f60c95ba416f5381ff6c3a948ff02ab12464715adf56c821"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
@ -686,9 +777,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.88"
|
||||
version = "0.2.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a"
|
||||
checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
|
@ -756,13 +847,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.7.9"
|
||||
version = "0.7.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5dede4e2065b3842b8b0af444119f3aa331cc7cc2dd20388bfb0f5d5a38823a"
|
||||
checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log 0.4.14",
|
||||
"miow 0.3.6",
|
||||
"miow 0.3.7",
|
||||
"ntapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
@ -793,11 +884,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.3.6"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897"
|
||||
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
|
||||
dependencies = [
|
||||
"socket2",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
|
@ -857,6 +947,25 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.0"
|
||||
|
@ -867,6 +976,12 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.0"
|
||||
|
@ -875,15 +990,15 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
|||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.32"
|
||||
version = "0.10.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "038d43985d1ddca7a9900630d8cd031b56e4794eecc2e9ea39dd17aa04399a70"
|
||||
checksum = "a61075b62a23fef5a29815de7536d940aa35ce96d18ce0cc5076272db678a577"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if 1.0.0",
|
||||
"foreign-types",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
|
@ -895,9 +1010,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
|
|||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.60"
|
||||
version = "0.9.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "921fc71883267538946025deffb622905ecad223c28efbfdef9bb59a0175f3e6"
|
||||
checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cc",
|
||||
|
@ -906,6 +1021,15 @@ dependencies = [
|
|||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parse-zoneinfo"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pear"
|
||||
version = "0.1.4"
|
||||
|
@ -924,7 +1048,7 @@ dependencies = [
|
|||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.13",
|
||||
"syn 0.15.44",
|
||||
"version_check 0.9.2",
|
||||
"version_check 0.9.3",
|
||||
"yansi",
|
||||
]
|
||||
|
||||
|
@ -957,7 +1081,7 @@ checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.63",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -995,6 +1119,12 @@ version = "0.2.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
|
@ -1013,6 +1143,16 @@ dependencies = [
|
|||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "publicsuffix"
|
||||
version = "1.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95b4ce31ff0a27d93c8de1849cf58162283752f065a90d508f1105fa6c9a213f"
|
||||
dependencies = [
|
||||
"idna 0.2.2",
|
||||
"url 2.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.13"
|
||||
|
@ -1080,6 +1220,23 @@ dependencies = [
|
|||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.3"
|
||||
|
@ -1097,6 +1254,8 @@ checksum = "bf12057f289428dbf5c591c74bf10392e4a8003f993405a902f20117019022d4"
|
|||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"bytes",
|
||||
"cookie 0.14.4",
|
||||
"cookie_store",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
|
@ -1115,6 +1274,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"time 0.2.26",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"url 2.2.1",
|
||||
|
@ -1139,9 +1299,9 @@ dependencies = [
|
|||
"rocket_codegen",
|
||||
"rocket_http",
|
||||
"state",
|
||||
"time",
|
||||
"time 0.1.44",
|
||||
"toml",
|
||||
"version_check 0.9.2",
|
||||
"version_check 0.9.3",
|
||||
"yansi",
|
||||
]
|
||||
|
||||
|
@ -1156,7 +1316,7 @@ dependencies = [
|
|||
"indexmap",
|
||||
"quote 0.6.13",
|
||||
"rocket_http",
|
||||
"version_check 0.9.2",
|
||||
"version_check 0.9.3",
|
||||
"yansi",
|
||||
]
|
||||
|
||||
|
@ -1179,25 +1339,24 @@ version = "0.4.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce364100ed7a1bf39257b69ebd014c1d5b4979b0d365d8c9ab0aa9c79645493d"
|
||||
dependencies = [
|
||||
"cookie",
|
||||
"cookie 0.11.4",
|
||||
"hyper 0.10.16",
|
||||
"indexmap",
|
||||
"pear",
|
||||
"percent-encoding 1.0.1",
|
||||
"smallvec",
|
||||
"state",
|
||||
"time",
|
||||
"time 0.1.44",
|
||||
"unicode-xid 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-api"
|
||||
version = "0.1.0"
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
dependencies = [
|
||||
"reqwest",
|
||||
"rocket",
|
||||
"rocket_contrib",
|
||||
"serde",
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1255,10 +1414,39 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.124"
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f"
|
||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
|
@ -1283,6 +1471,12 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.9.3"
|
||||
|
@ -1319,12 +1513,70 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "standback"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff"
|
||||
dependencies = [
|
||||
"version_check 0.9.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "state"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483"
|
||||
|
||||
[[package]]
|
||||
name = "stdweb"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
|
||||
dependencies = [
|
||||
"discard",
|
||||
"rustc_version",
|
||||
"stdweb-derive",
|
||||
"stdweb-internal-macros",
|
||||
"stdweb-internal-runtime",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stdweb-derive"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stdweb-internal-macros"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
|
||||
dependencies = [
|
||||
"base-x",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"sha1",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stdweb-internal-runtime"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.4.0"
|
||||
|
@ -1344,9 +1596,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.63"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd9bc7ccc2688b3344c2f48b9b546648b25ce0b20fc717ee7fa7981a8ca9717"
|
||||
checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
|
@ -1369,14 +1621,53 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.43"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
|
||||
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.2.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08a8cbfbf47955132d0202d1662f49b2423ae35862aee471f3ba4b133358f372"
|
||||
dependencies = [
|
||||
"const_fn",
|
||||
"libc",
|
||||
"standback",
|
||||
"stdweb",
|
||||
"time-macros",
|
||||
"version_check 0.9.3",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"time-macros-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-macros-impl"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"standback",
|
||||
"syn 1.0.64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.1.1"
|
||||
|
@ -1394,15 +1685,15 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.3.0"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d56477f6ed99e10225f38f9f75f872f29b8b8bd8c0b946f63345bb144e9eeda"
|
||||
checksum = "134af885d758d645f0f0505c9a8b3f9bf8a348fd822e112ab5248138348f1722"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mio 0.7.9",
|
||||
"mio 0.7.11",
|
||||
"num_cpus",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
@ -1419,9 +1710,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.6.4"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec31e5cc6b46e653cf57762f36f71d5e6386391d88a72fd6db4508f8f676fb29"
|
||||
checksum = "5143d049e85af7fbc36f5454d990e62c2df705b3589f123b71f441b6b59f443f"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
|
@ -1486,9 +1777,9 @@ checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
|
|||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.12.0"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
|
||||
checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
|
@ -1576,15 +1867,15 @@ checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
|
|||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.2"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.1"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
|
||||
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi 0.3.9",
|
||||
|
@ -1603,15 +1894,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.71"
|
||||
version = "0.2.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7"
|
||||
checksum = "8fe8f61dba8e5d645a4d8132dc7a0a66861ed5e1045d2c0ed940fab33bac0fbe"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"serde",
|
||||
|
@ -1621,24 +1912,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.71"
|
||||
version = "0.2.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b7d8b6942b8bb3a9b0e73fc79b98095a27de6fa247615e59d096754a3bc2aa8"
|
||||
checksum = "046ceba58ff062da072c7cb4ba5b22a37f00a302483f7e2a6cdc18fedbdc1fd3"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log 0.4.14",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.63",
|
||||
"syn 1.0.64",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.21"
|
||||
version = "0.4.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e67a5806118af01f0d9045915676b22aaebecf4178ae7021bc171dab0b897ab"
|
||||
checksum = "73157efb9af26fb564bb59a009afd1c7c334a44db171d280690d0c3faaec3468"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
|
@ -1648,9 +1939,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.71"
|
||||
version = "0.2.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b"
|
||||
checksum = "0ef9aa01d36cda046f797c57959ff5f3c615c9cc63997a8d545831ec7976819b"
|
||||
dependencies = [
|
||||
"quote 1.0.9",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
@ -1658,28 +1949,28 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.71"
|
||||
version = "0.2.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e"
|
||||
checksum = "96eb45c1b2ee33545a813a92dbb53856418bf7eb54ab34f7f7ff1448a5b3735d"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.63",
|
||||
"syn 1.0.64",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.71"
|
||||
version = "0.2.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1"
|
||||
checksum = "b7148f4696fb4960a346eaa60bbfb42a1ac4ebba21f750f75fc1375b098d5ffa"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.48"
|
||||
version = "0.3.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b"
|
||||
checksum = "59fe19d70f5dacc03f6e46777213facae5ac3801575d56ca6cbd4c93dcd12310"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
|
|
22
Cargo.toml
22
Cargo.toml
|
@ -1,19 +1,35 @@
|
|||
[package]
|
||||
name = "rust-api"
|
||||
name = "fej"
|
||||
version = "0.1.0"
|
||||
authors = ["Jef Roosens <roosensjef@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[lib]
|
||||
name = "fej_lib"
|
||||
src = "src/lib.rs"
|
||||
test = true
|
||||
bench = true
|
||||
doc = true
|
||||
doctest = true
|
||||
|
||||
[[bin]]
|
||||
name = "fej"
|
||||
src = "src/main.rs"
|
||||
test = false
|
||||
bench = false
|
||||
doc = false
|
||||
|
||||
[dependencies]
|
||||
rocket = "0.4.7"
|
||||
serde = "1.0.124"
|
||||
chrono = "0.4.19"
|
||||
chrono-tz = "0.5.3"
|
||||
regex = "1.4.5"
|
||||
|
||||
[dependencies.reqwest]
|
||||
version = "0.11.2"
|
||||
default-features = true
|
||||
features = ["blocking", "json"]
|
||||
features = ["blocking", "json", "cookies"]
|
||||
|
||||
[dependencies.rocket_contrib]
|
||||
version = "0.4.7"
|
||||
|
|
39
Dockerfile
39
Dockerfile
|
@ -1,18 +1,37 @@
|
|||
# syntax=docker/dockerfile:1.2
|
||||
FROM rustlang/rust:nightly AS builder
|
||||
# syntax = docker/dockerfile:1.2
|
||||
|
||||
# We use a multi-stage build to end up with a very small final image
|
||||
FROM alpine:latest AS builder
|
||||
|
||||
ENV PATH "$PATH:/root/.cargo/bin"
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Build the app
|
||||
COPY . .
|
||||
RUN --mount=type=cache,target=/usr/src/app/target cargo install --path .
|
||||
# Install build dependencies, rustup & rust's nightly build & toolchain
|
||||
RUN apk update && apk add --no-cache openssl-dev build-base curl && \
|
||||
{ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly; }
|
||||
|
||||
# Copy source code over to builder
|
||||
COPY Cargo.toml Cargo.lock ./
|
||||
COPY src/ ./src/
|
||||
|
||||
# Run the tests, don't want no broken docker image
|
||||
# And then finally, build the project
|
||||
# Thank the lords that this article exists
|
||||
# https://users.rust-lang.org/t/sigsegv-with-program-linked-against-openssl-in-an-alpine-container/52172
|
||||
# TODO add what these flags do & why they work
|
||||
# NOTE: cargo install auto-appends bin to the path
|
||||
RUN --mount=type=cache,target=/usr/src/app/target RUSTFLAGS="-C target-feature=-crt-static" cargo test && \
|
||||
RUSTFLAGS="-C target-feature=-crt-static" cargo install --path . --bin fej --root /usr/local
|
||||
|
||||
|
||||
FROM debian:buster-slim
|
||||
# Now, we create the actual image
|
||||
FROM alpine:latest
|
||||
|
||||
# Install dependencies
|
||||
RUN apt update && apt install -y openssl
|
||||
# Install some dynamic libraries needed for everything to work
|
||||
RUN apk update && apk add --no-cache openssl libgcc
|
||||
|
||||
COPY --from=builder /usr/local/cargo/bin/rust-api /usr/local/bin/rust-api
|
||||
# Copy binary over to final image
|
||||
COPY --from=builder /usr/local/bin/fej /usr/local/bin/fej
|
||||
|
||||
CMD ["rust-api"]
|
||||
CMD ["/usr/local/bin/fej"]
|
||||
|
|
20
Makefile
20
Makefile
|
@ -1,5 +1,4 @@
|
|||
IMAGE := rust_api:latest
|
||||
shell := /bin/bash
|
||||
IMAGE := chewingbever/fej
|
||||
|
||||
|
||||
all: debug
|
||||
|
@ -15,21 +14,32 @@ release:
|
|||
.PHONY: release
|
||||
|
||||
image: Dockerfile
|
||||
@ DOCKER_BUILDKIT=1 docker build -t '$(IMAGE)' .
|
||||
@ ./build '$(IMAGE)'
|
||||
.PHONY: image
|
||||
|
||||
push:
|
||||
@ ./build '$(IMAGE)' push
|
||||
.PHONY: push
|
||||
|
||||
# Run
|
||||
run:
|
||||
@ cargo run
|
||||
@ RUST_BACKTRACE=1 cargo run --bin fej
|
||||
.PHONY: run
|
||||
|
||||
|
||||
# Testing
|
||||
test:
|
||||
@ cargo test
|
||||
@ cargo test --no-fail-fast
|
||||
.PHONY: test
|
||||
|
||||
format:
|
||||
@ cargo fmt
|
||||
.PHONY: format
|
||||
|
||||
lint:
|
||||
@ cargo fmt -- --check
|
||||
.PHONY: lint
|
||||
|
||||
|
||||
# Documentation
|
||||
docs:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# rust-api
|
||||
# Fej
|
||||
|
||||
An API written in Rust, which I used to learn the language.
|
||||
Fej is an API written in Rust. I started this project to learn the language,
|
||||
and really just have some fun.
|
||||
|
||||
## Project Structure
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Simple guard to check input args
|
||||
[[ $# -eq 1 ]] || [[ $# -eq 2 ]] || {
|
||||
>&2 echo "Usage: ./build IMAGE [ACTION]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Extract current version from Cargo.toml & get current branch
|
||||
patch_version="$(grep -Po '(?<=version = ").*(?=")' Cargo.toml | head -n1)"
|
||||
major_version="$(echo "$patch_version" |
|
||||
sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+)/\1/')"
|
||||
minor_version="$(echo "$patch_version" |
|
||||
sed -E 's/([0-9]+).([0-9]+).([0-9]+)/\1.\2/')"
|
||||
branch="$(git branch --show-current)"
|
||||
|
||||
if [[ "$branch" = "master" ]]; then
|
||||
tags=("$patch_version" "$minor_version" "$major_version" "latest")
|
||||
|
||||
elif [[ "$branch" = "develop" ]]; then
|
||||
tags=("$patch_version-dev" "$minor_version-dev" "$major_version-dev" "dev")
|
||||
|
||||
else
|
||||
tags=("$branch")
|
||||
|
||||
fi
|
||||
|
||||
# Run the actual build command
|
||||
DOCKER_BUILDKIT=1 docker build -t "$1:$tags" .
|
||||
|
||||
if [[ "$2" = push ]]; then
|
||||
[[ "$branch" =~ ^develop|master$ ]] || {
|
||||
>&2 echo "You can only push from develop or master."
|
||||
exit 2
|
||||
}
|
||||
|
||||
for tag in "${tags[@]}"; do
|
||||
# Create the tag
|
||||
docker tag "$1:$tags" "$1:$tag"
|
||||
|
||||
# Push the tag
|
||||
docker push "$1:$tag"
|
||||
|
||||
# Remove the tag again, if it's not the main tag
|
||||
[[ "$tag" != "$tags" ]] && docker rmi "$1:$tag"
|
||||
done
|
||||
|
||||
elif [[ "$2" = run ]]; then
|
||||
docker run \
|
||||
--rm \
|
||||
--interactive \
|
||||
--tty \
|
||||
--publish 8000:8000 \
|
||||
"$1:$tags"
|
||||
fi
|
|
@ -0,0 +1,6 @@
|
|||
use rocket::Request;
|
||||
|
||||
#[catch(404)]
|
||||
pub fn not_found(_: &Request) -> String {
|
||||
String::from("This route doesn't exist or doesn't use the specified parameters.")
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// I can probably do this way easier using an external crate, I should do that
|
||||
use rocket::http::Status;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum FejError {
|
||||
InvalidArgument,
|
||||
FailedRequest,
|
||||
}
|
||||
|
||||
impl From<FejError> for Status {
|
||||
fn from(err: FejError) -> Status {
|
||||
match err {
|
||||
FejError::InvalidArgument => Status::BadRequest,
|
||||
FejError::FailedRequest => Status::InternalServerError,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO make this more advanced where possible
|
||||
impl From<reqwest::Error> for FejError {
|
||||
fn from(_: reqwest::Error) -> FejError {
|
||||
FejError::FailedRequest
|
||||
}
|
||||
}
|
||||
|
||||
impl From<chrono::ParseError> for FejError {
|
||||
fn from(_: chrono::ParseError) -> FejError {
|
||||
FejError::InvalidArgument
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
#[cfg(test)] mod tests;
|
||||
|
||||
pub fn routes() -> Vec<rocket::Route> {
|
||||
routes![
|
||||
world,
|
||||
hello,
|
||||
name_age
|
||||
]
|
||||
}
|
||||
|
||||
#[get("/world")]
|
||||
fn world() -> &'static str {
|
||||
"Hello, world!"
|
||||
}
|
||||
|
||||
#[get("/<name>")]
|
||||
fn hello(name: String) -> String {
|
||||
format!("Hello, {}", name)
|
||||
}
|
||||
|
||||
#[get("/world?<name>&<age>")]
|
||||
fn name_age(name: String, age: u16) -> String {
|
||||
format!("Hello, {} who is {} years old!", name, age)
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
use rocket::local::Client;
|
||||
use rocket::http::Status;
|
||||
|
||||
fn rocket() -> rocket::Rocket {
|
||||
rocket::ignite().mount("/", super::routes())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_world() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client.get("/world").dispatch();
|
||||
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.body_string(), Some("Hello, world!".into()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hello() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client.get("/thisisaname").dispatch();
|
||||
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.body_string(), Some("Hello, thisisaname".into()));
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
# Ivago
|
||||
|
||||
This part of the API is a wrapper around the Ivago website (Ivago being the
|
||||
company that collects the trash in my city). Their site isn't exactly RESTful,
|
||||
so this endpoint simply wraps it in a RESTful wrapper.
|
|
@ -0,0 +1,68 @@
|
|||
use crate::errors::FejError;
|
||||
use chrono::{DateTime, NaiveDate, TimeZone};
|
||||
use chrono_tz::Europe::Brussels;
|
||||
use chrono_tz::Tz;
|
||||
use rocket::http::RawStr;
|
||||
use rocket::request::FromFormValue;
|
||||
use serde::ser::Serializer;
|
||||
use serde::Serialize;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// This class is a simple wrapper around chrono's DateTime. Its sole purpose
|
||||
/// is to avoid error E0117.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct BasicDate(pub DateTime<Tz>);
|
||||
|
||||
impl<'v> FromFormValue<'v> for BasicDate {
|
||||
type Error = &'v RawStr;
|
||||
|
||||
fn from_form_value(form_value: &'v RawStr) -> Result<BasicDate, Self::Error> {
|
||||
match BasicDate::try_from(form_value.as_str()) {
|
||||
Err(_) => Err(form_value),
|
||||
Ok(date) => Ok(date),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for BasicDate {
|
||||
type Error = FejError;
|
||||
|
||||
fn try_from(s: &str) -> Result<BasicDate, Self::Error> {
|
||||
let naive_date = NaiveDate::parse_from_str(s, "%Y-%m-%d")?;
|
||||
|
||||
Ok(BasicDate(
|
||||
Brussels
|
||||
.from_local_datetime(&naive_date.and_hms(0, 0, 0))
|
||||
.single()
|
||||
.ok_or(FejError::InvalidArgument)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&BasicDate> for String {
|
||||
fn from(date: &BasicDate) -> String {
|
||||
format!("{}", date.0.format("%Y-%m-%d"))
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for BasicDate {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&String::from(self))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// Tests catching a string with an invalid date
|
||||
#[test]
|
||||
fn test_invalid_date() {
|
||||
let val = "2012-13-12";
|
||||
let date = BasicDate::try_from(val);
|
||||
assert_eq!(date, Err(FejError::InvalidArgument));
|
||||
}
|
||||
}
|
|
@ -1,17 +1,24 @@
|
|||
use crate::errors::FejError;
|
||||
use chrono::DateTime;
|
||||
use chrono_tz::Tz;
|
||||
use reqwest::blocking as reqwest;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use rocket::http::Status;
|
||||
use std::error::Error;
|
||||
use std::convert::{From, TryFrom};
|
||||
|
||||
pub mod structs;
|
||||
use structs::{Street, Date, PickupTime};
|
||||
mod basic_date;
|
||||
mod pickup_time;
|
||||
mod street;
|
||||
|
||||
pub use basic_date::BasicDate;
|
||||
pub use pickup_time::PickupTime;
|
||||
pub use street::Street;
|
||||
|
||||
/// The base URL where their API starts
|
||||
/// Endpoint for the search feature
|
||||
const SEARCH_URL: &str = "https://www.ivago.be/nl/particulier/autocomplete/garbage/streets";
|
||||
/// Endpoint for populating the initial cookies
|
||||
const BASE_URL: &str = "https://www.ivago.be/nl/particulier/afval/ophaling";
|
||||
const SEARCH_URL: &str ="https://www.ivago.be/nl/particulier/autocomplete/garbage/streets";
|
||||
|
||||
/// Endpoint for the actual calendar output
|
||||
const CAL_URL: &str = "https://www.ivago.be/nl/particulier/garbage/pick-up/pickups";
|
||||
|
||||
/// Searches the Ivago API for streets in the given city
|
||||
///
|
||||
|
@ -19,36 +26,71 @@ const SEARCH_URL: &str ="https://www.ivago.be/nl/particulier/autocomplete/garbag
|
|||
///
|
||||
/// * `street` - name of the street
|
||||
/// * `city` - city the street is in
|
||||
// TODO find out how to do this async
|
||||
pub fn search_streets(street_name: &String) -> Result<Vec<Street>, Box<dyn Error>> {
|
||||
pub fn search_streets(street_name: &str) -> Result<Vec<Street>, FejError> {
|
||||
let client = reqwest::Client::new();
|
||||
let response = client.get(SEARCH_URL)
|
||||
.query(&[("q", street_name)])
|
||||
.send()?;
|
||||
let response = client.get(SEARCH_URL).query(&[("q", street_name)]).send()?;
|
||||
let data: Vec<HashMap<String, String>> = response.json()?;
|
||||
|
||||
let mut output: Vec<Street> = Vec::new();
|
||||
// This is pretty cool, filter_map first does get() on all the maps, and
|
||||
// then filters out any None values
|
||||
// Then, we do the same thing for streets
|
||||
Ok(data
|
||||
.iter()
|
||||
.filter_map(|m| m.get("value"))
|
||||
.filter_map(|v| Street::try_from(v.as_str()).ok())
|
||||
.collect())
|
||||
}
|
||||
|
||||
// We iterate over every item and extract the needed data
|
||||
for map in data.iter() {
|
||||
if let Some(value) = map.get("value") {
|
||||
match Street::try_from(value) {
|
||||
Ok(street) => output.push(street),
|
||||
Err(_) => continue,
|
||||
}
|
||||
/// Returns the pickup times for the various trash types
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `street` - desired street
|
||||
/// * `number` - house number
|
||||
/// * `start_date` - earliest date for the results
|
||||
/// * `end_date` - latest date for the results
|
||||
pub fn get_pickup_times(
|
||||
street: &Street,
|
||||
number: &u32,
|
||||
start_date: &DateTime<Tz>,
|
||||
end_date: &DateTime<Tz>,
|
||||
) -> Result<Vec<PickupTime>, FejError> {
|
||||
let client = reqwest::Client::builder().cookie_store(true).build()?;
|
||||
|
||||
// This populates the cookies with the necessary values
|
||||
client
|
||||
.post(BASE_URL)
|
||||
.form(&[
|
||||
("garbage_type", ""),
|
||||
("ivago_street", &String::from(street)),
|
||||
("number", &number.to_string()),
|
||||
("form_id", "garbage_address_form"),
|
||||
])
|
||||
.send()?;
|
||||
|
||||
let response = client
|
||||
.get(CAL_URL)
|
||||
.query(&[
|
||||
("_format", "json"),
|
||||
("type", ""),
|
||||
("start", &start_date.timestamp().to_string()),
|
||||
("end", &end_date.timestamp().to_string()),
|
||||
])
|
||||
.send()?;
|
||||
let data: Vec<HashMap<String, String>> = response.json()?;
|
||||
|
||||
let mut output: Vec<PickupTime> = Vec::new();
|
||||
|
||||
for map in data
|
||||
.iter()
|
||||
.filter(|m| m.contains_key("date") && m.contains_key("label"))
|
||||
{
|
||||
// Because we filtered the maps in the loop, we can safely use unwrap
|
||||
// here
|
||||
if let Ok(date) = BasicDate::try_from(map.get("date").unwrap().as_str()) {
|
||||
output.push(PickupTime::new(date, map.get("label").unwrap().to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
|
||||
/// Return the known pickup times for the given street and/or city
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `street` - name of the street
|
||||
/// * `city` - city the street is in
|
||||
pub fn get_pickup_times(street: Street) -> Vec<PickupTime> {
|
||||
Vec::new()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
use super::BasicDate;
|
||||
use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||
|
||||
/// Represents a pickup time instance. All fields are a direct map of the
|
||||
/// original API
|
||||
pub struct PickupTime {
|
||||
date: BasicDate,
|
||||
label: String,
|
||||
}
|
||||
|
||||
impl PickupTime {
|
||||
pub fn new(date: BasicDate, label: String) -> PickupTime {
|
||||
PickupTime {
|
||||
date: date,
|
||||
label: label,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for PickupTime {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut s = serializer.serialize_struct("PickupTime", 2)?;
|
||||
s.serialize_field("date", &self.date)?;
|
||||
s.serialize_field("label", &self.label)?;
|
||||
s.end()
|
||||
}
|
||||
}
|
||||
|
||||
// I'd put tests here, but there's barely anything to do
|
|
@ -0,0 +1,85 @@
|
|||
use regex::Regex;
|
||||
use rocket::http::RawStr;
|
||||
use rocket::request::FromFormValue;
|
||||
use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Represents a street
|
||||
pub struct Street {
|
||||
name: String,
|
||||
city: String,
|
||||
}
|
||||
|
||||
impl Street {
|
||||
// This constructor just makes my life a bit easier during testing
|
||||
#[cfg(test)]
|
||||
fn new(name: String, city: String) -> Street {
|
||||
Street {
|
||||
name: name,
|
||||
city: city,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Street> for String {
|
||||
fn from(street: &Street) -> String {
|
||||
format!("{} ({})", street.name, street.city)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Street {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut s = serializer.serialize_struct("Street", 2)?;
|
||||
s.serialize_field("name", &self.name)?;
|
||||
s.serialize_field("city", &self.city)?;
|
||||
s.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for Street {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
if let Some(index) = value.find('(') {
|
||||
Ok(Street {
|
||||
name: (value[0..index - 1].trim()).to_string(),
|
||||
city: (value[index + 1..value.len() - 1].trim()).to_string(),
|
||||
})
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'v> FromFormValue<'v> for Street {
|
||||
type Error = &'v RawStr;
|
||||
|
||||
fn from_form_value(form_value: &'v RawStr) -> Result<Street, Self::Error> {
|
||||
// This regex is pretty loose tbh, but not sure how I can make it more
|
||||
// strict right now
|
||||
let re = Regex::new(r"^(.+) \((.+)\)$").unwrap();
|
||||
|
||||
match re.captures(&form_value.url_decode_lossy()) {
|
||||
None => Err(form_value),
|
||||
Some(caps) => Ok(Street {
|
||||
name: String::from(caps.get(1).unwrap().as_str()),
|
||||
city: String::from(caps.get(2).unwrap().as_str()),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_to_string() {
|
||||
let street = Street::new(String::from("testname"), String::from("city"));
|
||||
|
||||
assert_eq!(String::from("testname (city)"), String::from(&street));
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
use std::convert::TryFrom;
|
||||
use serde::ser::{Serialize, Serializer, SerializeStruct};
|
||||
|
||||
|
||||
/// Represents a street
|
||||
pub struct Street {
|
||||
name: String,
|
||||
city: String,
|
||||
}
|
||||
|
||||
impl Serialize for Street {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut s = serializer.serialize_struct("Street", 2)?;
|
||||
s.serialize_field("name", &self.name)?;
|
||||
s.serialize_field("city", &self.city)?;
|
||||
s.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&String> for Street {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: &String) -> Result<Self, Self::Error> {
|
||||
if let Some(index) = value.find('(') {
|
||||
Ok(Street {
|
||||
name: (value[0 .. index - 1].trim()).to_string(),
|
||||
city: (value[index + 1 .. value.len() - 1].trim()).to_string(),
|
||||
})
|
||||
|
||||
}else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Represents a timezoneless date
|
||||
pub struct Date {
|
||||
day: u8,
|
||||
month: u8,
|
||||
year: u32,
|
||||
}
|
||||
|
||||
|
||||
/// Represents a pickup time instance. All fields are a direct map of the
|
||||
/// original API
|
||||
pub struct PickupTime {
|
||||
date: Date,
|
||||
label: String,
|
||||
classes: Vec<String>,
|
||||
url: String
|
||||
}
|
|
@ -1,27 +1,30 @@
|
|||
#[cfg(test)] mod tests;
|
||||
mod controller;
|
||||
|
||||
use controller::{get_pickup_times, search_streets};
|
||||
use controller::{BasicDate, PickupTime, Street};
|
||||
use rocket::http::Status;
|
||||
use rocket_contrib::json::Json;
|
||||
|
||||
mod controller;
|
||||
use controller as ctrl;
|
||||
use ctrl::structs::Street;
|
||||
|
||||
pub fn routes() -> Vec<rocket::Route> {
|
||||
routes![
|
||||
search_streets,
|
||||
]
|
||||
routes![route_search_streets, route_get_pickup_times]
|
||||
}
|
||||
|
||||
// URL: https://www.ivago.be/nl/particulier/autocomplete/garbage/streets?q=Lange
|
||||
// TODO make this async
|
||||
// TODO change this so it can return errors instead of empty json
|
||||
#[get("/search?<street>", format="json")]
|
||||
pub fn search_streets(street: String) -> Json<Vec<Street>> {
|
||||
match ctrl::search_streets(&street) {
|
||||
Ok(streets) => Json(streets),
|
||||
Err(err) => {
|
||||
println!("{:?}", err);
|
||||
Json(Vec::new())
|
||||
},
|
||||
}
|
||||
#[get("/search?<street>")]
|
||||
pub fn route_search_streets(street: String) -> Result<Json<Vec<Street>>, Status> {
|
||||
Ok(Json(search_streets(street.as_str())?))
|
||||
}
|
||||
|
||||
#[get("/?<street>&<number>&<start_date>&<end_date>")]
|
||||
pub fn route_get_pickup_times(
|
||||
street: Street,
|
||||
number: u32,
|
||||
start_date: BasicDate,
|
||||
end_date: BasicDate,
|
||||
) -> Result<Json<Vec<PickupTime>>, Status> {
|
||||
Ok(Json(get_pickup_times(
|
||||
&street,
|
||||
&number,
|
||||
&start_date.0,
|
||||
&end_date.0,
|
||||
)?))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
#![feature(proc_macro_hygiene, decl_macro)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rocket;
|
||||
|
||||
// Route modules
|
||||
pub mod ivago;
|
||||
|
||||
// Helper modules
|
||||
pub mod catchers;
|
||||
pub mod errors;
|
11
src/main.rs
11
src/main.rs
|
@ -1,15 +1,12 @@
|
|||
#![feature(proc_macro_hygiene, decl_macro)]
|
||||
#[macro_use]
|
||||
extern crate rocket;
|
||||
|
||||
#[macro_use] extern crate rocket;
|
||||
|
||||
// Route modules
|
||||
mod hello;
|
||||
mod ivago;
|
||||
use fej_lib::{catchers, ivago};
|
||||
|
||||
fn rocket() -> rocket::Rocket {
|
||||
rocket::ignite()
|
||||
.mount("/hello", hello::routes())
|
||||
.mount("/ivago", ivago::routes())
|
||||
.register(catchers![catchers::not_found])
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/// In here, any non-unit tests are placed.
|
||||
use rocket::http::Status;
|
||||
use rocket::local::Client;
|
||||
|
||||
fn rocket() -> rocket::Rocket {
|
||||
rocket::ignite().mount("/", fej_lib::ivago::routes())
|
||||
}
|
||||
|
||||
/// Test 404 response
|
||||
#[test]
|
||||
fn test_404_response() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/").dispatch();
|
||||
|
||||
assert_eq!(response.status(), Status::NotFound);
|
||||
// TODO add text check as well
|
||||
}
|
||||
|
||||
/// Test 404 on invalid parameters
|
||||
// TODO make this check a 400 instead
|
||||
#[test]
|
||||
fn test_invalid_parameters() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.get("/?street=astreet+(city)&number=500&start_date=2021-04-04&end_date=2021-04-555")
|
||||
.dispatch();
|
||||
|
||||
assert_eq!(response.status(), Status::NotFound);
|
||||
}
|
Loading…
Reference in New Issue