summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTyler Murphy <tylermurphy534@gmail.com>2023-01-31 00:00:13 -0500
committerTyler Murphy <tylermurphy534@gmail.com>2023-01-31 00:00:13 -0500
commitef24cfedbff489bff73d6e1e6114fdd527235acb (patch)
tree2eddef955fd025f836dc3d2cfa0f28e80698238b
parentcolored pfps (diff)
downloadxssbook-ef24cfedbff489bff73d6e1e6114fdd527235acb.tar.gz
xssbook-ef24cfedbff489bff73d6e1e6114fdd527235acb.tar.bz2
xssbook-ef24cfedbff489bff73d6e1e6114fdd527235acb.zip
rate limiting
-rw-r--r--Cargo.lock263
-rw-r--r--Cargo.toml9
-rw-r--r--public/js/header.js2
-rw-r--r--public/js/home.js7
-rw-r--r--public/js/people.js7
-rw-r--r--public/js/profile.js9
-rw-r--r--src/api/mod.rs43
-rw-r--r--src/main.rs24
8 files changed, 321 insertions, 43 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 2f93e62..9a47937 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -113,6 +113,12 @@ dependencies = [
]
[[package]]
+name = "bumpalo"
+version = "3.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
+
+[[package]]
name = "bytes"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -151,6 +157,15 @@ dependencies = [
]
[[package]]
+name = "crossbeam-utils"
+version = "0.8.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -161,6 +176,19 @@ dependencies = [
]
[[package]]
+name = "dashmap"
+version = "5.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc"
+dependencies = [
+ "cfg-if",
+ "hashbrown",
+ "lock_api",
+ "once_cell",
+ "parking_lot_core",
+]
+
+[[package]]
name = "digest"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -208,25 +236,58 @@ dependencies = [
]
[[package]]
+name = "futures"
+version = "0.3.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
name = "futures-channel"
-version = "0.3.25"
+version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed"
+checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5"
dependencies = [
"futures-core",
+ "futures-sink",
]
[[package]]
name = "futures-core"
-version = "0.3.25"
+version = "0.3.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608"
+
+[[package]]
+name = "futures-executor"
+version = "0.3.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
+checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531"
[[package]]
name = "futures-macro"
-version = "0.3.25"
+version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
+checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70"
dependencies = [
"proc-macro2",
"quote",
@@ -235,25 +296,35 @@ dependencies = [
[[package]]
name = "futures-sink"
-version = "0.3.25"
+version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9"
+checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364"
[[package]]
name = "futures-task"
-version = "0.3.25"
+version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea"
+checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366"
+
+[[package]]
+name = "futures-timer"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c"
[[package]]
name = "futures-util"
-version = "0.3.25"
+version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
+checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
dependencies = [
+ "futures-channel",
"futures-core",
+ "futures-io",
"futures-macro",
+ "futures-sink",
"futures-task",
+ "memchr",
"pin-project-lite",
"pin-utils",
"slab",
@@ -277,7 +348,25 @@ checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "governor"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c390a940a5d157878dd057c78680a33ce3415bcd05b4799509ea44210914b4d5"
+dependencies = [
+ "cfg-if",
+ "dashmap",
+ "futures",
+ "futures-timer",
+ "no-std-compat",
+ "nonzero_ext",
+ "parking_lot",
+ "quanta",
+ "rand",
+ "smallvec",
]
[[package]]
@@ -402,6 +491,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
+name = "js-sys"
+version = "0.3.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -444,6 +542,15 @@ dependencies = [
]
[[package]]
+name = "mach"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
+dependencies = [
+ "libc",
+]
+
+[[package]]
name = "matchit"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -479,17 +586,29 @@ checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
dependencies = [
"libc",
"log",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys",
]
[[package]]
+name = "no-std-compat"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c"
+
+[[package]]
name = "nonempty"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7"
[[package]]
+name = "nonzero_ext"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21"
+
+[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -604,6 +723,22 @@ dependencies = [
]
[[package]]
+name = "quanta"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20afe714292d5e879d8b12740aa223c6a88f118af41870e8b6196e39a02238a8"
+dependencies = [
+ "crossbeam-utils",
+ "libc",
+ "mach",
+ "once_cell",
+ "raw-cpuid",
+ "wasi 0.10.2+wasi-snapshot-preview1",
+ "web-sys",
+ "winapi",
+]
+
+[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -643,6 +778,15 @@ dependencies = [
]
[[package]]
+name = "raw-cpuid"
+version = "10.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6823ea29436221176fe662da99998ad3b4db2c7f31e7b6f5fe43adccd6320bb"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
name = "redox_syscall"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -977,6 +1121,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
+name = "tower_governor"
+version = "0.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c6be418f6d18863291f0a7fa1da1de71495a19a54b5fb44969136f731a47e86"
+dependencies = [
+ "axum",
+ "forwarded-header-value",
+ "futures",
+ "futures-core",
+ "governor",
+ "http",
+ "pin-project",
+ "thiserror",
+ "tokio",
+ "tower",
+ "tower-layer",
+ "tracing",
+]
+
+[[package]]
name = "tracing"
version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1092,11 +1256,81 @@ dependencies = [
[[package]]
name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+
+[[package]]
+name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
+name = "wasm-bindgen"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
+
+[[package]]
+name = "web-sys"
+version = "0.3.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1192,6 +1426,7 @@ dependencies = [
"tower",
"tower-cookies",
"tower-http",
+ "tower_governor",
"tracing",
"tracing-subscriber",
]
diff --git a/Cargo.toml b/Cargo.toml
index 9181b8e..9fdbd0c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,16 +6,17 @@ edition = "2021"
[dependencies]
tokio = { version = "1.23.0", features = ["full"] }
axum = { version = "0.6.4", features = ["headers"] }
+axum-client-ip = "0.3.1"
tower-http = { version = "0.3.5", features = ["fs"] }
+tower_governor = "0.0.4"
tower-cookies = "0.8.0"
tower = "0.4.13"
+tracing = "0.1.37"
+tracing-subscriber = "0.3.16"
bytes = "1.3.0"
-axum-client-ip = "0.3.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", features = ["std"] }
rusqlite = { version = "0.28.0", features = ["bundled"] }
rand = "0.8.5"
time = "0.3.17"
-lazy_static = "1.4.0"
-tracing = "0.1.37"
-tracing-subscriber = "0.3.16" \ No newline at end of file
+lazy_static = "1.4.0" \ No newline at end of file
diff --git a/public/js/header.js b/public/js/header.js
index 0e251ed..f296567 100644
--- a/public/js/header.js
+++ b/public/js/header.js
@@ -15,7 +15,7 @@ function header(home, people, user_id) {
</a>
</div>
<a class="pfp" id="profile" hreF="profile">
- ${pfp(user_id)}
+ ${user_id === undefined ? '' : pfp(user_id)}
</a>
</div>
<div class="spacer"></div>
diff --git a/public/js/home.js b/public/js/home.js
index 0083297..2e5818a 100644
--- a/public/js/home.js
+++ b/public/js/home.js
@@ -243,7 +243,12 @@ async function load() {
}
async function init() {
- data.user = (await loadself()).json
+ let request = (await loadself());
+ if (request.status === 429) {
+ header(true, false)
+ throw new Error("Rate limited");
+ }
+ data.user = request.json
header(true, false, data.user.user_id)
data.users[data.user.user_id] = data.user
const posts = await load()
diff --git a/public/js/people.js b/public/js/people.js
index b861818..6568ccc 100644
--- a/public/js/people.js
+++ b/public/js/people.js
@@ -48,7 +48,12 @@ async function loadMore() {
}
async function load() {
- const self = (await loadself()).json
+ let request = await loadself()
+ if (request.status === 429) {
+ header(false, true)
+ throw new Error("Rate limited");
+ }
+ const self = request.json
header(false, true, self.user_id)
const users = (await loaduserspage(page)).json
if (users.length === 0) {
diff --git a/public/js/profile.js b/public/js/profile.js
index a043fde..10eb873 100644
--- a/public/js/profile.js
+++ b/public/js/profile.js
@@ -89,7 +89,14 @@ async function load() {
params[key] = value
}
- data.self = (await loadself()).json;
+ let request = await loadself()
+
+ if (request.status === 429) {
+ header(false, false)
+ throw new Error("Rate limited");
+ }
+
+ data.self = request.json;
data.users[data.self.user_id] = data.self
let id;
diff --git a/src/api/mod.rs b/src/api/mod.rs
index c347207..d36b127 100644
--- a/src/api/mod.rs
+++ b/src/api/mod.rs
@@ -1,5 +1,48 @@
+use crate::types::extract::RouterURI;
+use axum::{Extension, Router, BoxError, error_handling::HandleErrorLayer};
+use tower::ServiceBuilder;
+use tower_governor::{governor::GovernorConfigBuilder, GovernorLayer, errors::display_error, key_extractor::SmartIpKeyExtractor};
+
pub mod admin;
pub mod auth;
pub mod pages;
pub mod posts;
pub mod users;
+
+pub fn router() -> Router {
+ let governor_conf = Box::new(
+ GovernorConfigBuilder::default()
+ .burst_size(10)
+ .per_second(1)
+ .key_extractor(SmartIpKeyExtractor)
+ .finish()
+ .expect("Failed to create rate limiter"),
+ );
+
+ Router::new()
+ .nest(
+ "/admin",
+ admin::router().layer(Extension(RouterURI("/api/admin"))),
+ )
+ .nest(
+ "/auth",
+ auth::router().layer(Extension(RouterURI("/api/auth"))),
+ )
+ .nest(
+ "/users",
+ users::router().layer(Extension(RouterURI("/api/users"))),
+ )
+ .nest(
+ "/posts",
+ posts::router().layer(Extension(RouterURI("/api/posts"))),
+ )
+ .layer(
+ ServiceBuilder::new()
+ .layer(HandleErrorLayer::new(|e: BoxError| async move {
+ display_error(e)
+ }))
+ .layer(GovernorLayer {
+ config: Box::leak(governor_conf),
+ }),
+ )
+}
diff --git a/src/main.rs b/src/main.rs
index 03cee25..a72ec5f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,7 +3,7 @@ use axum::{
http::{Request, StatusCode},
middleware::{self, Next},
response::Response,
- Extension, RequestExt, Router,
+ RequestExt, Router,
};
use axum_client_ip::ClientIp;
use std::{net::SocketAddr, process::exit};
@@ -14,10 +14,7 @@ use tracing_subscriber::{
};
use types::http::ResponseCode;
-use crate::{
- api::{auth, pages, posts, users},
- types::extract::RouterURI,
-};
+use crate::api::pages;
mod admin;
mod api;
@@ -77,22 +74,7 @@ async fn main() {
.layer(middleware::from_fn(log))
.layer(middleware::from_fn(serve))
.nest("/", pages::router())
- .nest(
- "/api/admin",
- api::admin::router().layer(Extension(RouterURI("/api/admin"))),
- )
- .nest(
- "/api/auth",
- auth::router().layer(Extension(RouterURI("/api/auth"))),
- )
- .nest(
- "/api/users",
- users::router().layer(Extension(RouterURI("/api/users"))),
- )
- .nest(
- "/api/posts",
- posts::router().layer(Extension(RouterURI("/api/posts"))),
- )
+ .nest("/api", api::router())
.layer(CookieManagerLayer::new());
let Ok(addr) = "[::]:8080".parse::<std::net::SocketAddr>() else {