wip: integrating docker/redis
Still untested, but this commit is a checkpoint as there are currently no errors in the Rust database. DOCKERFILE AND DOCKER-COMPOSE ARE STILL COMPLETELY UNTESTED AT THIS POINT
This commit is contained in:
parent
4405448fa2
commit
4d83500fed
|
@ -2,17 +2,6 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ahash"
|
|
||||||
version = "0.7.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
|
|
||||||
dependencies = [
|
|
||||||
"getrandom",
|
|
||||||
"once_cell",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "0.7.18"
|
version = "0.7.18"
|
||||||
|
@ -22,12 +11,52 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "argh"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dbb41d85d92dfab96cb95ab023c265c5e4261bb956c0fb49ca06d90c570f1958"
|
||||||
|
dependencies = [
|
||||||
|
"argh_derive",
|
||||||
|
"argh_shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "argh_derive"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be69f70ef5497dd6ab331a50bd95c6ac6b8f7f17a7967838332743fbd58dc3b5"
|
||||||
|
dependencies = [
|
||||||
|
"argh_shared",
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "argh_shared"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6f8c380fa28aa1b36107cd97f0196474bb7241bb95a453c5c01a15ac74b2eac"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-trait"
|
||||||
|
version = "0.1.53"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atomic"
|
name = "atomic"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
@ -110,6 +139,20 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "combine"
|
||||||
|
version = "4.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50b727aacc797f9fc28e355d21f34709ac4fc9adecfe470ad07b8f4464f53062"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"memchr",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cow-utils"
|
name = "cow-utils"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -160,6 +203,12 @@ dependencies = [
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dtoa"
|
||||||
|
version = "0.4.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "educe"
|
name = "educe"
|
||||||
version = "0.4.19"
|
version = "0.4.19"
|
||||||
|
@ -192,18 +241,6 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fallible-iterator"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fallible-streaming-iterator"
|
|
||||||
version = "0.1.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "1.7.0"
|
version = "1.7.0"
|
||||||
|
@ -330,18 +367,6 @@ name = "hashbrown"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||||
dependencies = [
|
|
||||||
"ahash",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hashlink"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf"
|
|
||||||
dependencies = [
|
|
||||||
"hashbrown",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "headers"
|
name = "headers"
|
||||||
|
@ -368,6 +393,15 @@ dependencies = [
|
||||||
"http",
|
"http",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-segmentation",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.19"
|
version = "0.1.19"
|
||||||
|
@ -385,7 +419,7 @@ checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"fnv",
|
"fnv",
|
||||||
"itoa",
|
"itoa 1.0.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -426,7 +460,7 @@ dependencies = [
|
||||||
"http-body",
|
"http-body",
|
||||||
"httparse",
|
"httparse",
|
||||||
"httpdate",
|
"httpdate",
|
||||||
"itoa",
|
"itoa 1.0.1",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -480,6 +514,12 @@ dependencies = [
|
||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "0.4.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -511,16 +551,6 @@ version = "0.2.121"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
|
checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libsqlite3-sys"
|
|
||||||
version = "0.24.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cb644c388dfaefa18035c12614156d285364769e818893da0dda9030c80ad2ba"
|
|
||||||
dependencies = [
|
|
||||||
"pkg-config",
|
|
||||||
"vcpkg",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linked-hash-map"
|
name = "linked-hash-map"
|
||||||
version = "0.5.4"
|
version = "0.5.4"
|
||||||
|
@ -549,12 +579,13 @@ dependencies = [
|
||||||
name = "lonk"
|
name = "lonk"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"argh",
|
||||||
"base64",
|
"base64",
|
||||||
"either",
|
|
||||||
"figment",
|
"figment",
|
||||||
"rusqlite",
|
"redis",
|
||||||
"serde",
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"toml",
|
||||||
"validators",
|
"validators",
|
||||||
"warp",
|
"warp",
|
||||||
]
|
]
|
||||||
|
@ -819,12 +850,6 @@ version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pkg-config"
|
|
||||||
version = "0.3.24"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
|
@ -907,6 +932,26 @@ dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redis"
|
||||||
|
version = "0.21.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a80b5f38d7f5a020856a0e16e40a9cfabf88ae8f0e4c2dcd8a3114c1e470852"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"bytes",
|
||||||
|
"combine",
|
||||||
|
"dtoa",
|
||||||
|
"futures-util",
|
||||||
|
"itoa 0.4.8",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project-lite",
|
||||||
|
"sha1",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.11"
|
version = "0.2.11"
|
||||||
|
@ -954,21 +999,6 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rusqlite"
|
|
||||||
version = "0.27.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "85127183a999f7db96d1a976a309eebbfb6ea3b0b400ddd8340190129de6eb7a"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"fallible-iterator",
|
|
||||||
"fallible-streaming-iterator",
|
|
||||||
"hashlink",
|
|
||||||
"libsqlite3-sys",
|
|
||||||
"memchr",
|
|
||||||
"smallvec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -1034,7 +1064,7 @@ version = "1.0.79"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
|
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa 1.0.1",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
@ -1046,7 +1076,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"itoa",
|
"itoa 1.0.1",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
@ -1075,6 +1105,21 @@ dependencies = [
|
||||||
"digest 0.10.3",
|
"digest 0.10.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770"
|
||||||
|
dependencies = [
|
||||||
|
"sha1_smol",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1_smol"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
@ -1360,6 +1405,12 @@ dependencies = [
|
||||||
"tinyvec",
|
"tinyvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-segmentation"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
@ -1429,12 +1480,6 @@ dependencies = [
|
||||||
"enum-ordinalize",
|
"enum-ordinalize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "vcpkg"
|
|
||||||
version = "0.2.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
|
|
@ -6,11 +6,12 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
argh = "0.1.7"
|
||||||
base64 = "0.13.0"
|
base64 = "0.13.0"
|
||||||
either = "1.6.1"
|
|
||||||
figment = { version = "0.10.6", features = ["toml", "env"] }
|
figment = { version = "0.10.6", features = ["toml", "env"] }
|
||||||
rusqlite = "0.27.0"
|
redis = { version = "~0.21.5", features = ["tokio-comp"] }
|
||||||
serde = { version = "~1.0.136", features = ["derive"] }
|
serde = { version = "~1.0.136", features = ["derive"] }
|
||||||
tokio = { version = "~1.17.0", features = ["full"] }
|
tokio = { version = "~1.17.0", features = ["full"] }
|
||||||
|
toml = "0.5.8"
|
||||||
validators = { version = "~0.24.1", features = ["url-dep"] }
|
validators = { version = "~0.24.1", features = ["url-dep"] }
|
||||||
warp = "0.3.2"
|
warp = "0.3.2"
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Create the build container to compile
|
||||||
|
FROM rust:latest as builder
|
||||||
|
RUN USER=root cargo new --bin lonk
|
||||||
|
WORKDIR lonk
|
||||||
|
|
||||||
|
# Compile dependencies
|
||||||
|
|
||||||
|
COPY ./Cargo.lock ./Cargo.lock
|
||||||
|
COPY ./Cargo.toml ./Cargo.toml
|
||||||
|
|
||||||
|
RUN cargo build --release
|
||||||
|
RUN src/*.rs
|
||||||
|
|
||||||
|
# Compile the source
|
||||||
|
COPY ./src ./src
|
||||||
|
RUN rm ./target/release/deps/lonk*
|
||||||
|
RUN cargo build
|
||||||
|
|
||||||
|
# Execution container
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=build /lonk/target/release/lonk .
|
||||||
|
CMD ["./lonk"]
|
|
@ -0,0 +1,17 @@
|
||||||
|
version: '3.9'
|
||||||
|
services:
|
||||||
|
lonk:
|
||||||
|
build: .
|
||||||
|
environment:
|
||||||
|
- PROFILE: release
|
||||||
|
- LONK_CONFIG: /data/config.toml
|
||||||
|
volumes:
|
||||||
|
- ./data:/data
|
||||||
|
redis:
|
||||||
|
image: 'redis:alpine'
|
||||||
|
command: redis-server --save 20 1 --loglevel warning
|
||||||
|
volumes:
|
||||||
|
- redis:/data
|
||||||
|
volumes:
|
||||||
|
redis:
|
||||||
|
driver: local
|
184
src/main.rs
184
src/main.rs
|
@ -1,11 +1,13 @@
|
||||||
|
use argh::FromArgs;
|
||||||
use figment::{
|
use figment::{
|
||||||
providers::{Format, Toml},
|
providers::{Format, Toml},
|
||||||
Figment,
|
Figment,
|
||||||
};
|
};
|
||||||
use rusqlite::Connection;
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{collections::BTreeSet, str::FromStr, sync::Arc};
|
use std::{collections::BTreeSet, path::PathBuf, str::FromStr, sync::Arc};
|
||||||
|
use tokio::sync::mpsc::{self, UnboundedSender};
|
||||||
use validators::prelude::*;
|
use validators::prelude::*;
|
||||||
use warp::{hyper::StatusCode, Filter};
|
use warp::{filters::BoxedFilter, hyper::StatusCode, Filter};
|
||||||
|
|
||||||
macro_rules! unwrap_or_unwrap_err {
|
macro_rules! unwrap_or_unwrap_err {
|
||||||
($x:expr) => {
|
($x:expr) => {
|
||||||
|
@ -16,62 +18,73 @@ macro_rules! unwrap_or_unwrap_err {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
mod config {
|
#[derive(Serialize, Deserialize, Debug, Validator, Clone)]
|
||||||
use serde::{Deserialize, Serialize};
|
#[validator(domain(ipv4(Allow), local(NotAllow), at_least_two_labels(Allow), port(Allow)))]
|
||||||
use std::{path::PathBuf, str::FromStr};
|
struct Url {
|
||||||
use warp::{filters::BoxedFilter, Filter};
|
domain: String,
|
||||||
|
port: Option<u16>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
pub struct Config {
|
struct DbConfig {
|
||||||
pub db_location: PathBuf,
|
pub address: Url,
|
||||||
pub slug_rules: SlugRules,
|
}
|
||||||
pub serve_rules: ServeRules,
|
|
||||||
|
impl Default for DbConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { address: Url::parse_str("redis://127.0.0.1/").unwrap() }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
pub struct SlugRules {
|
pub struct SlugRules {
|
||||||
pub length: usize,
|
pub length: usize,
|
||||||
pub chars: String,
|
pub chars: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
impl Default for SlugRules {
|
||||||
pub enum ServeRules {
|
fn default() -> Self {
|
||||||
File(PathBuf),
|
Self {
|
||||||
Dir(PathBuf),
|
length: 5,
|
||||||
}
|
chars: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-".to_string(),
|
||||||
|
|
||||||
impl ServeRules {
|
|
||||||
pub fn to_filter(&self) -> BoxedFilter<(warp::fs::File,)> {
|
|
||||||
match self {
|
|
||||||
ServeRules::File(file) => warp::fs::file(file.clone()).boxed(),
|
|
||||||
ServeRules::Dir(dir) => warp::fs::dir(dir.clone()).boxed(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for SlugRules {
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
fn default() -> Self {
|
pub enum ServeRules {
|
||||||
Self {
|
File(PathBuf),
|
||||||
length: 5,
|
Dir(PathBuf),
|
||||||
chars: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
|
}
|
||||||
.to_string(),
|
|
||||||
}
|
impl ServeRules {
|
||||||
|
pub fn to_filter(&self) -> BoxedFilter<(warp::fs::File,)> {
|
||||||
|
match self {
|
||||||
|
ServeRules::File(file) => warp::fs::file(file.clone()).boxed(),
|
||||||
|
ServeRules::Dir(dir) => warp::fs::dir(dir.clone()).boxed(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for ServeRules {
|
impl Default for ServeRules {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
ServeRules::Dir(PathBuf::from_str("/etc/lonk/served").unwrap())
|
ServeRules::Dir(PathBuf::from_str("/etc/lonk/served").unwrap())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
fn default() -> Self {
|
struct Config {
|
||||||
Self {
|
pub db: DbConfig,
|
||||||
db_location: PathBuf::from_str("/etc/lonk/data.db").unwrap(),
|
pub slug_rules: SlugRules,
|
||||||
slug_rules: Default::default(),
|
pub serve_rules: ServeRules,
|
||||||
serve_rules: Default::default(),
|
}
|
||||||
}
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
db: Default::default(),
|
||||||
|
slug_rules: Default::default(),
|
||||||
|
serve_rules: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,13 +93,6 @@ mod config {
|
||||||
#[validator(base64_url(padding(NotAllow)))]
|
#[validator(base64_url(padding(NotAllow)))]
|
||||||
struct Base64WithoutPaddingUrl(String);
|
struct Base64WithoutPaddingUrl(String);
|
||||||
|
|
||||||
#[derive(Validator)]
|
|
||||||
#[validator(domain(ipv4(Allow), local(Allow), at_least_two_labels(Allow), port(Allow)))]
|
|
||||||
struct Url {
|
|
||||||
domain: String,
|
|
||||||
port: Option<u16>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Base64WithoutPaddingUrl {
|
impl FromStr for Base64WithoutPaddingUrl {
|
||||||
type Err = <Self as ValidateString>::Error;
|
type Err = <Self as ValidateString>::Error;
|
||||||
|
|
||||||
|
@ -95,17 +101,25 @@ impl FromStr for Base64WithoutPaddingUrl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SlugDatabase(rusqlite::Connection);
|
#[derive(Debug)]
|
||||||
|
struct SlugDatabase {
|
||||||
|
tx: UnboundedSender<SlugDbMessage>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum SlugDbMessage {
|
||||||
|
Add(Slug, Url),
|
||||||
|
}
|
||||||
|
|
||||||
impl SlugDatabase {
|
impl SlugDatabase {
|
||||||
fn from_connection(connection: rusqlite::Connection) -> Self {
|
fn from_client(client: redis::Client) -> Self {
|
||||||
// TODO: Check that the database has the necessary format
|
todo!()
|
||||||
|
|
||||||
SlugDatabase(connection)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_slug(slug: Slug, url: Url) -> Result<(), ()> {
|
fn insert_slug(&self, slug: Slug, url: Url) -> Result<(), ()> {
|
||||||
todo!();
|
self.tx
|
||||||
|
.send(SlugDbMessage::Add(slug, url))
|
||||||
|
.expect("Could not send message.");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,6 +129,7 @@ struct SlugFactory {
|
||||||
slug_chars: BTreeSet<char>,
|
slug_chars: BTreeSet<char>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct Slug(String);
|
struct Slug(String);
|
||||||
|
|
||||||
enum InvalidSlug {
|
enum InvalidSlug {
|
||||||
|
@ -123,7 +138,7 @@ enum InvalidSlug {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SlugFactory {
|
impl SlugFactory {
|
||||||
fn from_rules(rules: config::SlugRules) -> Self {
|
fn from_rules(rules: SlugRules) -> Self {
|
||||||
let mut slug_chars = BTreeSet::<char>::new();
|
let mut slug_chars = BTreeSet::<char>::new();
|
||||||
slug_chars.extend(rules.chars.chars());
|
slug_chars.extend(rules.chars.chars());
|
||||||
|
|
||||||
|
@ -152,7 +167,11 @@ impl SlugFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shorten<'s>(slug_factory: &SlugFactory, db: SlugDatabase, b64url: &'s str) -> Result<StatusCode, StatusCode> {
|
fn shorten(
|
||||||
|
slug_factory: &SlugFactory,
|
||||||
|
db: &SlugDatabase,
|
||||||
|
b64url: &str,
|
||||||
|
) -> Result<StatusCode, StatusCode> {
|
||||||
let url = {
|
let url = {
|
||||||
let raw = base64::decode_config(b64url, base64::URL_SAFE_NO_PAD)
|
let raw = base64::decode_config(b64url, base64::URL_SAFE_NO_PAD)
|
||||||
.map_err(|_| warp::http::StatusCode::BAD_REQUEST)?;
|
.map_err(|_| warp::http::StatusCode::BAD_REQUEST)?;
|
||||||
|
@ -166,10 +185,10 @@ fn shorten<'s>(slug_factory: &SlugFactory, db: SlugDatabase, b64url: &'s str) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn serve() {
|
||||||
// Read configuration
|
// Read configuration
|
||||||
let config_file = std::env::var("LONK_CONFIG").unwrap_or("lonk.toml".to_string());
|
let config_file = std::env::var("LONK_CONFIG").unwrap_or("lonk.toml".to_string());
|
||||||
let config: config::Config = Figment::new()
|
let config: Config = Figment::new()
|
||||||
.merge(Toml::file(&config_file))
|
.merge(Toml::file(&config_file))
|
||||||
.extract()
|
.extract()
|
||||||
.expect("Could not parse configuration file.");
|
.expect("Could not parse configuration file.");
|
||||||
|
@ -178,7 +197,16 @@ async fn main() {
|
||||||
let slug_factory = Arc::new(SlugFactory::from_rules(config.slug_rules));
|
let slug_factory = Arc::new(SlugFactory::from_rules(config.slug_rules));
|
||||||
|
|
||||||
// Initialize database
|
// Initialize database
|
||||||
let db = Connection::open(config.db_location);
|
let db = {
|
||||||
|
let client = if let Some(port) = config.db.address.port {
|
||||||
|
redis::Client::open((config.db.address.domain, port))
|
||||||
|
} else {
|
||||||
|
redis::Client::open(config.db.address.domain)
|
||||||
|
};
|
||||||
|
let client = client.expect("Error opening Redis database.");
|
||||||
|
//let conn = Connection::open(config.db_location).expect("Could not open database.");
|
||||||
|
Arc::new(SlugDatabase::from_client(client))
|
||||||
|
};
|
||||||
|
|
||||||
// GET /
|
// GET /
|
||||||
let homepage = warp::path::end().and(config.serve_rules.to_filter());
|
let homepage = warp::path::end().and(config.serve_rules.to_filter());
|
||||||
|
@ -188,7 +216,7 @@ async fn main() {
|
||||||
move |link: Base64WithoutPaddingUrl| {
|
move |link: Base64WithoutPaddingUrl| {
|
||||||
warp::reply::with_status(
|
warp::reply::with_status(
|
||||||
warp::reply(),
|
warp::reply(),
|
||||||
unwrap_or_unwrap_err!(shorten(&slug_factory, &link.0)),
|
unwrap_or_unwrap_err!(shorten(&slug_factory, &db, &link.0)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -202,3 +230,25 @@ async fn main() {
|
||||||
|
|
||||||
warp::serve(routes).run(([127, 0, 0, 1], 8892)).await;
|
warp::serve(routes).run(([127, 0, 0, 1], 8892)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(FromArgs, PartialEq, Debug)]
|
||||||
|
/// Start lonk.
|
||||||
|
struct Run {
|
||||||
|
/// write a default configuration to stdout and quit
|
||||||
|
#[argh(switch)]
|
||||||
|
print_default_config: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let run = argh::from_env::<Run>();
|
||||||
|
|
||||||
|
if run.print_default_config {
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
toml::to_string(&Config::default())
|
||||||
|
.expect("Default configuration should always be TOML serializable")
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
serve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue