RustでシンプルなWebサーバー
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!"}