Happstack Lite:Haskell Webフレームワーク

画像

注意を引く画像であるclckwrksは、Happstackに密接にリンクされたWebフレームワークです。



Happstackは、過去7年間にわたって日々のWeb開発のニーズを満たすために進化してきた豊富なAPIを備えた、 優れ機能を備えた Webフレームワークです。 残念ながら、リッチで柔軟なAPIは、単純なものが必要なときに役に立たず、混乱を招く可能性があります。 しかし、多くの人は、Happstackの翼の下に非常にエレガントで使いやすいHappstack Lite Webフレームワークがあることに気付いていません。





まえがき



Happstack Liteは構造がシンプルで、Happstackの使いやすいバージョンです。 それを作成するために、開発者は:

  1. 単一のHappstack.Lite



    モジュールでWebアプリケーションを開発するために必要なすべての基本的なタイプと機能をコンパイルしたため、必要なモジュールをHappstack.Lite



    必要はありません。
  2. それらは関数にもっとシンプルなシグネチャを与え、モナド変換子を排除し、ほとんどの型クラスを取り除きました。
  3. このチュートリアルを作成しました。Webアプリケーションの作成を開始するために知っておく必要があるすべての基本事項を2,000語未満で説明しています。


しかし、最も重要なこと-Happstack LiteはHappstackとほぼ完全に互換性があります! Happstack Liteでアプリケーションを開発していて、Happstackの高度な機能が必要な場合は、対応するモジュールをインポートして使用するだけです。

Happstack Liteから通常のプロジェクトに移行するには、4つの小さな変更を加えるだけです。

  1. import Happstack.Lite



    置き換えimport Happstack.Server



  2. simpleHTTP nullConf



    serve Nothing



    simpleHTTP nullConf



    置き換えserve Nothing



  3. import Control.Monad (msum)



    追加
  4. 明示的な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



前の例と比較して、かなり新しいものが登場しました。

  1. lookCookieValue



    まったく同じようにlookText



    しますが、クエリパラメータやフォームではなく、Cookieの値を検索するという唯一の違いがあります。
  2. addCookies



    Cookieをブラウザに送信し、次のタイプがあります: addCookies :: [(CookieLife, Cookie)] -> ServerPart ()



  3. CookieLife



    は、Cookieが存在し、正しいとCookieLife



    れるCookieLife



    決定します。 Session



    とは、ブラウザウィンドウが閉じるまでのCookieの有効期間を意味します。
  4. mkCookie



    は、Cookie名とその値を受け入れ、Cookieを作成します。
  5. 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を理解することをお勧めします。 素晴らしい開発を!



All Articles