Domino Web Server APIで自作Web APIは作ることはできるのか?プロローグ

Domino Web Server API、略してDSAPI。いわゆるHTTPタスクのアドインです。HTTPタスクに介入できるようになったのは、R5からだったと記憶しています。

昔からDSAPIで標準提供されているものに、Domino Offline Service(DOLS)がありますし、DSAPIではないですが、iNotesやXPagesなどもDSAPIを起点にしてHTTPタスクに統合されていったのではないかと勝手に想像しています。

Domino Data Service(DDS)は、DominoサーバをREST/WebAPI化する強力なサービスで、ググると8.5.3 SP1からの提供であるようですが、これ以前に、自前でRESTサービスをDominoに組み込めないか、よく思案したものです。

DDSはJSONでレスポンスを返すので、Node.jsやJavaScriptフロントエンドなどと相性もよく、標準のデータベースアクセスのほかにカレンダーに特化したものもあり、機能的にはそんなに遜色ない出来だと思っています。

でも、使い込んでくると欲が出てくるもので、「ああ!こんな機能があったらいいのに!!!」と思ったことは一度や二度ではなかったですね。

そんなわけで、これまた昔からの小さな夢を、実現してみようかと思い立ち、自作Web APIを作ってみることにしました。今回はそのプロローグ、Hello,Worldです。

OSとDominoはWindows、ライブラリはVS2013 32bitとQt5.6、Dominoは9.0.1です。VSモジュール(msvcr120.dll、msvcp120.dll)とQtCoreのDLLを、パスで解決できる場所に置きます。DSAPIを使ったアドインDLLは、他のアドインと違って序数1によるエキスポートは不要ですが、Cリンケージ(extern “C”)にしておく必要があります。

DSAPIは、関数やシンボルなどを「FilterXXXX」と命名しているように、基本的にHTTP処理のフィルタリングを主目的としているようです。処理できる段階は、リクエストの受付時からレスポンスの返しまでの一般的なものから、認証処理時、名前リスト構築時など、認証機能を備えたDominoならではのタイミングもあります。今回は、認証済みのタイミング(kFilterAuthorized)を使ってみました。

Webブラウザなどから、http://domino.server/csapi/とたたくと、Hello~とプレーンテキストで返すだけの単純なサンプルは、以下の通りです。

main.cpp

#include <QByteArray>

#pragma pack(push, 1)
#include <global.h>
#include <dsapi.h>
#include <addin.h>
#pragma pack(pop)

extern "C"
__declspec(dllexport) uint FilterInit(FilterInitData* pInitData)
{
  pInitData->appFilterVersion = kInterfaceVersion;
  pInitData->eventFlags = kFilterAuthorized;
  strcpy(pInitData->filterDesc, "Chiburu Systems API");
  AddInLogMessageText("Chiburu Systems API Started.", NOERROR);
  return kFilterHandledEvent;
}

extern "C"
__declspec(dllexport) uint HttpFilterProc(
    FilterContext* ctx
    , uint eventType
    , void* /*ptr*/
    )
{
  uint errID;
  switch (eventType)
  {
  case kFilterAuthorized:
  {
    FilterRequest request;
    ctx->GetRequest(ctx, &request, &errID);
    QByteArray url(request.URL);
    if (url.startsWith("/csapi/") && request.method == kRequestGET)
    {
      QByteArray buffer(request.version);
      buffer += " 200 OK\r\n";
      buffer += "Content-Type: text/plain\r\n";
      buffer += "\r\n";
      buffer += "Hello, Chiburu Systems Web API!\r\n";
      ctx->WriteClient(ctx, buffer.data(), buffer.size(), 0, &errID);
      return kFilterHandledEvent;
    }
  }
    break;
  }
  return kFilterNotHandled;
}

訂正(2017/4/10)

誤:Domino Server API => 正:Domino Web Server API 誤:\n => 正:\r\n