RustでHttpServer

# 概要
[rosettacodeにあったコード](http://rosettacode.org/wiki/Hello_world/Web_server#Rust)をほとんどそのまま書くので、自分で作ったというのではなくrosettacodeにあるコードが
どうなっているかということをゆっくり見ていく。また、Rustについては初心者のため、もっと理解したらその都度更新していく。

rosettacodeとは何なのかというと以下のとおり。私は知らなかった。
>「Rosetta Code」は、「いろいろなタスク(例題)を、様々なプログラミング言語で書いたらどうなるか」を比較できるプログラミング言語の名句集サイトです。
> https://www.softantenna.com/wp/webservice/rosetta-code/



# やってみる(というか見てみる)

## 全体のコード
まず全体のコードが以下。これを分解してみていく。

```rust
use std::net::{Shutdown, TcpListener};
use std::thread;
use std::io::Write;
 
const RESPONSE: &'static [u8] = b"HTTP/1.1 200 OK\r
Content-Type: text/html; charset=UTF-8\r\n\r
<!DOCTYPE html><html><head><title>Bye-bye baby bye-bye</title>
<style>body { background-color: #111 }
h1 { font-size:4cm; text-align: center; color: black;
text-shadow: 0 0 2mm red}</style></head>
<body><h1>Goodbye, world!</h1></body></html>\r";
 
 
fn main() {
    let listener = TcpListener::bind("127.0.0.1:8080").unwrap();
 
    for stream in listener.incoming() {
        thread::spawn(move || {
            let mut stream = stream.unwrap();
            match stream.write(RESPONSE) {
                Ok(_) => println!("Response sent!"),
                Err(e) => println!("Failed sending response: {}!", e),
            }
            stream.shutdown(Shutdown::Write).unwrap();
        });
    }
}
```

## 宣言等

```
use std::net::{Shutdown, TcpListener};
use std::thread;
use std::io::Write;

const RESPONSE: &'static [u8] = b"HTTP/1.1 200 OK\r
Content-Type: text/html; charset=UTF-8\r\n\r
<!DOCTYPE html><html><head><title>Bye-bye baby bye-bye</title>
<style>body { background-color: #111 }
h1 { font-size:4cm; text-align: center; color: black;
text-shadow: 0 0 2mm red}</style></head>
<body><h1>Goodbye, world!</h1></body></html>\r";
```
しょっぱなではあるが、ここはこういうものなのかな、で済ませる。
定数`Response`の型が`&'static [u8]`として宣言されている理由は、この後見ていくがResponseを返す際に`write()`を使用する。この`write()`が引数として`u8`のデータを期待するため`&'static [u8]`となっている。

`'static`については[ライフタイム](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/book/lifetimes.html#static)の記事を読んでみて、ライフサイクル全体で有効にしておきたい変数を定義する際に必要な記述なんだろうと解釈した。

## TCPリスナーの作成

```
let listener = TcpListener::bind("127.0.0.1:8080").unwrap();
```
`bind()`は引数に指定されたアドレスをもとに新しいTcpListerを作成する。
また、`Result<TcpListener>`型でデータが返ってくるため`unwrap()`をして内包されるTcpListerを取得する。
今回は`bind()`のアドレスは1つしか指定していないが、
以下のように指定することでポート80への接続で失敗した際にポート443に向いたTcpListerを作成することもできる。

```rust:複数指定
let addrs = [
    SocketAddr::from(([127, 0, 0, 1], 80)),
    SocketAddr::from(([127, 0, 0, 1], 443)),
];
let listener = TcpListener::bind(&addrs[..]).unwrap();
```

参考
[TcpLister - bind](https://doc.rust-lang.org/std/net/struct.TcpListener.html#method.bind)
[unwrap()について](https://ja.stackoverflow.com/questions/1730/rust%E3%81%AEunwrap%E3%81%AF%E4%BD%95%E3%82%92%E3%81%99%E3%82%8B%E3%82%82%E3%81%AE%E3%81%A7%E3%81%99%E3%81%8B)

## Listenをする部分

```
for stream in listener.incoming() { ... }
```
`incoming()`メソッドを利用するとIncoming構造体を取得することができる。
これは対象のTcpListerに対する接続要求を待ち続けるイテレータであるためループ処理を利用してListenをさせる。

参考
[Incoming](https://doc.rust-lang.org/std/net/struct.Incoming.html)

## thread作成

```
thread::spawn(move || { ... })
```
`thread::spawn`はスレッド生成の標準ライブラリである。スレッドを動かす際の基本的な形は`thread::spawn(|| { ... })`であり、渡された無名関数が別スレッドで動作する。
今回は生成したスレッドにおいて変数`stream`を使用したい。そのためには、所有権の問題にぶち当たってしまうため`stream`のコピーの所有権を渡るようにするために、基本構文にmoveキーワードを付与する。

参考
[Rustでマルチスレッドプログラミングのメモ](http://totem3.hatenablog.jp/entry/2017/05/10/210000)


## レスポンスをする

```
let mut stream = stream.unwrap();
match stream.write(RESPONSE) {
    Ok(_) => println!("Response sent!"),
    Err(e) => println!("Failed sending response: {}!", e),}
stream.shutdown(Shutdown::Write).unwrap();
```
Incomingオブジェクトをループした際に取得した`stream`の型は`Result<TcpStream>`である。したがって`unwrap()`をすることでTcpStream型のデータを取得することができる。

コネクションを通じたデータのやり取りは`read()`もしくは`write()`を通して行わる。今回はレスポンスだけを行うので`write()`を使用する。`write()`の結果が成功した場合は`Ok`が呼ばれ失敗した場合は`Err`が呼ばれる。

参考
[matchの使い方](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/book/match.html)

また、個々の接続は閉じられる必要があるため`shutdown`メソッドを利用して閉じる。今回はwriteしか行っていないので引数として`Shutdown::Write`を指定するが、readを行う場合は`Shutdown::Read`、両方を使用した場合は`Shutdown::Both`を使用する。ところで最後に`shutdown`メソッドの戻り値に対して`unwrap()`をする理由はわからなかった。どこで使われるわけでもない値なので、必要ないと思ったが…、ご存知の方がいればアドバイスをいただきたく思います。

# 結果
ちゃんとブラウザで結果を表示させることができた。
また、コンソール側でも`Response sent!`が表示された(なぜか3回出た…)。
(2018/5/7追記 3回出た理由はわかりませんが、2回表示される理由は以下のコメントにあります。)
もっと理解を深めて言葉を正確に使った解説をしていけるようになりたい。

```
Compiling hello_cargo v0.1.0 (file:///xxx/rust/hello_cargo)
 Finished dev [unoptimized + debuginfo] target(s) in 0.91 secs
  Running `target\debug\hello_cargo.exe`
Response sent!
Response sent!
Response sent!
```

# 参考
https://gist.github.com/mjohnsullivan/e5182707caf0a9dbdf2d