52 lines
2.2 KiB

use std::time::Duration;
use anyhow::*;
use log::LevelFilter;
use kochab::{Server, Request, Response, Document};
/// An ultra-simple ratelimiting example
/// We set up two pages:
/// * `/*` which can be accessed as much as the user wants
/// * /limit/*` which can only be accessed twice every 10 seconds
/// Once we tell it what needs to be ratelimited, kochab will automatically handle keeping
/// track of what users have and have not visited that page and how often. A very small
/// concurrent background task is in charge of cleaning the in-memory database every so
/// often so that a memory leak doesn't form.
async fn main() -> Result<()> {
// We set up logging so we can see what's happening. This isn't technically required,
// and you can use a simpler solution (like env_logger::init()) during production
.filter_module("kochab", LevelFilter::Debug)
Server::new() // Create a server
.add_route("/", handle_request) // Create a page, content doesn't matter
.ratelimit("/limit", 2, Duration::from_secs(10)) // Set the ratelimit to 2 / 10s
.serve_ip("localhost:1965") // Start the server
/// Render a simple page based on the current URL
/// The actual content of the response, and really anything in this section, doesn't
/// actually affect the ratelimit, but it's nice to have a usable demo, so we set up a
/// couple nice pages
async fn handle_request(request: Request) -> Result<Response> {
let mut document = Document::new();
if let Some("limit") = request.trailing_segments().get(0).map(String::as_str) {
document.add_text("You're on a rate limited page!")
.add_text("You can only access this page twice every 10 seconds");
} else {
document.add_text("You're on a normal page!")
.add_text("You can access this page as much as you like.");
.add_link("/limit", "Go to rate limited page")
.add_link("/", "Go to a page that's not rate limited");