![Proxy](/images/patterns/cards/proxy-mini.png?id=25890b11e7dc5af29625ccd0678b63a8)
Proxy en Rust
Proxy es un patrón de diseño estructural que proporciona un objeto que actúa como sustituto de un objeto de servicio real utilizado por un cliente. Un proxy recibe solicitudes del cliente, realiza parte del trabajo (control de acceso, almacenamiento en caché, etc.) y después pasa la solicitud a un objeto de servicio.
El objeto proxy tiene la misma interfaz que un servicio, lo que lo hace intercambiable con un objeto real cuando se pasa a un cliente.
Conceptual Example: Nginx Proxy
A web server such as Nginx can act as a proxy for your application server:
- It provides controlled access to your application server.
- It can do rate limiting.
- It can do request caching.
server.rs
mod application;
mod nginx;
pub use nginx::NginxServer;
pub trait Server {
fn handle_request(&mut self, url: &str, method: &str) -> (u16, String);
}
server/application.rs
use super::Server;
pub struct Application;
impl Server for Application {
fn handle_request(&mut self, url: &str, method: &str) -> (u16, String) {
if url == "/app/status" && method == "GET" {
return (200, "Ok".into());
}
if url == "/create/user" && method == "POST" {
return (201, "User Created".into());
}
(404, "Not Ok".into())
}
}
server/nginx.rs
use std::collections::HashMap;
use super::{application::Application, Server};
/// NGINX server is a proxy to an application server.
pub struct NginxServer {
application: Application,
max_allowed_requests: u32,
rate_limiter: HashMap<String, u32>,
}
impl NginxServer {
pub fn new() -> Self {
Self {
application: Application,
max_allowed_requests: 2,
rate_limiter: HashMap::default(),
}
}
pub fn check_rate_limiting(&mut self, url: &str) -> bool {
let rate = self.rate_limiter.entry(url.to_string()).or_insert(1);
if *rate > self.max_allowed_requests {
return false;
}
*rate += 1;
true
}
}
impl Server for NginxServer {
fn handle_request(&mut self, url: &str, method: &str) -> (u16, String) {
if !self.check_rate_limiting(url) {
return (403, "Not Allowed".into());
}
self.application.handle_request(url, method)
}
}
main.rs
mod server;
use crate::server::{NginxServer, Server};
fn main() {
let app_status = &"/app/status".to_string();
let create_user = &"/create/user".to_string();
let mut nginx = NginxServer::new();
let (code, body) = nginx.handle_request(app_status, "GET");
println!("Url: {}\nHttpCode: {}\nBody: {}\n", app_status, code, body);
let (code, body) = nginx.handle_request(app_status, "GET");
println!("Url: {}\nHttpCode: {}\nBody: {}\n", app_status, code, body);
let (code, body) = nginx.handle_request(app_status, "GET");
println!("Url: {}\nHttpCode: {}\nBody: {}\n", app_status, code, body);
let (code, body) = nginx.handle_request(create_user, "POST");
println!("Url: {}\nHttpCode: {}\nBody: {}\n", create_user, code, body);
let (code, body) = nginx.handle_request(create_user, "GET");
println!("Url: {}\nHttpCode: {}\nBody: {}\n", create_user, code, body);
}
Output
Url: /app/status HttpCode: 200 Body: Ok Url: /app/status HttpCode: 200 Body: Ok Url: /app/status HttpCode: 403 Body: Not Allowed Url: /create/user HttpCode: 201 Body: User Created Url: /create/user HttpCode: 404 Body: Not Ok