Wikiエンジンの開発
13.3 CGIの処理
昨日までで、"runCGI"関数の中の"cgiEnvs"関数まで解析が終わりました。
次は"runCGI"関数の心臓部である"parseCGIRequest"関数を見ていきます。
"parseCGIRequest"関数の定義を見てみます。
parseCGIRequest env input = case method of "GET" -> parseGET env "POST" -> parsePOST env input _ -> parseUnknown
where節は大きいのでまずは省略。
"GET"や"POST"はHTTPリクエストのメソッドでしょうね。
つまり、メソッドの種類で適用する関数を切り換えています。
また"GET"、"POST"以外のメソッドは受け付けない仕様のようです。
一番簡単そうな"parseUnknown"関数から見ていきましょうか。
parseUnknown = HTTPRequest []
"HTTPRequest"は関数ではなく、データコンストラクタです。
こんな感じ。
data HTTPRequest = HTTPRequest { params :: [(String, String)] }
予想ですが、"HTTPRequest"型は、ヘッダとその値のタプルをリスト化したものなのでしょう。
その観点からすると、"GET"、"POST"メソッド以外の場合、ヘッダは全て破棄することになります。
まぁ、仕様外ですからね。
ちょっと順番が前後しましたが、次は"method"関数。
method = getenv "REQUEST_METHOD" env
"env"は、"parseCGIRequest"関数の第1引数です。
これは"cgiEnvs"関数の戻り値を非モナド化したものです。
つまり、
(環境変数名, 環境変数値)
というタプルのリストです。
"method"関数は"getenv"関数を呼び出しています。
すぐ下に定義があります。
getenv key env = fromMaybe "" $ lookup key env
"lookup"関数はお初なので中身を見てみます。
- Preludeモジュール
lookup :: (Eq a) => a -> [(a,b)] -> Maybe b lookup key [] = Nothing lookup key ((x,y):xys) | key == x = Just y | otherwise = lookup key xys
名前から察するに、
第1引数をキーとして、第2引数のタプルのリストの左側要素に一致するタプルを検索して、右側要素を返すみたいですね。
もし見つからなければ"Nothing"を返す。
簡単な例で実験してみましょう。
Prelude> lookup 1 [(1, "1"), (2, "2"), (3, "3")] Just "1" Prelude> lookup 4 [(1, "1"), (2, "2"), (3, "3")] Nothing
まぁ、合ってそうですね。
定義もとってもシンプルですね。
次に"fromMaybe"関数。
定義はこんな感じ。
- Data.Maybeモジュール
fromMaybe :: a -> Maybe a -> a fromMaybe d Nothing = d fromMaybe d (Just a) = a
これもとても分かりやすいですね。
ちょっと乱暴ですが、「"Maybe"外し」という感じでしょうか。
"Nothing"の場合は第1引数を返す。
これも簡単な例で試してみましょう。
Prelude> :m + Data.Maybe Prelude Data.Maybe> fromMaybe 1 Nothing 1 Prelude Data.Maybe> fromMaybe 1 (Just 2) 2
ということで"getenv"関数の機能はこんな感じ。
環境変数の中から、"REQUEST_METHOD"を検索します("lookup"関数)。
もしあれば、そのまま環境変数の値を返します。なければ""を返します("fromMaybe"関数)。
順調、順調。
今日はここまで!
明日は"parseGET"関数、"parsePOST"関数に進みます。