Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Rust で簡易 HTTP サーバーを作ってみよう

1,519 views

Published on

2018/06/26 Rust LT

Published in: Technology
  • Login to see the comments

  • Be the first to like this

Rust で簡易 HTTP サーバーを作ってみよう

  1. 1. Rustで 簡易HTTPサーバーを 作ってみよう Rust LT #1 @helloyuk13
  2. 2. 目次 • 自己紹介 • HTTPサーバーのしくみ • 今回の要件 • Rustで実装する • まとめ
  3. 3. 自己紹介 • とよだゆうき • サイバーエージェント アドテクスタジオ • 言語: Scala, Rust, C++, Java, etc • 興味分野: 並列計算,分散計算,言語処理系 • twitter: @helloyuk13
  4. 4. 今日話すこと • さかのぼること半年前… • Web系の会社に入ったのでHTTPサーバーくらいわからな いと!と思って,簡易HTTPサーバーを作ってみた話 • Rustでやったときに必要だったライブラリの話
  5. 5. HTTPサーバーのしくみ リクエストを受け取って,処理をして,レスポンスを返す HTTPリクエスト HTTPレスポンス あなた Webサーバー なんらかの処理 (リクエストのパース, ルーティングなど)
  6. 6. 今回の要件 • GET のリクエストを受け取り • 中でパスを読み取ってから URL をハンドリングし • それに応じたレスポンスを返す • …以外のことはやりません!笑 がんばりすぎない!
  7. 7. つまり… • Cache とか難しいことを考えないし 🙅 • GET 以外はすべて無視するし 🙅 • パフォーマンスも考えないし 🤷♀️ • セキュリティも考えない 🙅 実用性皆無ですが,HTTPサーバーを勉強するにはこれで十分!
  8. 8. ブラウザで見るとこんな感じ
  9. 9. Rustで実装する • リクエストの受け取り: std::net::TcpStream#read • リクエストのパース: regex (今回は許してください🙏) • URL のハンドリング • レスポンス生成: format! マクロ • レスポンスの書き出し: std::net::TcpStream#write なにをつかったらいいの??
  10. 10. リクエストの受け取り std::net::TcpStream#read use std::net::TcpStream; let mut buf = [0; 512]; self.stream.read(&mut buf).expect("parsing error in stream"); let result: String = String::from_utf8(buf.to_vec()).unwrap();
  11. 11. リクエストでくる文字列 "GET /ja/test/test.html HTTP/1.1rn" "Connection: closern" "Accept: */*rn" "Host: xxx.comrn" "rn" 今回は「リクエストライン」と呼ばれる1行目だけをパースする
  12. 12. リクエストのパース regex crateを使用する extern crate regex; use regex::Regex; static ref REGEX: Regex = Regex::new(r"(.*) /(.*) HTTP/(.*)rn”).unwrap(); let caps = REGEX.captures(&result).unwrap();
  13. 13. URL のハンドリング HTML ファイルを読み込み,それをbodyに入れてレスポンスを返す if req.head.path == "hello" { let content = read_html("./src/static/assets/html/hello.html"); return Response::builder() .status(StatusCode::Ok) .content_type(Mime::Html) .content_length(len2str(&content)) .body(content) .build(); }
  14. 14. URL のハンドリング HTML ファイルを読み込み,それをbodyに入れてレスポンスを返す fn read_html(path: &'static str) -> String { let f = File::open(path).expect("failed to open file."); let mut lines = String::new(); BufReader::new(f).read_to_string(&mut lines).expect( "failed to read file.", ); lines }
  15. 15. レスポンスの生成 format! マクロで整形して,レスポンスの文字列に直す fn into_http_response(res: &Response) -> String { format!("HTTP/1.1 {}rnServer: SimpleRustHttpServerrn Content-Type: {}rnContent-Length: {}rnConnection: Closernrn", &res.head.status, &res.head.content_type, &res.head.content_length) }
  16. 16. レスポンスの書き出し std::net::TcpStream#write use std::net::TcpStream; fn write(&mut self, res: Response) { let res_str = into_http_response(&res); self.stream.write(res_str.as_bytes()).unwrap(); self.stream.write(res.body.as_bytes()).unwrap(); self.stream.flush().unwrap(); }
  17. 17. まとめ • HTTP サーバーのしくみがわかった! • 細かいことを考えなければ,結構簡単につくれる! • Rust のいい練習になる! • 解説しきれなかった部分は https://github.com/yuk1ty/simple-http-server をご覧くださ い.

×