Webサーバーをつくるときは、Hyperというのがデファクトらしいので、これを使ってみます。(Webアプリケーションフレームワークとしてはまた別で、IronとかRocketとかがある。)

今回のコードサンプルは以下。
https://github.com/yo1000/rust-hyper/tree/705dc5ca10

要件

  • Rust 1.31.1
  • Cargo 1.31.0
$ rustc -V
rustc 1.31.1 (b6c32da9b 2018-12-18)

$ cargo -V
cargo 1.31.0 (339d9f9c8 2018-11-16)

プロジェクトの作成

プロジェクトを作成して、プロジェクトルートに移動しておきます。

$ cargo new --bin rust-hyper
     Created binary (application) `rust-hyper` package

$ cd rust-hyper/

依存関係

Cargo.tomlを編集して、hyperと、JSONを扱う場合によく使用されるserde_jsonを依存に追加しておきます。

[dependencies]
hyper = "0.12.20"
serde_json = "1.0.35"

エンドポイントの記述

ほんとはもう少しちゃんとヘッダー構築したほうが良いのかもしれないけど、まあちゃんと動きます。/helloはステータスOKでJSONを返却し、それ以外のリクエストはステータスNOT_FOUNDとしています。

extern crate hyper;
#[macro_use]
extern crate serde_json;

use hyper::{Body, Method, Response, Server, StatusCode};
// Used for map_err
use hyper::rt::Future;
use hyper::service::service_fn_ok;

fn main() {
    let addr = ([127, 0, 0, 1], 3000).into();

    let new_svc = || {
        service_fn_ok(|_req|{
            match(_req.method(), _req.uri().path()) {
                (&Method::GET, "/hello") => {
                    Response::builder()
                        .status(StatusCode::OK)
                        .header("X-HELLO", "world")
                        .body(Body::from(json!({
                            "message": "Hello, World!"}).to_string()))
                        .unwrap()
                },
                (_, _) => {
                    Response::builder()
                        .status(StatusCode::NOT_FOUND)
                        .body(Body::from("Not found"))
                        .unwrap()
                }
            }
        })
    };

    let server = Server::bind(&addr)
        .serve(new_svc)
        .map_err(|e| eprintln!("server error: {}", e));

    hyper::rt::run(server);
}

Webサーバーの起動

以下のようにコマンドを実行すると、ポート3000でWebサーバーが起動します。

$ cargo run --release
   Compiling rust-hyper v0.1.0 (/xyz/rust-hyper)                                                                                           
    Finished release [optimized] target(s) in 12.85s                                                                                                                                        
     Running `target/release/rust-hyper`

cURLで確認してみると、JSONとともに、設定したヘッダーもしっかり出力されています。

$ curl -v localhost:3000/hello
*   Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 3000 failed: Connection refused
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 3000 (#0)
> GET /hello HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< x-hello: world
< content-length: 27
< date: Mon, 14 Jan 2019 01:23:19 GMT
<
* Connection #0 to host localhost left intact
{"message":"Hello, World!"}

参考