Rust实现Http Web Server
Contents
用Rust实现WebSerer的第一篇
最近业余时间一直在学习Rust,也在尝试用Rust去造轮子。第一个轮子就是用Rust去实现Web服务器。Web服务器的核心流程就是Request
和 Response
。
简单的总结就是解析请求
,然后匹配到Server初始化的路由处理器
,然后路由处理器处理完返回
。
同步版本的程序
- 启动
TCP
服务 - 解析处理请求
- 匹配路由
- 返回响应
示范代码如下
use sync_core::server::Server;
use sync_core::service::Service;
fn main() {
//trace log
tracing_subscriber::fmt::init();
let mut server = Server::new(Service::new());
let route = sync_core::route::Route::new("GET".to_string(), "/hello".to_string(), || {
"Hello World".to_string()
});
// hello world 2 return int value
let route2 = sync_core::route::Route::new("GET".to_string(), "/hello2".to_string(), || {
//i32 value return
42.to_string()
});
// push route to server
server.service.routes.push(route);
server.service.routes.push(route2);
server.start();
}
use crate::service::Service;
use log::info;
use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};
pub struct Server {
pub service: Service,
}
impl Server {
pub fn new(service: Service) -> Self {
Self { service }
}
pub fn start(&self) {
let addr = "127.0.0.1:8080";
let listener = TcpListener::bind(addr).unwrap();
info!("Listening on http://{}", addr);
for stream in listener.incoming() {
match stream {
Ok(stream) => {
self.handle_connection(stream);
}
Err(e) => {
eprintln!("failed: {}", e);
}
}
}
}
fn handle_connection(&self, mut tcp_stream: TcpStream) {
let mut buffer = [0; 1024];
tcp_stream.read(&mut buffer).unwrap();
info!("Request: {}", String::from_utf8_lossy(&buffer));
// parse request
let request = String::from_utf8_lossy(&buffer);
let request = request.split_whitespace().collect::<Vec<&str>>();
let method = request[0];
let path = request[1];
let _version = request[2];
info!("Method: {}", method);
info!("Path: {}", path);
info!("Version: {}", _version);
// find route
let route = self
.service
.routes
.iter()
.find(|r| r.method == method && r.path == path);
match route {
Some(route) => {
let response_body = (route.handler)();
let response = format!("HTTP/1.1 200 OK\r\n\r\n{}", response_body);
tcp_stream.write(response.as_bytes()).unwrap();
}
None => {
let response_body = "Not Found Route";
let response = format!("HTTP/1.1 200 OK\r\n\r\n{}", response_body);
tcp_stream.write(response.as_bytes()).unwrap();
}
}
}
}
use crate::route::Route;
pub struct Service {
pub routes: Vec<Route>,
}
impl Service {
pub fn new() -> Self {
Self { routes: Vec::new() }
}
}
pub struct Route {
pub method: String,
pub path: String,
pub handler: fn() -> String,
}
impl Route {
pub fn new(method: String, path: String, handler: fn() -> String) -> Self {
Self {
method,
path,
handler,
}
}
}