Skip to content

Commit

Permalink
Adding rate limit to back-end (#102)
Browse files Browse the repository at this point in the history
Signed-off-by: danbugs <[email protected]>
  • Loading branch information
danbugs authored Feb 21, 2024
1 parent 4367169 commit 3655c93
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 14 deletions.
120 changes: 120 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ rocket = "0.5.0"
rocket_cors = "0.6.0"
serde_json = "1"
thiserror = "1"
smithe_lib = { path = "../lib" }
smithe_lib = { path = "../lib" }
rocket-governor = "0.2.0-rc.1"
70 changes: 57 additions & 13 deletions backend/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(non_snake_case)]
#[macro_use]
extern crate rocket;

Expand All @@ -7,6 +8,7 @@ use rocket::{
Build, Request, Rocket,
};
use rocket_cors::{AllowedHeaders, AllowedOrigins};
use rocket_governor::{Quota, RocketGovernable, RocketGovernor};
use smithe_lib::{
player::{get_all_like, get_player, get_top_two_characters},
set::{
Expand Down Expand Up @@ -39,75 +41,108 @@ impl<'r, 'o: 'r> Responder<'r, 'o> for Error {
}

#[get("/")]
fn index() -> &'static str {
fn index(_limitguard: RocketGovernor<'_, RateLimitGuard>) -> &'static str {
"Hello, world!"
}

#[get("/<tag>")]
fn search_players(tag: String) -> Result<String, Error> {
fn search_players(
tag: String,
_limitguard: RocketGovernor<'_, RateLimitGuard>,
) -> Result<String, Error> {
Ok(serde_json::to_string(&get_all_like(&tag)?)?)
}

#[get("/<id>")]
fn view_player(id: i32) -> Result<String, Error> {
fn view_player(id: i32, _limitguard: RocketGovernor<'_, RateLimitGuard>) -> Result<String, Error> {
// insert player page view
smithe_lib::player_page_views::insert_player_page_view(id).unwrap();
Ok(serde_json::to_string(&get_player(id)?)?)
}

#[get("/<id>")]
async fn get_player_tournaments(id: i32) -> Result<String, Error> {
async fn get_player_tournaments(
id: i32,
_limitguard: RocketGovernor<'_, RateLimitGuard>,
) -> Result<String, Error> {
Ok(serde_json::to_string(
&get_tournaments_from_requester_id(id).await?,
)?)
}

#[get("/<id>/wins_without_dqs")]
async fn get_player_set_wins_without_dqs(id: i32) -> Result<String, Error> {
async fn get_player_set_wins_without_dqs(
id: i32,
_limitguard: RocketGovernor<'_, RateLimitGuard>,
) -> Result<String, Error> {
Ok(serde_json::to_string(&get_set_wins_without_dqs(id)?)?)
}

#[get("/<id>/losses_without_dqs")]
async fn get_player_set_losses_without_dqs(id: i32) -> Result<String, Error> {
async fn get_player_set_losses_without_dqs(
id: i32,
_limitguard: RocketGovernor<'_, RateLimitGuard>,
) -> Result<String, Error> {
Ok(serde_json::to_string(&get_set_losses_without_dqs(id)?)?)
}

#[get("/<id>/wins_by_dqs")]
async fn get_player_set_wins_by_dqs(id: i32) -> Result<String, Error> {
async fn get_player_set_wins_by_dqs(
id: i32,
_limitguard: RocketGovernor<'_, RateLimitGuard>,
) -> Result<String, Error> {
Ok(serde_json::to_string(&get_set_wins_by_dq(id)?)?)
}

#[get("/<id>/losses_by_dqs")]
async fn get_player_set_losses_by_dqs(id: i32) -> Result<String, Error> {
async fn get_player_set_losses_by_dqs(
id: i32,
_limitguard: RocketGovernor<'_, RateLimitGuard>,
) -> Result<String, Error> {
Ok(serde_json::to_string(&get_set_losses_by_dq(id)?)?)
}

#[get("/<id>/winrate")]
async fn get_player_winrate(id: i32) -> Result<String, Error> {
async fn get_player_winrate(
id: i32,
_limitguard: RocketGovernor<'_, RateLimitGuard>,
) -> Result<String, Error> {
Ok(serde_json::to_string(&get_winrate(id)?)?)
}

#[get("/<id>/competitor_type")]
async fn get_player_competitor_type(id: i32) -> Result<String, Error> {
async fn get_player_competitor_type(
id: i32,
_limitguard: RocketGovernor<'_, RateLimitGuard>,
) -> Result<String, Error> {
let ct = get_competitor_type(id)?;
Ok(serde_json::to_string(&format!("{}-{}er", ct.0, ct.1))?)
}

// endpoint to get_top_two_characters
#[get("/<id>/top_two_characters")]
async fn get_player_top_two_characters(id: i32) -> Result<String, Error> {
async fn get_player_top_two_characters(
id: i32,
_limitguard: RocketGovernor<'_, RateLimitGuard>,
) -> Result<String, Error> {
Ok(serde_json::to_string(&get_top_two_characters(id)?)?)
}

// get sets by player id
#[get("/<id>")]
async fn get_player_sets(id: i32) -> Result<String, Error> {
async fn get_player_sets(
id: i32,
_limitguard: RocketGovernor<'_, RateLimitGuard>,
) -> Result<String, Error> {
Ok(serde_json::to_string(&get_sets_per_player_id(id)?)?)
}

// get head to head by player id
#[get("/<id>/head_to_head")]
async fn get_player_head_to_head(id: i32) -> Result<String, Error> {
async fn get_player_head_to_head(
id: i32,
_limitguard: RocketGovernor<'_, RateLimitGuard>,
) -> Result<String, Error> {
Ok(serde_json::to_string(&get_head_to_head_record(id)?)?)
}

Expand Down Expand Up @@ -155,6 +190,7 @@ fn rocket() -> Rocket<Build> {
get_player_competitor_type,
],
)
.register("/", catchers!(rocket_governor::rocket_governor_catcher))
.attach(cors)
}

Expand All @@ -163,3 +199,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let _ = rocket().launch().await?;
Ok(())
}

pub struct RateLimitGuard;

impl<'r> RocketGovernable<'r> for RateLimitGuard {
fn quota(_method: Method, _route_name: &str) -> Quota {
Quota::per_minute(Self::nonzero(60u32))
}
}
4 changes: 4 additions & 0 deletions backend/test-rate-limit.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
1..150 | ForEach-Object {
curl http://127.0.0.1:8000/
Write-Output "Request $_"
}

0 comments on commit 3655c93

Please sign in to comment.