Skip to content

Commit e9d99fe

Browse files
committed
Proxy Pattern: Conpeptual example "Nginx Proxy"
1 parent 25bcfb1 commit e9d99fe

File tree

7 files changed

+130
-0
lines changed

7 files changed

+130
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ members = [
1515
"structural/decorator",
1616
"structural/facade",
1717
"structural/flyweight",
18+
"structural/proxy",
1819
]

structural/proxy/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
edition = "2021"
3+
name = "proxy"
4+
version = "0.1.0"
5+
6+
[[bin]]
7+
name = "proxy"
8+
path = "main.rs"

structural/proxy/README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Proxy
2+
3+
## Conceptual Example: Nginx Proxy
4+
5+
```bash
6+
cargo run
7+
```
8+
9+
## Execution Result
10+
11+
```
12+
Url: /app/status
13+
HttpCode: 200
14+
Body: Ok
15+
16+
Url: /app/status
17+
HttpCode: 200
18+
Body: Ok
19+
20+
Url: /app/status
21+
HttpCode: 403
22+
Body: Not Allowed
23+
24+
Url: /create/user
25+
HttpCode: 201
26+
Body: User Created
27+
28+
Url: /create/user
29+
HttpCode: 404
30+
Body: Not Ok
31+
```

structural/proxy/main.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
mod server;
2+
3+
use crate::server::{NginxServer, Server};
4+
5+
fn main() {
6+
let app_status = &"/app/status".to_string();
7+
let create_user = &"/create/user".to_string();
8+
9+
let mut nginx = NginxServer::new();
10+
11+
let (code, body) = nginx.handle_request(app_status, "GET");
12+
println!("Url: {}\nHttpCode: {}\nBody: {}\n", app_status, code, body);
13+
14+
let (code, body) = nginx.handle_request(app_status, "GET");
15+
println!("Url: {}\nHttpCode: {}\nBody: {}\n", app_status, code, body);
16+
17+
let (code, body) = nginx.handle_request(app_status, "GET");
18+
println!("Url: {}\nHttpCode: {}\nBody: {}\n", app_status, code, body);
19+
20+
let (code, body) = nginx.handle_request(create_user, "POST");
21+
println!("Url: {}\nHttpCode: {}\nBody: {}\n", create_user, code, body);
22+
23+
let (code, body) = nginx.handle_request(create_user, "GET");
24+
println!("Url: {}\nHttpCode: {}\nBody: {}\n", create_user, code, body);
25+
}

structural/proxy/server.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
mod application;
2+
mod nginx;
3+
4+
pub use nginx::NginxServer;
5+
6+
pub trait Server {
7+
fn handle_request(&mut self, url: &String, method: &str) -> (u16, String);
8+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use super::Server;
2+
3+
pub struct Application;
4+
5+
impl Server for Application {
6+
fn handle_request(&mut self, url: &String, method: &str) -> (u16, String) {
7+
if url == "/app/status" && method == "GET" {
8+
return (200, "Ok".into());
9+
}
10+
11+
if url == "/create/user" && method == "POST" {
12+
return (201, "User Created".into());
13+
}
14+
15+
(404, "Not Ok".into())
16+
}
17+
}

structural/proxy/server/nginx.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use std::collections::HashMap;
2+
3+
use super::{application::Application, Server};
4+
5+
pub struct NginxServer {
6+
application: Application,
7+
max_allowed_requests: u32,
8+
rate_limiter: HashMap<String, u32>,
9+
}
10+
11+
impl NginxServer {
12+
pub fn new() -> Self {
13+
Self {
14+
application: Application,
15+
max_allowed_requests: 2,
16+
rate_limiter: HashMap::default(),
17+
}
18+
}
19+
20+
pub fn check_rate_limiting(&mut self, url: &String) -> bool {
21+
let rate = self.rate_limiter.entry(url.clone()).or_insert(1);
22+
23+
if *rate > self.max_allowed_requests {
24+
return false;
25+
}
26+
27+
*rate += 1;
28+
return true;
29+
}
30+
}
31+
32+
impl Server for NginxServer {
33+
fn handle_request(&mut self, url: &String, method: &str) -> (u16, String) {
34+
if !self.check_rate_limiting(url) {
35+
return (403, "Not Allowed".into());
36+
}
37+
38+
return self.application.handle_request(url, method);
39+
}
40+
}

0 commit comments

Comments
 (0)