main.rs
use std::collections::HashMap;
mod ares;
fn main() {
let mut content = HashMap::new();
content.insert(
"title",
"index page",
);
content.insert(
"data1",
"10000",
);
let _ = ares::Router::new("index", Some(content));
}
### フレームワーク側
ares.rs
use std::fs;
use std::io;
use std::io::prelude::*;
use std::net::{TcpListener, TcpStream};
use std::collections::HashMap;
pub struct Router;
impl Router {
pub fn new(path: &str, content: Option<HashMap<&str, &str>>) {
let mut routes = HashMap::new();
let temp_path = format!("./templates/{}.html", path);
let mut html = fs::read_to_string(temp_path).unwrap();
match content {
Some(data) => {
for (key, value) in data {
let k = format!("{{{{ {} }}}}", key);
html = html.replace(&k, value);
}
},
None => {},
}
let route_path = format!("/{}", path);
routes.insert(
route_path, html,
);
println!("{:?}", routes);
let listenr = TcpListener::bind("192.168.33.10:8000").unwrap();
for stream in listenr.incoming() {
match stream {
Ok(stream) => {
let _ = handle_connection(stream, routes.clone());
}
Err(e) => {
println!("Connection failed: {}", e);
}
}
}
}
}
fn handle_connection(mut stream: TcpStream, routes: HashMap<String, String>) {
let mut buffer = [0; 1024];
stream.read(&mut buffer).unwrap();
let request = String::from_utf8_lossy(&buffer);
let request_line = request.lines().next().unwrap_or("");
println!("Received request:\n{}", request);
let path = request_line
.split_whitespace()
.nth(1)
.unwrap_or("/");
let response_body = routes.get(path)
.cloned()
.unwrap_or_else(|| "<h1>404 Not Found</h1>".to_string());
let response = http_response(200, "text/html", &response_body);
stream.write_all(response.as_bytes()).unwrap();
stream.flush().unwrap();
}
fn http_response(status_code: u16, content_type: &str, body: &str) -> String {
format!(
"HTTP/1.1 {} {}\r\nContent-Type: {}\r\nContent-Length: {}\r\n\r\n{}",
status_code,
get_status_text(status_code),
content_type,
body.len(),
body
)
}
fn get_status_text(code: u16) -> &'static str {
match code {
200 => "OK",
404 => "Not Found",
_ => "Unknown",
}
}
複数パスに対応できるようにしたい。
### 複数パスに対応
hashmapにパスとコンテンツを追加するように実装する
use std::collections::HashMap;
mod ares;
fn main() {
let mut router = ares::Router::new();
let mut content1 = HashMap::new();
content1.insert(
"title",
"index page",
);
let mut content2 = HashMap::new();
content2.insert(
"title",
"this is title",
);
router.add("index", Some(content1));
router.add("hello", None);
router.add("world", Some(content2));
router.up("192.168.33.10:8000");
}
pub struct Router {
route: HashMap<String, String>,
}
impl Router {
pub fn new() -> Self {
Router {
route: HashMap::new(),
}
}
pub fn add(&mut self, path: &str, content: Option<HashMap<&str, &str>>){
let temp_path = format!("./templates/{}.html", path);
let mut html = fs::read_to_string(temp_path).unwrap();
match content {
Some(data) => {
for (key, value) in data {
let k = format!("{{{{ {} }}}}", key);
html = html.replace(&k, value);
}
},
None => {},
}
let route_path = format!("/{}", path);
self.route.insert(route_path, html);
}
pub fn up(&self, ip: &str) {
let listenr = TcpListener::bind(ip).unwrap();
for stream in listenr.incoming() {
match stream {
Ok(stream) => {
let _ = handle_connection(stream, self.route.clone());
}
Err(e) => {
println!("Connection failed: {}", e);
}
}
}
}
}
MVCモデルにしたい…