Ocsigen/EliomでWebアプリを作る (フォームの設置編)

今回書いた全ソースコードはgithubのリポジトリのtut3ディレクトリにあります.

前回はローカルの手書きHTMLからサービスに向ってPOSTリクエストを投げましたが,今回はリクエストを投げるHTMLをWebアプリで出すようにします.その前の準備として前回のままだと不都合があるので,main_serviceを 1. サービスを受け持つ部分 2. ページを出力する部分 の2つに分割します.

let main_service =
  Eliom_services.service
    ~path:["index"]
    ~get_params:unit
    ()
 
let comment_service =
  Eliom_services.post_service
    ~fallback:main_service
    ~post_params:(string "name" ** string "comment" ** string "submit")
    ()
 
let main_page =
  register
    ~service:main_service
    (fun () () -> (* HTML出力部.あとでフォームを出力するように置き換える *) Lwt.return
        (html (head (title (pcdata "")) [])
              (body [p [pcdata "hogehoge"]])))

つまり,register_serviceというのはserviceとregisterを一挙にやってくれていたわけです.

次にHTML出力部をフォームを出力するように置き換えます.

	 let f =
	 (Eliom_output.Html5.post_form comment_service
				       (fun (name, (comment, submit)) ->
					    [p [pcdata "name: ";
					    string_input ~input_type:`Text ~name:name ();
					    pcdata "comment: ";
					    string_input ~input_type:`Text ~name:comment ();
					    string_input ~input_type:`Submit ~name:submit ~value:"Post" ()]]) ()) in
	 return (html (head (title (pcdata "")) [])
                               (body [f]))

Eliom_output.Html5.post_formの最初の引数でどのサービスに向ってリクエストを投げるかを指定し,次の引数でPOSTリクエストのパラメータからどのようなフォームを作るかを指定します.ここでcomment_serviceを参照する必要があったので,serviceとregisterを分割しました.いやlet rec使えば分割しないでも行けたんですけど,ややこしくなるので.

string_inputはEliom_output.Html5.string_inputのことです.まあそんなに難しくないと思います.

こうすることにより,/indexにアクセスするとフォームが表示されるようになります.

Ocsigen/EliomでWebアプリを作る (POSTリクエストの処理編)

今回書いた全ソースコードはgithubのリポジトリのtut2ディレクトリにあります.

POSTを処理するサービスを記述するには,POST単体だけではダメで,そのサービスのURIがGETリクエストされた時の処理も書かないといけません.
EliomではEliom_services.post_service関数の~fallbackにGETを処理するサービスを指定します.~post_paramsにはGETのときと同様にパラメータを記述します.

let comment_service =
  Eliom_services.post_service
    ~fallback:main_service
    ~post_params:(string "name" ** string "comment" ** string "submit")
    ()

サービスでどんなページを表示するかはGETのときと似たような感じです(今回は関数が2つに分割されてるけど).ページの内容を返す関数の第二引数の記述に注意.どうやら(param1, (param2, (param3, …)))と書かないといけないようで.

let comment_page = Eliom_output.Html5.register
    ~service:comment_service
    (fun () (name, (comment, _)) ->
      let message = name ^ "さんのコメント: " ^ comment
      in
      Lwt.return
        (html (head (title (pcdata "")) [])
              (body [p [pcdata message]])));

テスト用のHTMLが以下.

<html>
<head><title>post</title></head>
<body>
<form action="http://localhost:8080/index" method="post">
name: <input type="text" name="name"><br>
comment: <input type="text" name="comment"><br>
<input type="submit" name="submit" value="Submit">
</form>
<body>
</html>

これに適当に入力してsubmitすると以下のようになるはず.

なお,この場合,Eliom_services.post_serviceの~post_paramsにはちゃんとstring “submit”を入れておかないと「パラメータが合わねえよ」と怒られます.パラメータの過不足は許容されないっぽい?
追記: Eliom_parameters.optを使って,opt (string “submit”)と書けばオプショナルなパラメータを作れるようなので不足する分にはよさそうです.

Ocsigen/EliomでWebアプリを作る (とにかく何か表示する編)

まえがき:ここのサンプルはgithubのplus7/ocsigen_tutのtut1/に置いてありますので適宜cloneしてください.

Webアプリはとにもかくにも何かを表示しないといけないことになっているらしいので.とりあえずHello worldしましょう.

ocsigenserverを動かすには設定ファイルが必要なのは前のエントリで環境構築していればわかると思いますが,いったい何が書いてあるんでしょうか.下記のXMLが私が簡略化してみたものです.

<!-- -*- Mode: Xml -*- -->
<ocsigen>
 
  <server>
 
    <port>8080</port>
 
    <logdir>./log</logdir>
    <datadir>./data</datadir>
    <user>ahya</user><!--www-data-->
    <group>ahya</group><!--www-data-->
 
    <commandpipe>/tmp/ocsigen_command</commandpipe>
 
    <charset>utf-8</charset>
 
    <findlib path="/usr/local/lib/ocaml/3.12.1"/>
 
    <extension findlib-package="ocsigenserver.ext.staticmod"/>
    <extension findlib-package="ocsigenserver.ext.ocsipersist-sqlite">
      <database file="./db/file"/>
    </extension>
    <extension findlib-package="eliom.server"/>
 
    <!-- Inclusion of all external configuration files matching *.conf
         from the directory 'dir' (in alphabetical order): -->
    <extconf dir="/usr/local/etc/ocsigenserver/conf.d" />
 
    <host charset="utf-8" hostfilter="*">
      <site path="">
<eliom module="./byoki.cmo" />
      </site>
    </host>
 
  </server>
</ocsigen>

<user>と<group>には自分のユーザー名入れてください.本格運用するときにはApacheのようにwww-dataとか.<logdir><datadir>はその名の通りのものです.mkdirしておいてください.

<commandpipe>はocsigenserverを制御するときに使う名前付きパイプのpathみたいです.再起動無しにモジュールをアップデートしたい時等に使うとか(Updating sites without shutting down the serverのところを参照).

<findlib>にはOCamlのライブラリへのPathが書かれています.普通にインストールしていれば変更の必要はないでしょう.

<extension>の列はocsigenserver内で有効にする拡張機能の一覧です.eliom.serverは古い資料だとocsigen.ext.eliomになってたりするので気をつけましょう.あとeliomはocsipersist-sqliteに依存してるっぽいです.これ書かないとエラーでて死にます.dbディレクトリもmkdirしておいてください.

<extconf>は私もよくわかってないのでそのままにしました.

<host>以下の<site>が核心部分です.<eliom>のmodule属性でどのモジュールに基づいてWebアプリを動かすかを指定します.<site>のpath属性ではどこのディレクトリ以下にこのWebアプリを配置するかを記述します.ここでは何も書いていないのでhttp://localhost:8080/直下でアクセスできます.例えば”exampleapp”と書けばhttp://localhost:8080/exampleapp/となります.

次にWebアプリ本体です.

open Lwt
open Eliom_pervasives
open HTML5.M
open Eliom_services
open Eliom_parameters
open Eliom_output.Html5
 
let main_service =
  register_service ~path:["index"] ~get_params:unit
    (fun () () -> return (html (head (title (pcdata "")) [])
                               (body [h1 [pcdata "Hello work!"]])))

register_serviceはEliom_output.Html5.register_serviceのことです.~pathにはこのサービスがどのpathを受け持つかを書きます.この例だとhttp:/localhost:8080/indexにアクセスするとこのサービスが表示されることになります.~get_paramsにはどのようなGETリクエストのパラメータを取るかを書きます.今回は何も取らないのでEliom_parameters.unitが指定されています.なにかパラメータを取りたい時には~get_params:(Eliom_parameters.int “i”)と書きます.こいつらにチルダがついてるのはOCamlのラベルを使っているからですね.使ってるの初めて見た….最後の関数はどんな内容を返すかの関数です.第一引数にGETのパラメータ,第二引数にPOSTのパラメータが渡されるらしい.今回は何もとらないので()になっています.htmlとかheadとかはHTML5.Mの型で,文字通りhtmlの要素を表しています.
このソースをocamlfind ocamlc -thread -package eliom.server -c byoki.mlでコンパイルした後,ocsigenserver -c kowai.confでサーバを起動すれば,http://localhost:8080/indexにアクセスすると味気のな~いページが表示されるはずです.

Ocsigen/EliomでWebアプリを作る (環境構築編)

日本語情報は3, 4年前くらいには出てるみたいなんですけど最近なさげなので検証も兼ねて作業記録つけますよ.作業環境はDebian sid.

今回は環境構築ということであんまり詳しくは書きませんので適宜リンク先を読んでください.

Ocsigen bundleのインストール

Ocsigen bundleを説明に従ってインストールする.ただしここの記述,抜けがあって,libgdbm-devが追加で必要だったので,必要なパッケージをapt-getするときには気をつけよう.

なお,Ocsigen bundleにはすでにEliomも付属しているので追加で何かする必要はない.

ocsigenserverの動作チェック

root で ocsigenserver または /etc/init.d/ocsigenserver start すれば80番ポートでデフォルトのHTTPサーバが起動するのでブラウザから確認する.It works! と出ているはず(ocsigen server単体のマニュアルより

次はもうちょっと詳しめのチュートリアルのソースコードと設定ファイルをコピペして,My first pageだけでも動かして満足してみよう.とりあえずここまで動けば遊べる態勢になっているはずだ.

次回に続く,かも?