Skip to content

Commit

Permalink
feat(mock-api): add comments to source code (#20)
Browse files Browse the repository at this point in the history
Co-authored-by: Kiryl Mialeshka <[email protected]>
  • Loading branch information
karatakis and meskill authored Sep 10, 2024
1 parent f625560 commit 1cf03ec
Show file tree
Hide file tree
Showing 10 changed files with 59 additions and 2 deletions.
30 changes: 29 additions & 1 deletion mock-api/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
### Dependencies

1. `rust` https://rust-lang.github.io/rustup/installation/index.html


### How to run

In the root directory of the project

`cargo run -p mock-api`
`cargo run -p mock-api`


### Routes

* `GET http://127.0.0.1:3000/posts`

Get all posts

* `GET http://127.0.0.1:3000/posts/1`

Get specific post

* `GET http://127.0.0.1:3000/users`

Get all users

* `GET http://127.0.0.1:3000/users/1`

Get specific user

* `GET http://127.0.0.1:3000/users?id=1&id=2`

Get specified users
8 changes: 8 additions & 0 deletions mock-api/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use serde_json::json;

use crate::{PostData, UserData};

/// Helper struct that is used to store the data
/// for the responses
pub struct Database {
user_template: serde_json::Value,
post_template: serde_json::Value,
Expand All @@ -23,6 +25,7 @@ fn geo_add_fractional_part(val: &mut f64) {
}

impl Database {
/// Initialize the database with random data
pub fn new() -> Self {
Self {
user_template: json!({
Expand Down Expand Up @@ -51,6 +54,7 @@ impl Database {
}
}

/// Used to reset the database and generate new data
pub fn reset(&self) -> Result<(), anyhow::Error> {
// clear the previous data from database.
self.users
Expand Down Expand Up @@ -91,18 +95,22 @@ impl Database {
Ok(())
}

/// Used to get all posts
pub fn posts(&self) -> Vec<PostData> {
self.posts.lock().unwrap().values().cloned().collect()
}

/// Used to get a post
pub fn post(&self, id: i64) -> Option<PostData> {
self.posts.lock().unwrap().get(&id).cloned()
}

/// Used to get all users
pub fn users(&self) -> Vec<UserData> {
self.users.lock().unwrap().values().cloned().collect()
}

/// Used to get a user
pub fn user(&self, id: i64) -> Option<UserData> {
self.users.lock().unwrap().get(&id).cloned()
}
Expand Down
8 changes: 7 additions & 1 deletion mock-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod database;
pub mod routes;
pub mod utils;

/// Represents the application state
pub struct AppState {
pub db: Database,
}
Expand Down Expand Up @@ -50,17 +51,22 @@ pub struct PostData {
pub body: String,
}

/// Custom error types for the application.
pub enum AppError {
/// Error indicating that a requested resource was not found.
NotFound(String),
/// Error indicating an internal server error occurred.
InternalServerError(String),
}

impl IntoResponse for AppError {
/// Convert the error into an HTTP response.
///
/// Maps the error variant to the corresponding HTTP status code and message.
fn into_response(self) -> axum::response::Response {
match self {
AppError::NotFound(msg) => (StatusCode::NOT_FOUND, msg).into_response(),
AppError::InternalServerError(msg) => (StatusCode::INTERNAL_SERVER_ERROR, msg).into_response(),
}
}
}

9 changes: 9 additions & 0 deletions mock-api/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@ async fn main() {
.with(tracing_subscriber::fmt::layer())
.init();

// The delay is expressed in milliseconds
// Used to add a delay for each request
// with the aim to "simulate" real world
let delay = env_default("MOCK_SERVER_DELAY", 5);
let delay = Duration::from_millis(delay);

// Number of requests the server can handle in a given moment
// after that number the server triggers rate-limiting
let burst_size = env_default("MOCK_SERVER_BURST_SIZE", 1000);

let rate_limiter_config = Arc::new(
Expand All @@ -37,8 +42,10 @@ async fn main() {
.unwrap(),
);

// Shared state of the API, used to keep the data that will be served
let state = Arc::new(AppState::default());

// The router and the available endpoints
let mut router = Router::new()
.route(
"/",
Expand All @@ -50,6 +57,7 @@ async fn main() {
.route("/users/:user_id", get(mock_api::routes::get_user::handle))
.route("/reset", post(mock_api::routes::reset_database::handle))
.layer(axum::middleware::from_fn(
// This middleware is responsible to apply the delay functionality
move |request: Request, next: Next| {
let delay = delay.clone();
async move {
Expand All @@ -61,6 +69,7 @@ async fn main() {
))
.with_state(state);

// Check if rate limiting is enabled and apply it
if env_default("MOCK_SERVER_LIMITER_ENABLED", false) {
router = router.layer(GovernorLayer {
config: rate_limiter_config,
Expand Down
1 change: 1 addition & 0 deletions mock-api/src/routes/get_post.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use axum::{

use crate::{AppError, AppState};

/// route handler for getting a post
pub async fn handle(
state: State<Arc<AppState>>,
post_id: Path<i64>,
Expand Down
1 change: 1 addition & 0 deletions mock-api/src/routes/get_posts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use axum::{extract::State, response::IntoResponse, Json};

use crate::{AppError, AppState};

/// route handler for getting all posts
pub async fn handle(state: State<Arc<AppState>>) -> Result<impl IntoResponse, AppError> {
Ok(Json(state.db.posts()))
}
1 change: 1 addition & 0 deletions mock-api/src/routes/get_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use axum::{

use crate::{AppError, AppState};

/// route handler for getting a user
pub async fn handle(
state: State<Arc<AppState>>,
user_id: Path<i64>,
Expand Down
1 change: 1 addition & 0 deletions mock-api/src/routes/get_users.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use axum::{

use crate::{AppError, AppState};

/// route handler for getting all users
pub async fn handle(
state: State<Arc<AppState>>,
Query(params): Query<Vec<(String, i64)>>,
Expand Down
1 change: 1 addition & 0 deletions mock-api/src/routes/reset_database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use serde_json::json;

use crate::{AppError, AppState};

/// route handler for resetting the database
pub async fn handle(state: State<Arc<AppState>>) -> Result<impl IntoResponse, AppError> {
match state.db.reset() {
Ok(()) => Ok(Json(json!({"status": "Database reset successfully"}))),
Expand Down
1 change: 1 addition & 0 deletions mock-api/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::str::FromStr;

/// Used to read variables from Environment
pub fn env_default<T: FromStr>(name: &str, default_value: T) -> T {
std::env::var(name)
.ok()
Expand Down

0 comments on commit 1cf03ec

Please sign in to comment.