機能説明(4/5)

WebHook機能とServer Side Script機能

WebHook機能

  • WebHook機能とは、entryへのPOSTまたはPUTの操作をトリガーに、指定されたURLに対してPOST呼び出しを実行する機能です。
  • POST呼び出しで渡されるのはリクエストのentryのselfidだけです。
  • entryにlink rel="via"タグが含まれていることが起動の条件になります。
  • 呼び出しは以下のように、リクエストにlink rel="via"タグを含める場合と親entryに記述しておく場合の2通りあります。 これは以下のようにtitle属性があるかどうかで判断し、もし付いていたら、子entryがPOST/PUTされた時点で実行されます。この場合、リクエスト時には実行されません。
    1. リクエストのentryの中に、<link rel="via" href="http://foo/" />があれば、http://foo/に対してPOSTします。
    2. リクエストのentryの親entryの中に、<link rel="via" href="http://foo/" title="POST,PUT" />があれば、http://foo/に対してPOSTします。子から遡った親entryの全てが対象となります。
  • POST呼び出しは、内部的にはまずTaskQueueが登録され、次にそのTaskからURLFetchが実行されます。(非同期実行)
  • WebHook機能は以下のようなケースで使用されることを想定しています。
    • イベント駆動型の非同期アプリケーションでユーザビリティを高める
      • サーバ処理に時間がかかるようなケースでは、まずリクエストの受付だけを行い、クライアントには直ぐにレスポンスを返します。 その一方で、TaskQueueにWebHookタスクを登録し、非同期に後続の処理を実行します。こうすることで、クライアント側はブロックせずに次の処理をすることができます。
    • メール送信のような非同期型のサービスの実行など

Server Side Script機能

  • Server Side Script機能とは、entryのcontentの中に埋め込んだJavaScriptをサーバで実行する機能です。
    • クライアントもサーバも同じJavaScriptを実行できるため、入力チェックや料金計算などのビジネスロジックを共通化することができます。
  • rhinoを使ってサーバにおけるJavaScript実行を可能にしています。
  • 起動方法はWebHookと同じようにlink rel="via"を使用します。リクエスト時に実行したい場合
    • entryにlink rel="via" type="text/javascript"タグが含まれていることが起動の条件になります。 hrefには、実行したいJavaScriptが埋め込まれたentryのselfid(/js/hello)とメソッド名(setTitle)を#に続けて指定します。
    • 実行結果(OK/NG)をクライアントに返すため通常は同期実行となりますが、hrefに&asyncパラメータを付けることで非同期実行も可能です。この場合、実行結果はログに書かれます。
    • &async=30など、数値を入れることで遅延実行ができます。単位は秒(S)です。
  • サンプル (→ 実行結果)
    javascriptを実行するentryの例(これを実行すると/js/hello3#setTitleが実行され、その結果のentryがPOSTされる)
    
    POST http://tagging-service.appspot.com/d/jstest
    
    <entry>
    <title>JS Test</title>
    <link rel='via' type='text/javascript' href='/js/hello3#setTitle' />
    <link rel='related' href='/jstest/1288587830825' />
    <content>
    Vtec!!
    </content>
    </entry>
    
  • /js/hello3の内容(これを実行するにはR権限が付与されている必要があります)
    javascript templateの例(Hello! + リクエストのcontent + 参照entryの更新日時を結果として返す)
    
    <entry>
    <link href="/js/hello3" rel="self"/>
    <title>JS Template</title>
    <content>
    function setTitle() {
    feed.entry[0].title = "Hello! " + feed.entry[0].content + " " + feed.entry[1].updated;
    }
    </content>
    </entry>
    
  • 親entryに記述しておく場合
    1. GET/PUT/POSTでそれぞれ定義できます。
    2. GETでは実行結果をレスポンスで返すため同期的な実行となりますが、hrefに?asyncパラメータを付けることで非同期的な実行も可能です。この場合、結果をクライアントには返しません。 サンプルのように同期と非同期を組み合わせて定義できるため、GETで実行結果を返した後に非同期にログに記録するような処理を記述できます。
  • サンプル1 (→ 実行結果)
    <entry>
    <title>JS Folder Test</title>
    <link href="/jstest/folder" rel="self"/>
    <link rel='via' type='text/javascript' href='/js/hello3#setTitle' title="GET" />
    <link rel='via' type='text/javascript' href='/js/log#write?async' title="GET" />     // ログ書込を非同期実行
    <link rel='via' type='text/javascript' href='/js/hello4#foo' title="POST" />         // 同期実行
    <link rel='via' type='text/javascript' href='/js/hello4#bar?async' title="POST" />   // 非同期実行
    <link rel='via' type='text/javascript' href='/js/hello5#baz' title="PUT" />
    </entry>
    
  • サンプル2
    • /js/folderにはACLとしてログインが必要な+(any)のCRUDが付いています。また、/js/folder/001のcontentには、1が入っています。
    • Google Acountで実行してください。(→ 実行)
      /js/folderの内容(ログインユーザのnicknameとともにリクエストentryのcontentに1を足して返す)
      
      <entry>
      <id>/js/folder,7</id>
      <link rel="self" href="/js/folder" />
      <link rel='via' type='text/javascript' href='/js/folder#add' title="GET" />
      <content type="text/javascript">
      function add() {
       var val = parseInt(feed.entry[0].content)+1;
       feed.entry[0].content = 'Hello! ' + feed.user.nickname + ' ' + val;
      }
      </content>
      </entry>
      
  • 自分と親の階層にそれぞれ指定されている場合、自分、親、親の親、・・・という順番でチェックします。JavascriptもWebHook同様にすべて実行します。
  • JavaScriptから参照可能な情報について
    • リクエストのentryは、feed.entry[0]に格納されているため、JavaScript内で自由に参照できます。
    • e4xでXMLオブジェクトにアクセスします。
    • link rel='related'を付与することで、entryの外部参照も可能です。 その場合、指定された順にfeed.entry[1]から格納されます。つまり、JavaScriptからは、{"feed" : {"entry" : [{self},{related}・・・{relatedN}] } }のように見えています。
  • 以下の情報が参照可能です。
    • リクエストentry
      • feed.entry[0]
    • 外部参照entry
      • feed.entry[1] ~ feed.entry[n]
    • User情報(OpenIdから得られる情報)
      • feed.user.authDomain
      • feed.user.email
      • feed.user.nickname
      • feed.user.federatedIdentity
    • HTTPヘッダ情報
      • feed.request.headers = {"A" : ["xxx", "yyy"]},{"B" : ["zzz"]};
    • URLパラメータ情報
      • feed.request.href
  • JavaScriptから登録/更新可能な情報について
    • JavaScriptから自由に登録/更新できるのはentryです。
    • feed.entry[0]に登録/更新したいentryを代入します。
    • 代入したentryのlink selfが実際の格納先となります。その格納先は実行ユーザの登録/更新権限が付与されている必要があります。また、格納先が自分以外の場合はchain実行できません。
  • Chain実行
    • 以下のようにfeed.entry[0].linkにJavaScript実行を記述するとChainで実行できます。サンプル (→ 実行結果)
      <entry>
      <link href="/js/hello4" rel="self"/>
      <title>JS Template</title>
      <content>
      function setTitle() {
      feed.entry[0].title = "Hello! " + feed.entry[0].content + " " + feed.entry[1].updated;
      feed.entry[0].link = [];
      feed.entry[0].link[0].@rel = "via";
      feed.entry[0].link[0].@href = "/js/hello4#chain";
      feed.entry[0].link[0].@type = "text/javascript";
      }
      function chain() {
      feed.entry[0].summary = "chain is executed: " + feed.entry[0].title;
      }
      </content>
      </entry>
      

    前へ << >> 次へ