RustのHyperでNode.jsライクなハンドラーは0.10だと使えていた様子
Hyper 0.10時代には以下のように(req, res)を引数にとったハンドラーが定義できていた様子。ただし、0.12のハンドラーは異なっている。
code:rs
fn main() {
let mut short_uris: HashMap<String, String> = HashMap::new();
let short_uris = std::sync::RwLock::new(short_uris);
Server::http("0.0.0.0:3001")
.unwrap()
.handle(move |req: Request, mut res: Response| match req.method {
hyper::Post => post(req, res, &mut short_uris.write().unwrap()),
hyper::Get => get(req, res, &short_uris.read().unwrap()),
_ => *res.status_mut() = StatusCode::MethodNotAllowed,
})
.unwrap();
}
HyperをSourceTreeで見てみて、0.10系は結構最近も保守されていることがわかった。APIの大きな変更があったし保守を続けているのかもしれない。 https://gyazo.com/b5fc260f8c27e0175c4ee64d3d1f943b
CHANGELOGの「v0.11.0 (2017-06-13)」のセクションの最後の方に以下のように書かれていて、ServerのAPIに大きな変更が入ったと言っている。 https://gyazo.com/2f82658452225f0b3b16f6826cae225f
「d35」から始まるコミットのURLは以下。
このコミットを見ると、handlerがNode.jsライクなものから変更していることがわかる。ただし0.12と同じ理由はなくResponseではなくてNextになっていたりする。
追記:以下のようなものが定義されていることも分かり、Node.jsライクなハンドラ使えるかもしれない。
https://gyazo.com/09171506c227c041b62cc06d512074f6
req, resを引数に取れるハンドラーが今後使えるか
0.12で違う方法でreq, resのハンドラーを使って処理できる方法が存在する可能性はある。ただ上記の事柄を全体を通してみると、req, resを引数に取る形に戻る感じはなさそう。なんで最初はreq, resを引数に取るハンドラーだったのに、変更したのか?理由が気になるところ。実装上そのほうが良いだろうか?
responseを返すというのが自然な感じはわかる。ただlow levelな操作をしたいときは、responseを返すというより、命令的にresponseを作っていく感じが向いている気がしている。理由としてはsocketは双方通信できるものだから。そのためNode.jsのAPIは操りやすかった。reqを少し読んで、それをもとにresにすこしwrite()するみたいな感じで進めていける。FutureやPromiseのresを返すのと違ってlow levelな操作はしやすいのではないかと思っている。
上記のコミットメッセージは「feat(lib): switch to non-blocking (asynchronous) IO」となっており、ノンブロッキングIOの実装がこのほうがしやすかったのだろうか?