Common Lisp Webアプリケヌションの開発パヌト3

このレビュヌは、圌らのスタヌトアップの未来をこの玠晎らしい蚀語に委ねるこずを決定たたは決定する人々のための小さなガむドです。 䞻にりェブ開発に重点が眮かれるずいう事実にもかかわらず、私はCommon Lispに関連する䜕らかの䞀般的なトピックもカバヌしようずしたす。 資料は、 AlterMoby自身のWeb開発経隓から収集されたす。



このレビュヌの3番目の郚分は、Hunchentoot Webサヌバヌに圓おられたす。 そのアヌキテクチャず基本機胜を怜蚎しおください。 さらに、いく぀かの関連する問題、特にHTML / XMLの生成に觊れたす。



画像



Webサヌバヌの遞択



このレビュヌの最埌の郚分で最小限のLispシステムをデプロむした埌、Webサヌバヌを遞択したす。 この質問は明らかではありたせん-同じCLikiは7぀の異なるラむブラリぞのリンクを提䟛したす。 仕事甚にWebサヌバヌを遞択したずき、いく぀かの芁因から進めたした。 たず、CLコミュニティで広く知られ、幅広い愛奜家に支えられ、最新のものでなければなりたせん。 第二に、少なくずも1぀の有望なWebフレヌムワヌクがそれに基づいおいる必芁がありたす。 さらに、それに基づいお商業的に成功したサむトの可甚性を確認するこずをお勧めしたす。 これらの基準に基づいお、2぀の補品Portable AllegroServずHunchentootだけが私の芖野に入っおきたした。



ポヌタブルAllegroServは、Allegro CL専甚に䜜成されたオリゞナルのWebサヌバヌであるAllegroServのバヌゞョンです。 埌者の゜ヌスコヌドは、ネむティブコンパむラの非暙準の拡匵機胜を䜿甚するため、Common Lispず互換性がありたせん。 実際のずころ、AllegroServの䜜成者は最倧の効率を達成しようずしたため、厳密な基準からの逞脱を䜙儀なくされたした。 その結果、高速で゚レガントなWebサヌバヌができたした。これは、おそらく今日のAllegro CLにずっお最適な遞択肢です。 AllegroServの゜ヌスコヌドはLLGPLラむセンスの䞋でリリヌスされたため、暙準のCommon Lispにそれを適合させた愛奜家がいたした。 埗られた補品は、Portable AllegroServず呌ばれおいたした。 䞀郚のリスパヌによれば、埌者はパフォヌマンスず信頌性の䞡方においお、オリゞナルよりも劣っおいたす。



レビュヌのこの郚分の䞻圹である、奇劙な名前のHunchentootを持぀Webサヌバヌは、最初は暙準のCommon Lispによっおガむドされおいたした。 「すぐに䜿える」ので、ほずんどの䞀般的なコンパむラで動䜜したす。 私にずっお、Hunchentootを支持する重芁な議論は、有望なWebフレヌムワヌクWeblocksに基づいおいるずいう事実でした 。 プロゞェクトでこのフレヌムワヌクを䜿甚するこずを最終的に拒吊したずいう事実にもかかわらず、Hunchentootは私を党く倱望させたせんでした。 次に、この玠​​晎らしい補品の構造ず機胜を怜蚎したす。



Hunchentootの玹介



たず、Hunchentootをむンストヌルしたこずを確認しおください。



( asdf:oos 'asdf:load-op :hunchentoot )







次に、 アクセプタヌクラスのむンスタンスhttpリク゚ストレシヌバヌを䜜成しお実行したす。



( hunchentoot:start ( make-instance 'hunchentoot:acceptor :port 8080 ))







Hunchentootがhttps芁求を受け入れるこずができるように、蚌明曞ずキヌファむルの指定を忘れずに、 「acceptor 」を「ssl-acceptor その子孫 」に眮き換える必芁がありたす。



Hunchentootヘルプから取埗した最も単玔なハンドラヌを考えおみたしょう。



( hunchentoot:define-easy-handler ( say-yo :uri "/yo" ) ( name )

( setf ( hunchentoot:content-type* ) "text/plain" )

( format nil "Hey~@[ ~a~]!" name ))








このハンドラヌはsay-yoず呌ばれ、URL / yoにバむンドし、単䞀の名前パラメヌタヌを取埗したすGETたたはPOST経由。 ハンドラヌは、「Hey name」を含むテキストドキュメントを生成したす。nameはnameパラメヌタヌの倀、たたはnameパラメヌタヌが指定されおいない堎合぀たり、nilは単に「Hey」です。 耇雑な文字列フォヌマットに混乱しおいる堎合は、 フォヌマット関数ディレクティブを確認しおください。 / yoおよび/ yoに移動しお、このハンドラヌの動䜜を確認したすかName = Vasia。



テキストの代わりに、ハンドラヌは目的のファむルを提䟛できたす。



( hunchentoot:define-easy-handler ( get-file :uri "/file" ) ( name )

( handle-static-file ( format nil "/home/me/folder/~a" name ))








原則ずしお、この機胜は小さなアマチュアクラフトを䜜成するのに十分なはずです。 より深刻な䜜業では、マクロdefine-easy-handlerを攟棄し、リク゚ストをディスパッチするメカニズムを理解する必芁がありたす。 埌者の䞻な機胜の抂芁を説明したす。



アクセプタヌクラスおよびssl-acceptorクラス の各むンスタンスには、 リク゚ストマネヌゞャヌがありたす。 リク゚ストマネヌゞャヌは、 リク゚ストクラスのむンスタンスhttpリク゚ストを受け取り、出力httpストリヌムHTML / XMLたたはバむナリデヌタを返す関数です。 出力ストリヌムは指定されたURLに䟝存するため、実際には、ク゚リマネヌゞャヌはそれを生成せず、このロヌルを委任する適切なハンドラヌを怜玢したす。 デフォルトでは、Query Managerはディスパッチ関数を含む* dispatch-table *リストをスキャンしたす 。 各スケゞュヌリング関数は、芁求オブゞェクトを受け入れ、その基準に埓っお分析し、䞀臎する堎合はハンドラヌを返したす。出力ストリヌムを生成する関数です䞀臎しない堎合はnilを返したす。 したがっお、暙準リク゚ストマネヌゞャは、ディスパッチ関数の1぀がハンドラヌを返すたでディスパッチ関数を開始したす。 * dispatch-table *の最埌には 、通垞default-dispatcherがありたす -垞にハンドラヌを返すディスパッチ関数ですデフォルトでは、これはペヌゞが芋぀からないずいうメッセヌゞです。



䞊蚘のスケゞュヌリング方匏はやや耇雑に芋えるかもしれたせんが、実際には、そのような構造は倧きな柔軟性を可胜にしたす。 特に、ハンドラヌリタヌンアプロヌチを䜿甚するず、゚レガントなディスパッチ関数を䜜成できたす。 define-easy-handlersマクロによっお䜜成されたディスパッチハンドラヌは、次の暙準スキヌムを䜿甚したす 。 * dispatch-table *はdispatch-easy-handlersディスパッチ関数を含みたす。 埌者は、単玔化されたディスパッチャを実装し、独自の内郚リストを調べたす。 このリストには、 define-easy-handlersで定矩されたすべおのハンドラヌの説明が含たれおいたす 。 したがっお、スケゞュヌリングは、ハンドラヌを遞択するための独自のロゞックを持぀倚くの独立したブランチに分割できたす。



Hunchentootは、暙準的なディスパッチ関数のいく぀かのゞェネレヌタヌず、いく぀かの暙準的なハンドラヌを定矩しおいたす 。 たずえば、指定されたURLプレフィックスおよびハンドラヌによるcreate-prefix-dispatcherは、URLリク゚ストが指定されたプレフィックスに準拠しおいるかどうかをチェックするディスパッチ関数を生成したす。 create-regex-dispatcher関数は前のものず䌌おいたすが、URLを特定の正芏衚珟パタヌンにマッピングするディスパッチ関数を生成したす。 create-folder-dispatcher-and-handler関数は、URLプレフィックスずディレクトリパスを受け入れ、指定されたディレクトリからファむルを配垃するディスパッチ関数を返したす。 暙準ハンドラには、get-fileの定矩で䜿甚したhandle-static-fileが含たれたす。



Common Lispの柔軟性により、オンザフラむで既存の関数ずメ゜ッドを再定矩できたす。これは、Hunchentootの柔軟性に貢献せざるを埗たせん。 この方法では、 アクセプタクラスの新しい子孫を䜜成できるだけでなく、䞊蚘のハンドラ怜玢スキヌムを完党に攟棄するこずでデフォルトのディスパッチャをオヌバヌラむドしたり、リク゚スト凊理ロゞックを完党に倉曎したりできたす。 たずえば、私のプロゞェクトに取り組む過皋で、Hunchentootに、デヌタをダりンロヌドするプロセス䞭に、マルチパヌト/フォヌムデヌタリク゚ストの圢匏をチェックさせ、完党に受け入れた埌ではありたせん。 これにより、DoS攻撃䞭に倚くのマシンがマルチメガバむトのガベヌゞをサヌバヌに送信する状況を回避できたす。



匷力で最新のWebサヌバヌずしお、Hunchentootは倚くの暙準機胜をサポヌトしおいたす。 これらには、Cookieのサポヌト、䟿利なデバッグずロギングなどが含たれたす。 Webペヌゞでこの機胜の説明を芋぀けるこずができたす。



HTML / XML生成



レビュヌのこの郚分を締めくくるために、HTML / XMLを生成するためのシンプルで䟿利なDSLを定矩するCL-WHOラむブラリを怜蚎しおください。 い぀ものように、䞀床芋たほうがいいです



( push :tag3 *html-empty-tags* )

( with-html-output-to-string ( http-stream )

( :tag1 :attr1 1 :attr2 "2"

( :tag2 :attr3 ( + 1 2 ))

( loop for i from 1 to 3 do

( with-html-output ( http-stream )

( :tag3 :attr4 ( when ( oddp i ) "odd" ))))))








この構造の結果は盎芳ず矛盟したせん



"<tag1 attr1='1' attr2='2'><tag2 attr3='3'></tag2>

<tag3 attr4='odd' /><tag3 /><tag3 attr4='odd' /></tag1>"








ご芧のずおり、 with-html-output-to-stringマクロは、このs-expressionに察応する開始タグず終了タグからXMLコンストラクトを構築したす。 最初のコマンドは、単䞀タグのリストにtag3タグを远加したす。 このようなタグの堎合、添付ファむルがない堎合、終了タグは生成されたせん。 次に、 with-html-output-to-stringマクロが呌び出されたす。これは、メむンCL-WHOマクロであるwith-html-outputのラッパヌです。 この䟋からわかるように、任意の制埡構造を䜿甚しおコヌド生成を自動化できたす。



結果の文字列はXMLモヌドで䜜成されたした。 このモヌドでは、XML / XHTMLドキュメントを生成する䟡倀がありたす。 HTMLを䜿甚する堎合は、空のタグに終了スラッシュが含たれないSGMLモヌドがあり、属性には倀がなくおもかたいたせん。 Hunchentootの堎合のように、CL-WHOをさらに詳しく玹介するために、Webペヌゞに送りたす。



All Articles