kahua.server

English page

Kahua Release

kahua-web Release

Security Advisory

Event Log

Documentation

For developers

Site info

Related Site

[module] kahua.server

このモジュールはkahua-serverの下で動作するアプリケーショ ンコードを記述する際に、他の様々なkahua.*モジュールへのアプリケーション サーバを作成する際に、様々なkahua.* モジュールへのインタフェースとなる 高レイヤAPIを提供します。

APIには大きく分けて、アプリケーションプログラマ (*.kahuaを書く人) が使 用する手続きと、kahua-server等のスクリプトが使用する手続きとがあります。

             kahua-server
                  |
                  v  API for scripts
        +-------------------+
        |    kahua.server   |
        +-------------------+
                ^   |  API for applications
                |   v
          applications *.kahua

以降、APIをこの二つのタイプに分けて説明します。アプリケーションプログラ マは、API for applicationsの項だけ読めば、kahua.serverモジュールの機能 を使うことができるでしょう。

API for Applications

Kahuaアプリケーションを記述する際に使用するAPIです。普通のアプリケーショ ンプログラマは、この部分を把握しておけば大丈夫です。

環境の問い合わせ

[procedure] kahua-worker-type

初期化時に与えられたworker-typeを返します。例えば"kahua-web"という アプリケーションの中では、"kahua-web"という文字列が返ります。

[procedure] kahua-bridge-name

このアプリケーションへのコールバックをURIとして埋め込みたい場合に、URI のベースとなる文字列を返します。例えば、/cgi-bin/kahua.cgiで呼び出され るCGIブリッジを経由してアクセスされた場合、"/cgi-bin/kahua.cgi"が返りま す。ただし、kahua-shellの中から呼び出した場合は、ダミー値として、 "/kahua.cgi"が返されます。

[procedure] kahua-server-uri

Kahuaサーバを外部から参照するためのuri ("scheme://server:port") を返し ます。ただし、kahua-shellの中から呼び出された場合は、ダミー値として、 "http://localhost" が返されます。

[procedure] kahua-self-uri . path-components

[procedure] kahua-self-uri-full . path-components

現在のアプリケーションサーバ内のリソースのURIを、 path-componentsから構築します。kahua-self-uriはURIのパス部分、 kahua-self-uri-fullはスキーム、サーバ名、ポート番号を含めた絶対URIを返 します。kahua-self-uriもkahua-self-uri-fullも、引数なしで呼ばれた場合は、 返す値を#\/で終端します。

[procedure] kahua-current-entry-name

現在呼び出されているエントリ名を文字列で取得します。well-knownエントリ でない場合は空文字列""が返ります。

ユーザ認証

[procedure] kahua-login username password

kahua.userの機能を使って認証を行い、認証に成功したら kahua-current-user にユーザオブジェクトをセットし、そのオブジェクトを返します。失敗したら #f が返ります。これは、kahua-current-userとkahua.userの機能を簡易に使うための ラッパー手続きです。

[procedure] kahua-logout

(current-kahua-user) に #f を設定するラッパー関数です。より明示的に「ユー ザログインセッションの終了」を示すにはこちらの手続きを使うことを推奨します。

[procedure] kahua-authorized? . roles

kahua.userの機能を使い、すでに適切な権限を持つユーザとしてログイン 状態にあれば #t を、そうでなければ #f を返します。rolesが渡された場合は、 認証済みのユーザが渡されたrolesのどれかひとつ以上に所属しているかどうかが 確かめられます。

[procedure] kahua-current-user context

[procedure] (setter kahua-current-user) context user

session-stateに保持されている、「現在のユーザ」情報をget/setするための 低レイヤ手続きですsession-stateは一般的にはクライアントのクッキーに結び つけられた情報を保存しています(kahua.session参照)。

「現在のユーザ」は、そのユーザ情報を保持していたデータベースとユーザ名 とをペアにして、そのユーザが同一であるかどうかを特定します。

(kahua-current-user) を呼び出すと、現在のデータベース((current-db)で 得られるデータベース)に由来するユーザ情報が「現在のユーザ」として 保持されているかどうかを調べ、見つかればそれを <kahua-user> オブジェクト として返します。見つからなければ #f を返します。

(set! (kahua-current-user) user) のように用いると、「現在のユーザ」を 設定することができます。userには<kahua-user>オブジェクトかユーザ名を 表す文字列、もしくは #f を渡します。ユーザ名を渡した場合、Kahuaは 現在のデータベース内からこのユーザ名で特定される kahua-user> インス タンスを検索し、見つかればそれを「現在のユーザ」として設定し、 見つからなければ #f を「現在のユーザ」として設定します。

これらの手続きはデータベースにアクセスするので、with-dbのダイナミックエ クステント内で呼ばれなければなりません (kahua.persistence参照)。

内部的には、Kahuaは <session-state> オブジェクトの login-states スロット に、ユーザ名とデータベースパスのペアのリストを保持しています。

 ※リリース0.7より前のバージョンのKahuaでは、「現在のユーザ」は単に
   <session-state> オブジェクトの user スロットに、ユーザ名を保持していた
   だけでした。これでは、由来するユーザデータベースが違うにもかかわらず、
   ログイン名が同じであれば同じユーザと見なされてしまい、セキュリティ上
   問題があるため、0.7から現在の仕様に変更されました。

[procedure] with-kahua-user user proc

[procedure] with-kahua-local-user user proc

ログインユーザを一時的に user に変更して proc を実行します。 procの外で補足された継続がproc内で呼び出されると、元のユーザに 戻った後その継続が実行されます。また、procの中で補足された継続が procの外で呼び出されると、ログインユーザをuserに変更した後に 継続が実行されます。with-kahua-userは、同一サイト内の同じデータベースに 由来するログインセッション全てに影響が及びます。with-kahua-local-userは アプリケーション内のコンテキストのみに影響します。

クライアント情報の問い合わせ

Kahuaクライアントから渡された情報は、kahua-serverからKahuaアプリケーション にcontextとして渡ってきます。ここで紹介する手続きを使って、contextにアクセス することができます。

[procedure] kahua-context-ref key . maybe-default

アプリケーションサーバのハンドラに渡されるコンテキスト情報に アクセスするための関数です。keyは文字列またはシンボルです。

コンテキスト情報には、例えばフォームで入力された値 (keyはname属性に与え た文字列)やHTTPのヘッダ情報、state sessionキーで管理されるクライアント 情報("session-state"というキーでアクセス可能)などが含まれます。 maybe-defaultは省略可能な引数で、該当するコンテキスト情報が存在しない場合に 返す値を渡します。省略した場合は #f が指定されたのと同じです。

この手続きは、コンテキスト情報値がリストである場合、そのリストの 最初の要素を返します。

ただし、フォームで渡されるパラメータを扱うなら、後述のエントリポイント のパラメータとして扱う方が自然です。

[procedure] kahua-context-ref* key . maybe-default

kahua-context-refとよく似ていますが、該当するコンテキスト情報が リストとして返されること、maybe-defaultを省略したときのデフォルト値が ()であることが違います。

[procedure] kahua-meta-ref key . maybe-default

contextから、CGIメタ変数を取り出します。maybe-defaultが省略された時は #fが渡されたのと同じです。

[procedure] kahua-cookie-ref key . maybe-default

contextから、COOKIEの値を取り出します。maybe-defaultが省略された時は #fが渡されたのと同じです。

継続エントリポイントの設定

外部からの制御を受け取るポイントを定義するAPIです。Webアプリケーション の場合、これは、worker type(アプリケーション名)の次にくるパス要素として 表現されます。

[macro] entry-lambda entry-formals . body

無名の継続エントリポイントを作成します。Kahuaの内部においては、これは引 数をとらない手続きとして表現されます。この手続きがKahuaアプリケーション 内で評価されると、Kahuaアプリケーションがkahua-serverから受け取るcontext に従ってentry-formalsに含まれるパラメータを束縛し、bodyを評価します。

継続エントリポイントの外部表現は、URLにパス要素として埋め込まれたある種 の文字列です。事前に外部から知ることはできず、リンクとしてたどることし かできません。このため、後述のdefine-entryで名前をつけられた継続エント リポイントに対して無名の継続エントリポイントと呼んでいます。

entry-formalsは、入力パラメータやパス要素を受け取るための仮引数のように 扱われます。書式については、次のdefine-entryの説明を参照してください。

[macro] define-entry (entry-name . entry-formals) . body

[macro] define-entry entry-name (entry-lambda ...)

entry-formalsを引数とし、bodyを処理内容とする継続手続きを作成し、 それをトップレベルでentry-nameという名前に束縛します。また、 entry-name を、外部からの制御を受け取るためのエントリポイント名 として登録します。外部からダイレクトにこのエントリポイントを呼び出すこと ができます。このためwell-knownエントリとかpermanentエントリと呼ばれること もあります。

「外部からの制御を受け取る」とは、define-entryで指定される継続手続きを、 例えば次のURLで起動できるということです。

  http://servername/cgi-bin/kahua.cgi/''worker-type''/''entry-name''

また、entry-nameに束縛された継続手続きは、特殊なSXMLノードである a/cont, form/cont などと一緒に使うことで、継続渡しスタイルでのアプリ ケーション記述を可能にします。

entry-formals は次のような形式の引数リストです。 ([...]は...が省略可能であることを示します)

  ([''arg'' ... ][:keyword ''karg'' ... ][:mvkeyword ''mvkarg'' ... ][:rest ''restarg''])

arg ... には、URIのentry-name の後ろに渡されるパス要素が 文字列として束縛され、パラメータが束縛され、karg ... には HTTPリクエストのクエリパラメータ部分が束縛されます。また、1つの パラメータ名に複数の値が渡ってくる可能性がある場合は、mvkarg ... によって、値(文字列)のリストとして受け取ることができます。 パス要素の数がarg ... より多く、restargが指定されている場合は、 restargに残りがリストとして束縛されます。

例えば、次のようなエントリ定義があるとします。

  (define-entry (name parg1 parg2 :keyword karg1 karg2 :restarg rarg)
     ...)

ここで、次のようなuriがアクセスされると:

  http://host/kahua.cgi/app-type/name/foo/bar/baz/boz?karg1=aa&karg2=bb

define-entryの本体は、次のような変数束縛のもとで評価されます。

  parg1 = "foo"
  parg2 = "bar"
  karg1 = "aa"
  karg2 = "bb"
  rarg = ("baz" "boz")

仮引数に対応する値が与えられなかった場合、仮引数には#fに束縛されます。 (但し、mvkargsとrargは、値が与えられない場合は()が束縛されます)。 対応する仮引数がない値は捨てられます。

Schemeから見ると、entry-nameに束縛される継続手続きは 引数を取らないクロージャです。継続手続きは、その内部で kahua-context-refを使ってクライアントから渡された情報を取り出し、 仮引数への束縛を行っています。

なお、entry-formalsbodyからの継続手続きの 作成は、前述のentry-lambdaマクロによって行われています。 entry-lambdaマクロを直接使うことにより、無名の継続手続きを 簡単に作成できます。

[procedure] kahua-call-with-current-context proc

[procedure] kall/cc proc

現在のcontextとともに継続を捕捉します。次のようなサンプルコードの場合を 考えてみましょう。

(define counter-page
  (let1 *counter* 0
    (lambda (self)
     (html/
      (head/ (title/ "call"))
      (body/
       (h1/ (begin
              (inc! *counter*)
              *counter*))
       (p/ (a/cont/ (@@/ (cont (cut callee self)))
                    "call")))))))

(define (callee return)
  (html/
   (head/ (title/ "callee"))
   (body/
    (h1/ (sys-time))
    (a/cont/ (@@/ (cont return))
             "return caller"))))

(define-entry (caller)
  (kall/cc counter-page))

(initialize-main-proc caller)

例えば http://localhost:8080/kallcc というアプリケーションだったとすると、 最初は、counter-pageで定義されたページ、そのリンクをたどるとcalleeで 定義されたページが表示されます。calleeのページでリンクをたどるとcounter-page に戻りますが、カウンターは進んでいきます。つまり、contextを保存したまま、 counter-pageが実行されているのです。

[procedure] initialize-main-proc thunk

アプリケーションがエントリ名なしで呼ばれた時に起動する引数をとらない手 続きthunkをワーカプロセスに登録します。thunkは継続エントリポイント (有名無名を問わず) でも、ただのサンクでもかまいません。

※この手続きはkahua.serverモジュールで定義されているものではなく、 kahua-server内で定義されている内部手続きですが、アプリケー ション記述の際に使用するため、ここで説明をします。

API for Scripts

kahua-serverが使うAPIです。kahua-serverにかわるアプリケーションサーバを 書くのでなければ、特に使う必要がありません。

[procedure] kahua-init-server worker-type [session-server-id]

kahua.serverフレームワークを初期化します。worker-typeには アプリケーションサーバのタイプを示す文字列を渡します。 この手続きの中でworker idが作成され、kahua.sessionの session-manager-initが呼ばれます。 作成されたworker idを返します。

session-server-idには、session gsidを管理するkahua-keyserv のworker idを渡します。通常の運用では、session-server-idkahua-spvrがkahua-serverを起動する際に コマンドラインオプションを通じて渡されます。

[procedure] kahua-default-handler header body reply-cont default-proc &keyword stale-proc wrapper-proc error-proc eval-proc eval-environment

アプリケーションサーバのhandle-requestから呼び出され、 セッションキーからの継続手続きのディスパッチ等を行います。

header, body, reply-cont にはhandle-requestに渡された ものをそのまま渡します。

kahua-default-handlerはheaderからcontinuation gsidを取り出し、 kahua.sessionのsession-cont-registerで登録された対応する 継続手続きを得て、bodyを伴ってそれを呼び出します。

継続手続きからの戻り値は、まずwrapper-procに渡されます。 wrapper-procのデフォルトはidentityですが、アプリケーションサーバは ここで共通のページテンプレート等を使うことができます。 kahua-default-handlerは、wrapper-procの返り値をreply-contに bodyとして渡します。

headerにcontinuation gsidが与えられていない場合は、 default-procが継続手続きの替わりにbodyを伴って呼び出されます。

continuation gsidに対応する継続手続きが無かった場合、 stale-procに与えられた手続きが替わりに呼び出されます。

default-proc, stale-proc, wrapper-proc等で 補足されないエラーが発生した場合、error-procがエラー例外を 伴って呼び出されます。error-procは適切なエラーページを表現する S式を返さねばなりません。

default-procおよび継続手続きに渡されるcontextはリストの リストで、各リストのcarにはパラメータ名が、cadrにその値が、 共に文字列で与えられます。通常、フォームからのsubmitが あった場合には、フォームパラメータだと思えば良いでしょう。 kahua-default-handlerはそれに追加して、"session-state"という パラメータを渡します。その値はstate session IDと結びつけられた <session-state>オブジェクトです(kahua.session参照)。

headerに"x-kahua-eval"が与えられた場合は、上記のメカニズム ではなく、bodyがS式として評価され、その結果がreply-contへと 渡されます。これは、アプリケーションサーバの管理用インタフェースです。 (将来は、何らかの認証メカニズムを導入するかもしれません)。 評価は、eval-procで指定された手続きにより行われます。 eval-procbodyに渡されたS式、およびeval-environmentに 渡されたモジュールを受け取り、2つの値を返さねばなりません。 最初の値は、評価が成功すれば#t, エラーが発生すれば#fです。 次の値は、評価が成功した場合は各値を文字列表現したもののリスト、 評価が失敗した場合はエラーメッセージです。 eval-procには適切なデフォルトの手続きが設定されているので、 通常はeval-environmentだけを与えてやれば良いでしょう。 eval-environmentのデフォルトはuserモジュールです。

Copyright (c) 2003-2007 Kahua Project Contact | About Us