ä»åã¯Rustã䜿ã£ãŠãç°¡åãªHTTPãµãŒããå®è£ ããŠã¿ãŸããããHTTPã¯åçŽã§ããçæŽ»ã€ã³ãã©ãšããŠãå¿ é ãšãªã£ãŠããWebã®æ ¹å¹¹ãšãªãæè¡ã§ããRustã«å¯Ÿããçè§£ãæ·±ãããšåæã«Webã®æ ¹å¹¹ãšãªãHTTPã«ã€ããŠãåŠã³ãŸãããã
HTTPãããã³ã«ãšã¯ïŒ
ãHTTP(Hypertext Transfer Protocol)ããšã¯ãWebãµãŒããŒãšWebãã©ãŠã¶ã®éã§ããŒã¿ããããšãããããã®éä¿¡èŠåïŒãããã³ã«ïŒã§ãã 1990幎æ«ã«ã€ã®ãªã¹ã®ç©çåŠè ãã£ã ã»ããŒããŒãºïŒãªãŒæ°ãšããããŒãã»ã«ã€ãªã¥ãŒæ°ã«ãã£ãŠèšèšãããŸããã
HTTPãããã³ã«ã¯ãRFCãšããŠå ¬ã«çºè¡šãããŠããŸããRFCãšã¯ãIETFãçºè¡ããŠããã€ã³ã¿ãŒãããã«é¢é£ããæè¡ä»æ§ãªã©ãå ±æããããã«å ¬éãããææžã§ãã誰ã§ãèªãããšãã§ããŸãã1996幎ã«HTTP/1.0ã«é¢ãããRFC 1945ããçºè¡šãããç¿å¹Žã«ã¯HTTP/1.1ããRFC2068ããšããŠçºè¡šãããŸããããã®åŸãç¶ã ãšæ¹è¯ããRFCãçºè¡šãããŸãããæè¿ã§ã¯ãããå¹ççã«éä¿¡ãè¡ããHTTP/3ããRFC 9114ããçºè¡šãã話é¡ãšãªããŸãããHTTPã¯ä»ã§ãæ¹è¯ããç¶ããŠããã®ã§ãã
ããã§ã¯ãå®éã«HTTPãããã³ã«ã«ã€ããŠç¢ºèªããŠã¿ãŸããããHTTPã§ã¯ãWebãµãŒããšWebãã©ãŠã¶ãéä¿¡ãè¡ããŸããã€ãŸããæ«ç«¯ã®ã¯ã©ã€ã¢ã³ã(Webãã©ãŠã¶)ãããµãŒãã«æ¥ç¶ããŠããŒã¿ã®éåä¿¡ãè¡ããŸããçããããåãã®ããã«ãWebãã©ãŠã¶ãå©çšããŠWebãµãŒãã«æ¥ç¶ããŠãHTMLãç»åãªã©ã®ããŒã¿ãååŸããŸãã
ãªããããŒã¿ã®éåä¿¡ã«é¢ããŠã§ãããHTTPã§ã¯æ¬¡ã®ãããªæµãã§éä¿¡ãè¡ãããŸãã
(1) ãã©ãŠã¶ã¯ãµãŒããžæ¥ç¶ãã
(2) ãã©ãŠã¶ãããµãŒããžããªã¯ãšã¹ã(Request)ããéä¿¡ãã
(3) ãµãŒããããã©ãŠã¶ãžã®ãã¬ã¹ãã³ã¹(Response)ããè¿ã
(4) æ¥ç¶ãåæãã
ãµãŒãã«æ¥ç¶ãããããªã¯ãšã¹ã(èŠæ±)ã«å¯Ÿããã¬ã¹ãã³ã¹(å¿ç)ããããäžåã®éä¿¡ãåããŸãããã®ããã«ãHTTPã¯åºæ¬çã«ãšãŠãã·ã³ãã«ãªä»çµã¿ã§æãç«ã£ãŠããŸãã
ãã¡ãããæšä»ã®HTTPéä¿¡ã§ã¯æå·åãã»ãã·ã§ã³ç®¡çãªã©ãããè€éãªä»çµã¿ãè¡ãããŠããŸãããæ¬çš¿ã§HTTPã®å šãŠãå®è£ ããã®ã¯ç¡çãªã®ã§ãåºæ¬çãªéšåã ããå®è£ ããŠã¿ãŸãããã
ããã§ã¯ãWebãã©ãŠã¶ã§ã¢ã¯ã»ã¹ããŠãæå®ãã£ã¬ã¯ããªä»¥äžã«ããHTMLãã¡ã€ã«ãè¿ä¿¡ãããšããåºæ¬çãªåŠçãRustã§å®è£ ããŠã¿ãŸãããã
HTTPãµãŒãã®ãããžã§ã¯ãã®äœæ
ããã§ã¯ãRustã§ãããžã§ã¯ããäœæããŸããããã¿ãŒããã«(WindowsãªãPowerShellãmacOSãªãã¿ãŒããã«.app)ãèµ·åããŠãäžèšã®ã³ãã³ããå®è¡ããŸãããã
# ãã©ã«ããäœæããŠç§»å
mkdir my_http_server
cd my_http_server
# ãããžã§ã¯ããåæå
cargo init
ãããŠãsrc/main.rs ãç·šéããŸãã
æãç°¡åãªHTTPãµãŒãã®ããã°ã©ã
以äžã¯æãç°¡åãªHTTPãµãŒãã®ããã°ã©ã ã§ããsrc/main.rsãæžãæããŸãããã
use std::io::prelude::*;
use std::net::TcpListener;
// ãµãŒãã¢ãã¬ã¹ãæå® --- (*1)
const SERVER_ADDRESS: &str = "127.0.0.1:8888";
fn main() {
// HTTPãµãŒããèµ·å --- (*2)
println!("[HTTPãµãŒããèµ·å] http://{}", SERVER_ADDRESS);
let listener = TcpListener::bind(SERVER_ADDRESS).unwrap();
// ã¯ã©ã€ã¢ã³ãããã®æ¥ç¶ãåŸ
ã¡åãã --- (*3)
for stream in listener.incoming() {
println!("ã¯ã©ã€ã¢ã³ããæ¥ç¶ããŸããã");
// ã¯ã©ã€ã¢ã³ããšã®éä¿¡ãè¡ã --- (*4)
let stream = stream.unwrap();
handle_client(stream);
}
}
fn handle_client(mut stream: std::net::TcpStream) {
// ã¯ã©ã€ã¢ã³ãã®ãªã¯ãšã¹ããèªã¿èŸŒã --- (*5)
let mut request_buf = [0; 4096];
let size = stream.read(&mut request_buf).unwrap();
let request = String::from_utf8_lossy(&request_buf);
println!("Request: {}B\n{}\n", size, request);
// ã¯ã©ã€ã¢ã³ããžã¬ã¹ãã³ã¹ãè¿ã --- (*6)
let response = "<h1>Hello, World!</h1>";
stream.write(b"HTTP/1.1 200 OK\r\n\r\n").unwrap(); // ããã
stream.write(response.as_bytes()).unwrap(); // æ¬äœ
stream.flush().unwrap(); // åºå
}
ã¿ãŒããã«ããããã°ã©ã ãå®è¡ããŠã¿ãŸãããã
cargo run
ãããšãHTTPãµãŒããèµ·åããŸãããããŠããã©ãŠã¶ã®åŸ ã¡åãç¶æ ã«ãªããŸããããã§ãWebãã©ãŠã¶ãèµ·åããŠãhttp://127.0.0.1:8888ãã«ã¢ã¯ã»ã¹ããŠã¿ãŸãããããããšã次ã®ããã«è¡šç€ºãããŸããããŸãåããªãã£ãå Žåã¯ã以äžã®è§£èª¬(*1)ãåèã«ããŠä¿®æ£ããŠã¿ãŠãã ãããããã°ã©ã ãçµäºããã«ã¯ã[Ctrl]ããŒãæŒããªãã[C]ããŒãæŒããã¿ãŒããã«ãéããŸãã
ããã°ã©ã ã確èªããŠã¿ãŸãããã(ïŒ1)ã§ã¯ããŒã«ã«ç°å¢ã§WebãµãŒãã®ã¢ãã¬ã¹ãæå®ããŸããããã§ã¯ãèªèº«(localhost)ã衚ãã¢ãã¬ã¹ã127.0.0.1ãã®ããŒã8888çªã§ãµãŒããŒãèµ·åããŸãã
ãªããæ¢ã«ããŒã8888ã§èµ·åããŠãããµãŒãã¹ããããšããµãŒãã¯èµ·åã«å€±æããŸãããã®å Žåã¯ããµãŒãã¢ãã¬ã¹ãã127.0.0.1:8889ãã«å€æŽãããªã©ãé©åœãªçªå·ã«å€æŽããŠè©ŠããŠã¿ãŠãã ããã
(ïŒ2)ã§ã¯å®éã«ãµãŒããèµ·åããŸããããã§ã¯ãTCPãœã±ãããæ±ãRustæšæºã©ã€ãã©ãªãTcpListenerãã®bind颿°ãå©çšããŠãµãŒããèµ·åããŸãããããŠã(ïŒ3)ã§ã¯ã¯ã©ã€ã¢ã³ãããã®æ¥ç¶ãåŸ ã¡åããŸããã¯ã©ã€ã¢ã³ããæ¥ç¶ãããšã(ïŒ4)ã®handle_clientãå®è¡ãããŸãã
(ïŒ5)以éã§ã¯é¢æ°handle_clientã®åŠçãèšè¿°ããŸããããã¯ã¯ã©ã€ã¢ã³ããæ¥ç¶ããŠããéã«è¡ãåŠçã§ãã(ïŒ5)ã§ã¯ã¯ã©ã€ã¢ã³ãã®ãªã¯ãšã¹ããèªã¿ã(ïŒ6)ã§ã¯ã¯ã©ã€ã¢ã³ãã«ã¬ã¹ãã³ã¹ãè¿ããŸãã
ãã®ããã°ã©ã ã§ã¯ãã¯ã©ã€ã¢ã³ãã®ãªã¯ãšã¹ããäœãè§£æãããåçç¡çšã«(ïŒ6)ã§ã<h1>Hello, World!</h1>ããšããHTMLãè¿ä¿¡ããŸãã
ãªã¯ãšã¹ããè§£æããŠHTMLãã¡ã€ã«ãè¿ä¿¡ããã
ããã§ã¯ãå°ãã ããµãŒããããåŠçãããããã«æ¹è¯ããŸããããå ã»ã©ããªã¯ãšã¹ãã«å¯ŸããŠãåžžã«åãå¿çãè¿ãããã«ãªã£ãŠããŸããã®ã§ããã©ãŠã¶ããã®ãªã¯ãšã¹ãããã£ãã確èªããŠãã©ã®ãã¡ã€ã«ãè¿ãã®ã確èªããããã«ããŠã¿ãŸãããã
å ã»ã©äœã£ãããã°ã©ã ã®å®è¡ãã°ã確èªããŠã¿ãŸãããããã©ãŠã¶ã®ãªã¯ãšã¹ãã¯æ¬¡ã®ãããªãã®ã§ããã
GET / HTTP/1.1
Host: 127.0.0.1:8888
Connection: keep-alive
Cache-Control: max-age=0
ãçç¥ã
ç¶ããŠããµãŒããèµ·åããç¶æ ã§ãWebãã©ãŠã¶ã®ã¢ãã¬ã¹ããŒã§ãhttp://127.0.0.1:8888/hoge.htmlãã«ã¢ã¯ã»ã¹ããŠã¿ãŸãããããããšãäžèšã®ããã«è¡šç€ºãããããšã§ãããã
GET /hoge.html HTTP/1.1
Host: 127.0.0.1:8888
Connection: keep-alive
ãçç¥ã
倿Žããã£ãéšåã¯ãªã¯ãšã¹ãã®äžè¡ç®ã§ããäžè¡ç®ãæ¯ã¹ãŠã¿ããšåãããŸãããGET (ååŸããããã¡ã€ã«å) HTTP/(ããŒãžã§ã³)ããšãªã£ãŠããããšãåããã§ãããã
ããã§ãå ã»ã©äœæãããµãŒãã®ããã°ã©ã ã®é¢æ°handle_clientãæ¬¡ã®ããã«æžãæããŠã¿ãŸãããããªããããã°ã©ã å šäœããã¡ãã«ã¢ããããŠããŸãã
fn handle_client(mut stream: std::net::TcpStream) {
// ã¯ã©ã€ã¢ã³ãã®ãªã¯ãšã¹ããèªã¿èŸŒã --- (*1)
let mut request_buf = [0; 4096];
let size = stream.read(&mut request_buf).unwrap();
let request = String::from_utf8_lossy(&request_buf);
println!("Request: {}B\n{}\n", size, request);
// ãªã¯ãšã¹ããè§£æãã --- (*2)
let request_lines: Vec<&str> = request.lines().collect();
// äžè¡ç®ã®ãªã¯ãšã¹ããåãåºããŠã¹ããŒã¹ã§åå² --- (*3)
let request_line = request_lines[0];
let mut parts = request_line.split_whitespace();
// çµæãåãåºã --- (*4)
let method = parts.next().unwrap();
let path = parts.next().unwrap();
let _version = parts.next().unwrap();
println!("Method: {}, Path: {}", method, path);
// ãã¡ã€ã«ãèªã¿èŸŒã --- (*5)
let path = if path == "/" { "/index.html" } else { path };
let fullpath = format!("./html{}", path);
let fullpath = fullpath.replace("..", ""); // ã»ãã¥ãªãã£å¯Ÿç
println!("Fullpath: {}", fullpath);
// ãã¡ã€ã«ãèªã¿èŸŒã --- (*6)
let response = std::fs::read_to_string(fullpath)
.unwrap_or("404 not found".to_string());
// ã¬ã¹ãã³ã¹ãè¿ã --- (*7)
stream.write(b"HTTP/1.1 200 OK\r\n").unwrap();
stream.write(b"Content-Type: text/html; charset=utf-8\r\n").unwrap();
// ããŒã¿æ¬äœãè¿ã --- (*8)
stream.write(b"\r\n").unwrap();
stream.write(response.as_bytes()).unwrap(); // æ¬äœ
stream.flush().unwrap(); // åºå
}
æåã«ããã°ã©ã ã確èªããŠã¿ãŸãããã(ïŒ1)ã§ã¯ã¯ã©ã€ã¢ã³ãã®ãªã¯ãšã¹ããèªã¿èŸŒã¿ãŸããããã¯å ã»ã©ãšåãã§ãã
(ïŒ2)ã§ã¯ãã©ãŠã¶ããéä¿¡ããããªã¯ãšã¹ããè§£æããŸããç¹ã«ãããã§ã¯1è¡ç®ã«æžãããŠãããGET (URL)ãã®éšåãæœåºããŸãããã®ããã«ãæ¹è¡ã§åå²ããåŸã(ïŒ3)ã§å é è¡ãåãåºããããã«ã¹ããŒã¹ã§åºåããŸãããããŠã(ïŒ4)ã§ãªã¯ãšã¹ãã®ããŒã¹çµæãåãåºããŠè¡šç€ºããŸãã
ããã§ã(ïŒ5)ã§ã¯ãããŒã«ã«ã«ããã©ã®ãã¡ã€ã«ãèªãã¹ãããã¹ã解決ããŸããä»åã¯ãhtmlããã£ã¬ã¯ããªä»¥äžã«ãã¡ã€ã«ãé 眮ããä»çµã¿ã«ããŸãããããã§æ°ãã€ãããã®ãããã£ã¬ã¯ããªã®çžå¯Ÿæå®ã®ã..ãã§ããç¹å®ã®ãã£ã¬ã¯ããªããäžã®éå±€ã«ãã¡ã€ã«ãèªããŠããŸããšæ©å¯ãã¡ã€ã«ãæŒæŽ©ããŠããŸãå¯èœæ§ãããã®ã§ãããã§ã¯äžã®éå±€ãžã®ã¢ã¯ã»ã¹ãèš±ããªãããã«ããŠããŸãããã¡ããããããªãã¹ãããã°ã©ã ã§æ¬çªéçšããªããšæããŸãããWebé¢é£ã®ããã°ã©ã ãäœãæã«ã¯ãã»ãã¥ãªãã£æèããã£ããæã€ããšã倧åã§ãã
(ïŒ6)ã§ã¯å®éã«ããŒã«ã«ãã¡ã€ã«ãèªã¿èŸŒã¿ãŸãããã¡ã€ã«ãååšããªããã°ã404 not foundããšããæååãè¿ãããã«ããŸããã
(ïŒ7)ã§ã¯ã¬ã¹ãã³ã¹ãè¿ããŸããããã§ã¯ãHTTP/1.1 200 OKããšããã¬ã¹ãã³ã¹ã³ãŒããšããã®åŸã§HTMLã衚ãMIMEã¿ã€ããšæåã³ãŒããè¿ä¿¡ããŸãããããŠã(ïŒ8)ã§ãã¡ã€ã«ã®å 容ãè¿ä¿¡ããŸãã
ããã§ã¯ãããã°ã©ã ãå®è¡ããŠã¿ãŸããããããã§ã¯ãhtmlãšãããã©ã«ããäœæããŠããã®äžã«ãindex.htmlããšãhoge.htmlãã®2ã€ã®HTMLãã¡ã€ã«ãçšæããŸããããæ¹ããŠãããžã§ã¯ãã®ãã£ã¬ã¯ããªæ§æã確èªããŠã¿ãŸãããã
.
âââ Cargo.toml
âââ html
â  âââ hoge.html
â  âââ index.html
âââ src
âââ main.rs
HTMLãã¡ã€ã«ã®å å®¹ã¯æ¬¡ã®ãããªç°¡åãªãã®ã§ãããªãããã¡ã€ã«åãåããããã«ä¿®æ£ãããšåäœãåãããããã§ãããã
<html><body>
<h1>ãhoge.htmlããããããã«ã¡ã¯ã</h1>
</body></html>
ããã°ã©ã ãå®è¡ããã«ã¯ã次ã®ã³ãã³ããå®è¡ããŸãããããŠããã©ãŠã¶ã§ãhttp://127.0.0.1:8888/hoge.htmlãã«ã¢ã¯ã»ã¹ããŠã¿ãŸãããã
cargo run
ãããšã次ã®ããã«è¡šç€ºãããŸãã
ããŸãè¡ã£ãããhttp://127.0.0.1:8888/index.htmlãã«ã¢ã¯ã»ã¹ããŠè¡šç€ºãããå 容ãå€ãããã確èªããŠã¿ãŸãããã
ãŸãšã
以äžãä»åã¯ãHTTPã®ä»çµã¿ã確èªããªãããRustã§ç°¡åãªHTTPãµãŒããå®è£ ããŠã¿ãŸãããRustã®TCPãœã±ããã©ã€ãã©ãªã䜿ãããããããæã£ããããé£ãããšããå°è±¡ã¯ãªãã®ã§ã¯ãªãã§ããããã
ããã°ã©ã ãèŠããšããšã©ãŒåŠçãç¡èŠããã.unwrapããé »åºããŠããŸãããã¡ãããå®çšçãªãµãŒããäœãå Žåã«ã¯ããã£ãããšãšã©ãŒåŠçãè¡ãå¿ èŠãããããšãåãããŸãããåºæ¬çãªä»çµã¿ã¯çè§£ã§ããããšã§ãããã
ãªããä»åã®ããã°ã©ã ã§ã¯ããµãŒãã®è¿ãã¬ã¹ãã³ã¹ã«å«ããHTTPã®ã¹ããŒã¿ã¹ã¡ãã»ãŒãžããå šãŠã200 OKããšè¿ããŠããŸããæ¬æ¥ãååšããªããã¡ã€ã«ããªã¯ãšã¹ãããããªãããHTTP/1.1 404 Not foundããè¿ãããã«ããå¿ èŠããããŸãããŸããHTMLãè¿ãããšããæ³å®ããŠããªãã®ã§ãMIMEã¿ã€ãããtext/htmlãã§åºå®ããŠããŸããæ¬¡ã®ã¹ããããšããŠãããããåŠçãå®è£ ããŠã¿ããšè¯ãã§ãããã
èªç±åããã°ã©ããŒããããã¯ãã©ã«ãŠãããã°ã©ãã³ã°ã®æ¥œãããäŒããæŽ»åãããŠããã代衚äœã«ãæ¥æ¬èªããã°ã©ãã³ã°èšèªããªã§ããã ãããã¹ã鳿¥œããµã¯ã©ããªã©ã2001幎ãªã³ã©ã€ã³ãœãã倧è³å ¥è³ã2004幎床æªèžãŠãŒã¹ ã¹ãŒããŒã¯ãªãšãŒã¿èªå®ã2010幎 OSSè²¢ç®è ç« åè³ãæè¡æžãå€ãå·çããŠãããçŽè¿ã§ã¯ããå®è·µåãã¢ãããã Pythonã«ããã¢ã«ãŽãªãºã ã®æç§æž(ãã€ããåºç)ããã·ãŽããã¯ãã©ã PythonèªååŠçã®æç§æž(ãã€ããåºç)ããããã«äœ¿ãã!æ¥åã§å®è·µã§ãã! Pythonã«ããAIã»æ©æ¢°åŠç¿ã»æ·±å±€åŠç¿ã¢ããªã®ã€ããæ¹ TensorFlow2察å¿(ãœã·ã )ãããã³ã¬ã§ãã£ããåŠã¶Python(ãã€ããåºç)ããªã©ã



