注意を引く画像であるclckwrksは、Happstackに密接にリンクされたWebフレームワークです。
Happstackは、過去7年間にわたって日々のWeb開発のニーズを満たすために進化してきた豊富なAPIを備えた、 優れた機能を備えた Webフレームワークです。 残念ながら、リッチで柔軟なAPIは、単純なものが必要なときに役に立たず、混乱を招く可能性があります。 しかし、多くの人は、Happstackの翼の下に非常にエレガントで使いやすいHappstack Lite Webフレームワークがあることに気付いていません。
まえがき
Happstack Liteは構造がシンプルで、Happstackの使いやすいバージョンです。 それを作成するために、開発者は:
- 単一の
Happstack.Lite
モジュールでWebアプリケーションを開発するために必要なすべての基本的なタイプと機能をコンパイルしたため、必要なモジュールをHappstack.Lite
必要はありません。 - それらは関数にもっとシンプルなシグネチャを与え、モナド変換子を排除し、ほとんどの型クラスを取り除きました。
- このチュートリアルを作成しました。Webアプリケーションの作成を開始するために知っておく必要があるすべての基本事項を2,000語未満で説明しています。
しかし、最も重要なこと-Happstack LiteはHappstackとほぼ完全に互換性があります! Happstack Liteでアプリケーションを開発していて、Happstackの高度な機能が必要な場合は、対応するモジュールをインポートして使用するだけです。
Happstack Liteから通常のプロジェクトに移行するには、4つの小さな変更を加えるだけです。
-
import Happstack.Lite
置き換えimport Happstack.Server
-
simpleHTTP nullConf
serve Nothing
simpleHTTP nullConf
置き換えserve Nothing
-
import Control.Monad (msum)
追加 - 明示的な
decodeBody
呼び出しを追加( 詳細 )
Happstack Liteは、通常のHapptsackと比較して軽量ですが、他のHaskell Webフレームワークとともに完全に機能するフレームワークです。
単純化するために、開発者はHappstackで動作するいくつかの高度なライブラリの使用を放棄しました。 タイプセーフURL、タイプセーフフォーム、HTMLリテラル構文などを備えたフレームワークに興味がある場合は、Happstack Foundationを検討することをお勧めします。 学習曲線は高くなりますが、追加された信頼性には価値があります。 これらのライブラリはHappstackコアの上に構築されているため、このチュートリアルで学習した資料はアプリケーションでも役立ちます。
詳細については、 Happstackクラッシュコースをお読みください( この記事に関心が表明されている場合は翻訳します-約Per )
サーバー起動
まず、いくつかの言語拡張機能が必要です。
{-# LANGUAGE OverloadedStrings, ScopedTypeVariables #-}
次に、いくつかのライブラリを接続します。
module Main where import Control.Applicative ((<$>), optional) import Data.Maybe (fromMaybe) import Data.Text (Text) import Data.Text.Lazy (unpack) import Happstack.Lite import Text.Blaze.Html5 (Html, (!), a, form, input, p, toHtml, label) import Text.Blaze.Html5.Attributes (action, enctype, href, name, size, type_, value) import qualified Text.Blaze.Html5 as H import qualified Text.Blaze.Html5.Attributes as A
アプリケーションを起動するには、
serve
関数を呼び出します。 最初の引数は構成であり、オプションです。 2番目の引数は、Webアプリケーション自体です。
main :: IO () main = serve Nothing myApp
Webアプリケーションのタイプは
ServerPart Response
です。
ServerPart
は
IO
モナドに相当
ServerPart
Webと見なすことができます。
( デフォルトでは、ポート8000が使用されます。つまり、 http:// localhost:8000 / -でアプリケーションを確認できます。
静的アドレス
Webアプリケーションは次のとおりです。
myApp :: ServerPart Response myApp = msum [ dir "echo" $ echo , dir "query" $ queryParams , dir "form" $ formPage , dir "fortune" $ fortune , dir "files" $ fileServing , dir "upload" $ upload , homePage ]
最も一般的な形式では、アプリケーションは静的アドレスにマッピングされるほんの数個のハンドラーです。
dir
、静的パスコンポーネントが正常にマップされた場合にのみハンドラーが実行されるように使用されます。 たとえば、
dir "echo"
はアドレスで正常に機能します
localhost:8000/echo
localhost:8000/echo
。 ハンドラをアドレス
"/foo/bar"
に割り当てるには、
dir "foo" $ dir "bar" $ handler
書くだけです。
各ハンドラーが成功した結果を返すまで、各ハンドラーを順番に適用しようとします。 この場合、
Response
。
msum
を使用してハンドラーのリストを単一のリストに変換します。
最後のハンドラー
homePage
は何にも制限されません( dirは適用されません-およそPer。 )。したがって、他のハンドラーがどれも正常に動作しない場合は常に呼び出されます。
HTMLテンプレート
Webアプリケーションを作成しているため、HTMLページを作成する必要があります。 これにはBlazeを使用できます。Blazeにはチュートリアルもあります。
HTMLテンプレートのテーマは、コミュニティで広く議論されています。 誰もが満足できるテンプレートシステムはないため、Happstackはさまざまなシステムをサポートしています。 このチュートリアルでは、純粋に機能的なコンビネーターに基づいてサポートされているため、Blazeを使用します。 コンパイル時のパターンが好きで、HTML構文が必要な場合は、HSPを検討できます。 コード内のテンプレートに否定的で、外部XMLファイルを好む場合は、Heistを検討してください。
CSS、外部JSファイル、メニューなどのインポートなど、Webアプリケーションのすべてのページに共通の要素を結合するテンプレート関数があると便利です。このチュートリアルでは、非常に単純なテンプレートを使用します。
template :: Text -> Html -> Response template title body = toResponse $ H.html $ do H.head $ do H.title (toHtml title) H.body $ do body p $ a ! href "/" $ " "
次に、メインページは次のようになります。
homePage :: ServerPart Response homePage = ok $ template " " $ do H.h1 "!" Hp " Happstack Lite !" Hp " :" Hp $ a ! href "/echo/secret%20message" $ "" Hp $ a ! href "/query?foo=bar" $ " " Hp $ a ! href "/form" $ " " Hp $ a ! href "/fortune" $ "- ()" Hp $ a ! href "/files" $ " " Hp $ a ! href "/upload" $ " "
ok
関数は、ページのHTTPコード「200 OK」を設定します。 他の補助関数があります。たとえば、
seeOther
はコードを「404 Not Found」に
seeOther
します。その他は「303 See Other」に
seeOther
します。 HTTPコードを数値で
setResponseCode
、
setResponseCode
使用されます。
住所の動的な部分
dir
関数は、アドレスの静的部分のみに一致します。
path
関数を使用して、アドレスの動的部分から値を抽出し、オプションで
Integer
などのタイプに変換できます。 この例では、パスの動的な部分を表示するだけです。 httpにアクセスして確認するには:// localhost:8000 / echo / fantastic
echo :: ServerPart Response echo = path $ \(msg :: String) -> ok $ template "" $ do p $ " : " >> toHtml msg p " , - ."
リクエストパラメータ
文字列クエリパラメーターの値を取得することもできます。 クエリ文字列は、「
?foo=bar
」のように見えるアドレスの一部
?foo=bar
。 http:// localhost:8000 / queryにアクセスしてみてください?Foo = bar
queryParams :: ServerPart Response queryParams = do mFoo <- optional $ lookText "foo" ok $ template " " $ do p $ "foo = " >> toHtml (show mFoo) p $ " , foo."
クエリパラメータが設定されていない場合、
lookText
関数は
mzero
を返します。 この例では、
Control.Applicative
モジュールの
optional
を使用し、最終的に
Maybe
型の値を取得します。
フォーム
lookText
を使用して、フォームからデータを取得できます。
formPage :: ServerPart Response formPage = msum [ viewForm, processForm ] where viewForm :: ServerPart Response viewForm = do method GET ok $ template "form" $ form ! action "/form" ! enctype "multipart/form-data" ! A.method "POST" $ do label ! A.for "msg" $ " - " input ! type_ "text" ! A.id "msg" ! name "msg" input ! type_ "submit" ! value "" processForm :: ServerPart Response processForm = do method POST msg <- lookText "msg" ok $ template "form" $ do Hp " :" Hp (toHtml msg)
前の段落と同じ
lookText
関数を使用して、フォームからデータを取得します。 また、
method
関数を使用して
GET
要求と
POST
要求を区別していることにお気づきかもしれません。
ユーザーがフォームを表示すると、ブラウザは
GET
を使用して
/form
ページを要求します。 HTML
form
タグでは、ボタンをクリックしたときのアクションとして、同じページを開くことを示しましたが、属性を使用して
POST
メソッドを選択しました。
クッキー! (HTTPクッキー)
この例では、メッセージをCookieに保存することにより、フォームを使用して例を拡張しています。 これは、ユーザーがページを離れることができることを意味します。ユーザーが戻ると、ページは保存されたメッセージを記憶します。
fortune :: ServerPart Response fortune = msum [ viewFortune, updateFortune ] where viewFortune :: ServerPart Response viewFortune = do method GET mMemory <- optional $ lookCookieValue "- ()" let memory = fromMaybe " -!" mMemory ok $ template "fortune" $ do Hp " - ():" Hp (toHtml memory) form ! action "/fortune" ! enctype "multipart/form-data" ! A.method "POST" $ do label ! A.for "fortune" $ " : " input ! type_ "text" ! A.id "fortune" ! name "new_fortune" input ! type_ "submit" ! value "" updateFortune :: ServerPart Response updateFortune = do method POST fortune <- lookText "new_fortune" addCookies [(Session, mkCookie "fortune" (unpack fortune))] seeOther ("/fortune" :: String) (toResponse ())
( 私はどういうわけかHTTP-cookieとfortune cookieの間の駄洒落を保存することができませんでした-およそPer )
前の例と比較して、かなり新しいものが登場しました。
-
lookCookieValue
まったく同じようにlookText
しますが、クエリパラメータやフォームではなく、Cookieの値を検索するという唯一の違いがあります。 -
addCookies
Cookieをブラウザに送信し、次のタイプがあります:addCookies :: [(CookieLife, Cookie)] -> ServerPart ()
-
CookieLife
は、Cookieが存在し、正しいとCookieLife
れるCookieLife
決定します。Session
とは、ブラウザウィンドウが閉じるまでのCookieの有効期間を意味します。 -
mkCookie
は、Cookie名とその値を受け入れ、Cookieを作成します。 -
seeOther
(つまり、303リダイレクト)は、ブラウザに/fortune
ページへの新しいGET
要求を行うように指示します。
ファイルアクセス
ほとんどのWebアプリケーションは、画像、スタイルシート、スクリプトなど、ディスクから静的ファイルへのアクセスを提供する必要があります
serveDirectory
関数を使用してこれを実現できます。
fileServing :: ServerPart Response fileServing = serveDirectory EnableBrowsing ["index.html"] "."
最初の引数
serveDirectory
、
serveDirectory
ディレクトリ内のファイルのリストを作成して表示できるようにするかどうかを決定します。
2番目の引数は、インデックスファイルのリストです。 ユーザーがディレクトリの表示を要求し、インデックスファイルが含まれている場合、ファイルのリストの代わりに表示されます。
3番目の引数は、アクセスが許可されるディレクトリへのパスです。 この例では、現在のディレクトリへのアクセスを提供します。
サポートされているプラットフォーム(Linux、OS X、Windows)では、
serveDirectory
関数は自動的に
sendfile()
を使用してファイルにアクセスします。
sendfile()
は、低レベルのカーネル操作を使用して、最小限のCPU負荷とネットワークチャネルの最大限の使用で、ドライブからネットワークにファイルを転送します。
ファイルの場所
サーバーへのファイルのアップロードの処理は非常に簡単です。 前の例のようにフォームを作成しますが、
lookText
代わりに
lookText
使用し
lookFile
。
upload :: ServerPart Response upload = msum [ uploadForm , handleUpload ] where uploadForm :: ServerPart Response uploadForm = do method GET ok $ template " " $ do form ! enctype "multipart/form-data" ! A.method "POST" ! action "/upload" $ do input ! type_ "file" ! name "file_upload" ! size "40" input ! type_ "submit" ! value "upload" handleUpload :: ServerPart Response handleUpload = do (tmpFile, uploadName, contentType) <- lookFile "file_upload" ok $ template " " $ do p (toHtml $ " : " ++ tmpFile) p (toHtml $ " : " ++ uploadName) p (toHtml $ " : " ++ show contentType)
ファイルがアップロードされると、一時的な場所に保存されます。 サーバーがブラウザに応答を送信すると、一時ファイルは自動的に削除されます。 これにより、未使用のファイルがディスク領域を汚染しないようにします。
ほとんどの場合、ユーザーは削除するためだけにファイルをダウンロードする必要はありません。 通常、ハンドラーで
moveFile
または
copyFile
呼び出して、ファイルを永続的な場所に移動(またはコピー)します。
翻訳者から
この記事の著者は、Haskell言語の基本的な知識があることを前提としています。 Happstackをインストールするには、サイトの指示に従ってください。
このフレームワークに興味がある場合は、フルバージョン(これも翻訳するコース)とそれに基づいたclckwrksを理解することをお勧めします。 素晴らしい開発を!