O Proxy é um padrão de projeto estrutural que fornece um objeto que atua como um substituto para um objeto de serviço real usado por um cliente. Um proxy recebe solicitações do cliente, realiza alguma tarefa (controle de acesso, armazenamento em cache etc.) e passa a solicitação para um objeto de serviço.
O objeto proxy tem a mesma interface que um serviço, o que o torna intercambiável com um objeto real quando passado para um 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