Skip to content

Commit 8d70849

Browse files
committed
♻️ refactoring
1 parent fb6fd2d commit 8d70849

File tree

15 files changed

+284
-351
lines changed

15 files changed

+284
-351
lines changed

src/error.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ pub enum MocksError {
88
FailedWriteFile(String),
99
InvalidArgs(String),
1010
Exception(String),
11-
ObjectNotFound(),
12-
MethodNotAllowed(),
11+
ResourceNotFound,
12+
ObjectNotFound,
13+
MethodNotAllowed,
14+
InvalidRequest,
1315
}
1416

1517
impl std::error::Error for MocksError {
@@ -25,8 +27,10 @@ impl fmt::Display for MocksError {
2527
Self::FailedWriteFile(err) => write!(fmt, "{err}"),
2628
Self::InvalidArgs(err) => write!(fmt, "{err}"),
2729
Self::Exception(err) => write!(fmt, "{err}"),
28-
Self::ObjectNotFound() => write!(fmt, "Object not found."),
29-
Self::MethodNotAllowed() => write!(fmt, "Method not allowed."),
30+
Self::ResourceNotFound => write!(fmt, "Resource not found."),
31+
Self::ObjectNotFound => write!(fmt, "Object not found."),
32+
Self::MethodNotAllowed => write!(fmt, "Method not allowed."),
33+
Self::InvalidRequest => write!(fmt, "Invalid request."),
3034
}
3135
}
3236
}

src/main.rs

Lines changed: 18 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -28,48 +28,22 @@ struct Args {
2828
}
2929

3030
#[tokio::main]
31-
async fn main() {
31+
async fn main() -> Result<(), MocksError> {
3232
let args = Args::parse();
33-
match init(&args.host, args.port) {
34-
Ok(socket_addr) => {
35-
println!("`mocks` started");
36-
println!("Press CTRL-C to stop");
33+
let socket_addr = init(&args.host, args.port)?;
3734

38-
let url = format!("http://{}:{}", &args.host, args.port);
35+
println!("`mocks` started");
36+
println!("Press CTRL-C to stop");
3937

40-
println!();
41-
println!("Index:");
42-
println!("{}", &url);
38+
let url = format!("http://{}:{}", &args.host, args.port);
39+
let overwrite = !args.no_overwrite;
4340

44-
println!();
45-
println!("Storage files:");
46-
println!("{}", args.file);
41+
print_startup_info(&url, &args.file, overwrite);
4742

48-
println!();
49-
println!("Overwrite:");
50-
println!("{}", if !args.no_overwrite { "YES" } else { "NO" });
43+
let storage = Storage::new(&args.file, overwrite)?;
44+
Server::startup(socket_addr, &url, storage).await?;
5145

52-
match Storage::new(&args.file, !args.no_overwrite) {
53-
Ok(s) => {
54-
// Run mock api server
55-
match Server::startup(socket_addr, &url, s).await {
56-
Ok(()) => {
57-
println!();
58-
}
59-
Err(e) => {
60-
println_err(&e);
61-
}
62-
}
63-
}
64-
Err(e) => {
65-
println_err(&e);
66-
}
67-
}
68-
}
69-
Err(e) => {
70-
println_err(&e);
71-
}
72-
}
46+
Ok(())
7347
}
7448

7549
fn init(host: &str, port: u16) -> Result<SocketAddr, MocksError> {
@@ -79,13 +53,15 @@ fn init(host: &str, port: u16) -> Result<SocketAddr, MocksError> {
7953
host
8054
};
8155

82-
match ip_addr.parse::<IpAddr>() {
83-
Ok(ip_addr) => Ok(SocketAddr::from((ip_addr, port))),
84-
Err(e) => Err(MocksError::InvalidArgs(e.to_string())),
85-
}
56+
ip_addr
57+
.parse::<IpAddr>()
58+
.map(|ip| SocketAddr::from((ip, port)))
59+
.map_err(|e| MocksError::InvalidArgs(e.to_string()))
8660
}
8761

88-
fn println_err(e: &MocksError) {
62+
fn print_startup_info(url: &str, file: &str, overwrite: bool) {
63+
println!("\nIndex:\n{}", url);
64+
println!("\nStorage files:\n{}", file);
65+
println!("\nOverwrite:\n{}", if overwrite { "YES" } else { "NO" });
8966
println!();
90-
println!("ERROR: {}", e);
9167
}

src/server.rs

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mod state;
55
use crate::error::MocksError;
66
use crate::server::handler::{delete, get_all, get_one, patch, patch_one, post, put, put_one};
77
use crate::server::hc::hc;
8-
use crate::server::state::AppState;
8+
use crate::server::state::{AppState, SharedState};
99
use crate::storage::Storage;
1010
use axum::http::StatusCode;
1111
use axum::response::{IntoResponse, Response};
@@ -19,40 +19,38 @@ use tokio::net::TcpListener;
1919
pub struct Server {}
2020

2121
impl Server {
22+
/// Starts the mock server
23+
///
24+
/// # Arguments
25+
/// * `socket_addr` - The socket address to bind the server to
26+
/// * `url` - The base URL of the server
27+
/// * `storage` - The storage instance to use
28+
///
29+
/// # Returns
30+
/// * `Result<(), MocksError>` - Ok if the server starts successfully, Err otherwise
2231
pub async fn startup(
2332
socket_addr: SocketAddr,
2433
url: &str,
2534
storage: Storage,
2635
) -> Result<(), MocksError> {
27-
match TcpListener::bind(socket_addr).await {
28-
Ok(listener) => {
29-
println!();
30-
println!("Endpoints:");
31-
print_endpoints(url, &storage.data);
36+
let listener = TcpListener::bind(socket_addr)
37+
.await
38+
.map_err(|e| MocksError::Exception(e.to_string()))?;
3239

33-
let state = AppState::new(storage);
40+
println!();
41+
println!("Endpoints:");
42+
print_endpoints(url, &storage.data);
3443

35-
let hc_router = Router::new().route("/", get(hc));
36-
let storage_router = Router::new()
37-
.route("/", get(get_all).post(post).put(put_one).patch(patch_one))
38-
.route("/:id", get(get_one).put(put).patch(patch).delete(delete));
39-
40-
let app = Router::new()
41-
.nest("/_hc", hc_router)
42-
.nest("/:resource", storage_router)
43-
.with_state(state);
44-
45-
axum::serve(listener, app)
46-
.await
47-
.map_err(|e| MocksError::Exception(e.to_string()))
48-
}
49-
Err(e) => Err(MocksError::Exception(e.to_string())),
50-
}
44+
let state = AppState::new(storage);
45+
let router = create_router(state);
46+
axum::serve(listener, router)
47+
.await
48+
.map_err(|e| MocksError::Exception(e.to_string()))
5149
}
5250
}
5351

5452
fn print_endpoints(url: &str, value: &Value) {
55-
println!("{}/{}", url, "_hc");
53+
println!("{}/_hc", url);
5654

5755
if let Value::Object(obj) = value {
5856
for (key, _) in obj {
@@ -61,15 +59,24 @@ fn print_endpoints(url: &str, value: &Value) {
6159
}
6260
}
6361

62+
fn create_router(state: SharedState) -> Router {
63+
let hc_router = Router::new().route("/", get(hc));
64+
let storage_router = Router::new()
65+
.route("/", get(get_all).post(post).put(put_one).patch(patch_one))
66+
.route("/:id", get(get_one).put(put).patch(patch).delete(delete));
67+
68+
Router::new()
69+
.nest("/_hc", hc_router)
70+
.nest("/:resource", storage_router)
71+
.with_state(state)
72+
}
73+
6474
pub fn response(status_code: StatusCode, body: String) -> Result<impl IntoResponse, StatusCode> {
65-
match Response::builder()
66-
.status(status_code.as_u16())
75+
Response::builder()
76+
.status(status_code)
6777
.header("Content-Type", "application/json")
6878
.body(body)
69-
{
70-
Ok(response) => Ok(response),
71-
Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR),
72-
}
79+
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
7380
}
7481

7582
pub fn format_err(message: &str) -> String {

src/server/handler.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub async fn get_all(
1515
Ok(state) => match state.storage.get_all(&resource) {
1616
None => response(
1717
StatusCode::NOT_FOUND,
18-
format_err(&MocksError::ObjectNotFound().to_string()),
18+
format_err(&MocksError::ObjectNotFound.to_string()),
1919
),
2020
Some(v) => response(StatusCode::OK, format!("{{\"{}\":{}}}", resource, v)),
2121
},
@@ -34,7 +34,7 @@ pub async fn get_one(
3434
Ok(state) => match state.storage.get_one(&resource, &id) {
3535
None => response(
3636
StatusCode::NOT_FOUND,
37-
format_err(&MocksError::ObjectNotFound().to_string()),
37+
format_err(&MocksError::ObjectNotFound.to_string()),
3838
),
3939
Some(v) => response(StatusCode::OK, format!("{{\"{}\":{}}}", resource, v)),
4040
},
@@ -51,13 +51,13 @@ pub async fn post(
5151
Json(input): Json<Value>,
5252
) -> Result<impl IntoResponse, StatusCode> {
5353
match state.lock() {
54-
Ok(mut state) => match state.storage.upsert(&resource, &input) {
54+
Ok(mut state) => match state.storage.insert(&resource, &input) {
5555
Ok(v) => response(StatusCode::CREATED, format!("{}", v)),
5656
Err(e) => match e {
57-
MocksError::ObjectNotFound() => {
57+
MocksError::ObjectNotFound => {
5858
response(StatusCode::NOT_FOUND, format_err(&e.to_string()))
5959
}
60-
MocksError::MethodNotAllowed() => {
60+
MocksError::MethodNotAllowed => {
6161
response(StatusCode::METHOD_NOT_ALLOWED, format_err(&e.to_string()))
6262
}
6363
_ => response(
@@ -82,7 +82,7 @@ pub async fn put(
8282
Ok(mut state) => match state.storage.replace(&resource, &id, &input) {
8383
Ok(v) => response(StatusCode::OK, format!("{}", v)),
8484
Err(e) => match e {
85-
MocksError::ObjectNotFound() => {
85+
MocksError::ObjectNotFound => {
8686
response(StatusCode::NOT_FOUND, format_err(&e.to_string()))
8787
}
8888
_ => response(
@@ -107,7 +107,7 @@ pub async fn put_one(
107107
Ok(mut state) => match state.storage.replace_one(&resource, &input) {
108108
Ok(v) => response(StatusCode::OK, format!("{}", v)),
109109
Err(e) => match e {
110-
MocksError::ObjectNotFound() => {
110+
MocksError::ObjectNotFound => {
111111
response(StatusCode::NOT_FOUND, format_err(&e.to_string()))
112112
}
113113
_ => response(
@@ -129,10 +129,10 @@ pub async fn patch(
129129
Json(input): Json<Value>,
130130
) -> Result<impl IntoResponse, StatusCode> {
131131
match state.lock() {
132-
Ok(mut state) => match state.storage.patch(&resource, &id, &input) {
132+
Ok(mut state) => match state.storage.update(&resource, &id, &input) {
133133
Ok(v) => response(StatusCode::OK, format!("{}", v)),
134134
Err(e) => match e {
135-
MocksError::ObjectNotFound() => {
135+
MocksError::ObjectNotFound => {
136136
response(StatusCode::NOT_FOUND, format_err(&e.to_string()))
137137
}
138138
_ => response(
@@ -154,10 +154,10 @@ pub async fn patch_one(
154154
Json(input): Json<Value>,
155155
) -> Result<impl IntoResponse, StatusCode> {
156156
match state.lock() {
157-
Ok(mut state) => match state.storage.patch_one(&resource, &input) {
157+
Ok(mut state) => match state.storage.update_one(&resource, &input) {
158158
Ok(v) => response(StatusCode::OK, format!("{}", v)),
159159
Err(e) => match e {
160-
MocksError::ObjectNotFound() => {
160+
MocksError::ObjectNotFound => {
161161
response(StatusCode::NOT_FOUND, format_err(&e.to_string()))
162162
}
163163
_ => response(
@@ -181,7 +181,7 @@ pub async fn delete(
181181
Ok(mut state) => match state.storage.delete(&resource, &id) {
182182
Ok(v) => response(StatusCode::OK, format!("{}", v)),
183183
Err(e) => match e {
184-
MocksError::ObjectNotFound() => {
184+
MocksError::ObjectNotFound => {
185185
response(StatusCode::NOT_FOUND, format_err(&e.to_string()))
186186
}
187187
_ => response(

0 commit comments

Comments
 (0)