WOCGISendResponse

2007/03/30 (Fri) 22:07:46 JST

if (resp != NULL) {
  sendResponse(resp);
  resp_free(resp);    /* dump the response */
}

#if defined(FINDLEAKS)
WOFREE(url);       /* just for neatness */
st_free(options);
req_free(req);
showleaks();
#endif

return 0;

いよいよmain()の最後です。 といってもこれも簡単で、前処理で返ってきたレスポンスをブラウザに送り、そのレスポンスを解放します。 マクロの部分はメモリリークがあったときの処理です。

sendResponse()

static void sendResponse(HTTPResponse *resp)
{
   String *resphdrs;

   fprintf(stdout,
           "Status: %d %s" CRLF,
           resp->status,
           resp->statusMsg);
   resphdrs = resp_packageHeaders(resp);
   fputs(resphdrs->text,stdout);
   str_free(resphdrs);
   fputs(CRLF,stdout);

   /* content_valid はHEADリクエストか空のレスポンスのとき、0になる */
   if (resp->content_valid) {
      while (resp->content_read < resp->content_length) {
         fwrite(resp->content,
                sizeof(char),
                resp->content_valid,
                stdout);
         resp_getResponseContent(resp, 1);
      }
      fwrite(resp->content,
             sizeof(char),
             resp->content_valid,
             stdout);
   }
   fflush(stdout);
}

それでは、アダプタ最後の処理を見てみましょう。 まずはデータ構造から。

String (wastring.h)

typedef struct _String {
  unsigned int bufferSize;     /* データのバッファサイズ */
  unsigned int length;         /* 文字数 */
  struct _String *next;        /* Stringを連結するときに使う */
  char *text;                  /* 文字列、終了はnull */
  char cached;                 /* キャッシュされているなら真 */
} String;

可変文字列ですね。 str_と頭につく関数はこのデータを操作する関数です。

レスポンス送信で最初にすることは、HTTPヘッダの出力(CGIアダプタの出力先は標準出力)です。 HTTPヘッダは resp_packageHeaders() でString構造体にまとめてから出力します。 HTTPヘッダを1行ずつ生成し、Stringに追加していきます。

resp_packageHeaders() (response.c)

String *resp_packageHeaders(HTTPResponse *resp)
{
  String *result;
  result = str_create(NULL, 1000);
  if (result)
    st_perform(resp->headers,
               (st_perform_callback)resp_appendHeader,
               result);
  return result;
}

resp_appendHeaders() (response.c)

static void resp_appendHeader(const char *key,
                              const char *val,
                              String *headers)
{
  str_append(headers, key);
  str_appendLiteral(headers, ": ");
  str_append(headers, val);
  str_appendLiteral(headers, "\r\n");
}

ヘッダを出力したら、次にコンテントデータを出力します。 HTTPResponseの content_valid にはコンテントデータの有効なサイズです。 HEADリクエストが来たり、空のレスポンス(コンテントデータがない)場合は 0 になります。

レスポンスのコンテントデータはアプリケーションが持っており、 resp_getResponseContent で取得します。 2番目の引数が 0 なら一度に、1 ならストリーミングで少しずつデータを取得します。 このとき取得したデータサイズの分だけ content_read が進みます。 content_length 分データを取得したら、最後に取得したデータを出力し、出力のバッファフラッシュを行って終了です。


Inverse Pages: WOCGIAdaptor