【Servant】 (1) Wai

[【Servant】(1) Wai - Qiita](https://qiita.com/sand/items/16a6ef431a8376e7cbaa)
[【Servant】(2) Servantチュートリアル - Qiita](https://qiita.com/sand/items/fea7c294dd7835692ff7)
[【Servant】(3) エンドポイントを増やす - Qiita](https://qiita.com/sand/items/3af359b1830453d1d0ed)
[【Servant】(4) URLパラメータをハンドラの引数とする - Qiita](https://qiita.com/sand/items/d1c0bfb84487a1dfa9bb)
[【Servant】(5) JSON - Qiita](https://qiita.com/sand/items/fd2ea8acdc56998d5c5e)
[【Servant】(6) HTML - Qiita](https://qiita.com/sand/items/0e9f3c80b5103b966be4)
[【Servant】(7) Post Data - Qiita](https://qiita.com/sand/items/d21aed7c24521e20f1cb)
[【Servant】(8) Another Monad - Qiita](https://qiita.com/sand/items/9c8fa50815b00daead24)
[【Servant】(9) Handlerモナド - Qiita](https://qiita.com/sand/items/ae649f14f1b598d636c3)
[【Servant】(10) SQLite - Qiita](https://qiita.com/sand/items/091b0ea981152ad7d744)
[【Servant】(11) Servant-Client - Qiita](https://qiita.com/sand/items/a0e7758da7274a119849)
[【Servant】(12) Basic 認証 - Qiita](https://qiita.com/sand/items/dba678cef365fbd23ae3)





[Web Application Interface :: Yesod Web Framework Book- Version 1.6](https://www.yesodweb.com/book/web-application-interface)
[wai: Web Application Interface. - Hackage](https://hackage.haskell.org/package/wai)

ここ数年間、Haskellから遠ざかっていましたけど、「プログラミングHaskell 第2版」をきっかけに、再び戻ってきました。ちょうどstackが出たころに離れたので、stackを使うのは新鮮な感じです。

今回はServentを少し調べてみたいと思います。最初はWaiから始めます。

#1. WAI & Warp

WAI & Warpの説明です。

* WAI: web applications と web servers の間のコミュニケーション・プロトコルを提供するものです。
* Warp: WAIをハンドリングするためのWebサーバです。A fast, light-weight HTTP server 


#2. サンプルを動かす

stackでテスト環境を構築します。

```
stack new wai-test
cd wai-test
```

wai,warp,http-typesの3つのパッケージを導入するためにpackage.yamlに3行追加します。

```yaml:package.yaml
dependencies:
- base >= 4.7 && < 5
- wai
- warp
- http-types
```

Hackageのサンプルを使います。

```haskell:app/Main.hs
{-# LANGUAGE OverloadedStrings #-}
import Network.Wai
import Network.HTTP.Types
import Network.Wai.Handler.Warp (run)

app :: Application
app _ respond = do
    putStrLn "I've done some IO here"
    respond $ responseLBS
        status200
        [("Content-Type", "text/plain")]
        "Hello, Web!"

main :: IO ()
main = do
    putStrLn $ "http://localhost:8080/"
    run 8080 app
```

コンパイルします

```
stack build
```

実行します。warpサーバが起動します


```
stack exec wai-test-exe
```

curlコマンドでアクセスすると、以下の出力が確認できます。

```
$ curl  http://localhost:8080
Hello, Web!
```

この時、サーバ側のコンソールには以下のログが出力されます。

```
I've done some IO here
```

#3. 型を確認する

それではプログラムの型を確認していきましょう。

[Network.Wai - Hackage - Haskell](http://hackage.haskell.org/package/wai-3.2.2.1/docs/Network-Wai.html)

Application型とresponseLBS型について確認します。

```
type Application = Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived

responseLBS :: Status -> ResponseHeaders -> ByteString -> Response
```

Applicationのコードです。

```
app :: Application
app _ respond = do
    putStrLn "I've done some IO here"
    respond $ responseLBS
        status200
        [("Content-Type", "text/plain")]
        "Hello, Web!"
```
少し詳細に確認します。

* appはIO ResponseReceivedであり、do構文の途中に任意のIO文を挿入できます。
* appの第1引数はRequest型ですが、_ とある通り無視されています。
* appの第2引数はrespond::(Response -> IO ResponseReceived) です。
* respondはresponseLBSでbuildされたResponseを引数として、IO ResponseReceived型の値を返します。

responseLBSはResponse composersと呼ばれ、その他にもresponseFileやresponseStreamなどがあります。

次にWAIをハンドリングするlight-weight HTTP serverであるwarp(run)の型を確認します。

[Network.Wai.Handler.Warp - Hackage - Haskell](http://hackage.haskell.org/package/warp-3.3.6/docs/Network-Wai-Handler-Warp.html)


```
type Port = Int
run :: Port -> Application -> IO ()
```


今回は以上です。