nine HTTPサーバーは、HTTP から Upgrade するプロトコルもサポートしているので、どのプロトコルに対するサーバーなのかを区別する必要がある。 通常の HTTP 要求・応答に対するサーバーを、デフォルトHTTPサーバーと称している。
サンプルのHTTPサーバーは、クライアントから来るメッセージを受信し、カウントするだけのものである。
class Server
: public nine::HttpServer
, public nine::HttpHandler
{
public:
Server();
virtual ~Server();
bool init(int nComms);
void run();
inline void enableDump(bool b) { m_bDump = b; }
public:
virtual HttpHandler* authorizeHttp(int cid, const HttpRequest* pReq);
virtual void onHttpRequestHeader(HttpChannel*, const HttpRequest* pReq);
virtual void onHttpRequest(HttpChannel*, const HttpRequest* pReq, Buffer* pBuf, HttpResponse* pRes);
virtual void onHttpResponse(HttpChannel*, const HttpResponse*, bool succeed);
デフォルトHTTPサーバーは HttpHandler クラスを継承して実装する。
サンプルでは Server クラス自身が HttpHandler となっている。もちろん独立したクラスとして実装してもよい。
class HttpServer
{
bool initialize(const HttpServerConfig* pCfg);
...
struct HttpServerConfig
{
HttpServerConfig();
HttpServerConfig(const HttpServerConfig&);
HttpServerConfig& operator=(const HttpServerConfig&);
int nAcceptors; //!< Acceptor の数。デフォルトは 1.
int nCommunicators; //!< Communicator の数(最大同時接続数)。デフォルトは 0.
int nConcurrency; //!< turn() の並列数。0の場合は並列化しない。デフォルトは 0.
int sockSendBufferSize; //!< ソケットの送信バッファサイズ。負だとOS設定値を使う。デフォルトは -1.
int sockRecvBufferSize; //!< ソケットの受信バッファサイズ。負だとOS設定値を使う。デフォルトは -1.
int nineSendBufferSize; //!< 送信バッファのサイズ。デフォルトは 10000.
int nineRecvBufferSize; //!< 受信バッファのサイズ。デフォルトは 10000.
int turnTrafficKB; //!< 一回の turn() で送受信する最大データサイズ。
bool enableWinsockAio; //!< nine1.2.1 より。1.2以降導入のWindows非同期I/O を使うなら真。デフォルトは偽。
int keepAliveTimeoutSec; // keep alive のタイムアウト秒数。ゼロなら keep alive しない。デフォルトは 3000(5分).
};
ほとんどの項目は、TransceiverConfig と同じである。
authorizeHttp() 関数は nine::HttpServer で定義された仮想関数であり、サブクラスでオーバーライドすることを想定している。
class HttpServer {
...
virtual HttpHandler* authorizeHttp(int cid, const HttpRequest*) = 0;
}
HttpRequest 引数に、HTTP要求のヘッダ情報が格納されている。複数のハンドラを使い分ける場合は、この情報を元に返すオブジェクトを変えることができる。
nine::HttpHandler* Server::authorizeHttp(int cid, const HttpRequest* pReq)
{
return this;
}
HTTP要求の本文全体を受け取ると、onHttpRequest 関数が呼びだされる。
パラメータから要求の内容を解析し、HttpChannel を用いて応答を作る。
virtual void onHttpRequest(HttpChannel* pChannel, const HttpRequest* pReq, Buffer* pBuf, HttpResponse* pRes) = 0;リクエストを解析する典型的なケースとして、GET の querystring と POST の本文がある。querystring は HttpRequest の uri.querystring に、本文は Buffer に格納されている。
HTTP応答をするには、HttpChannel を次のように扱う:
例えばサンプルコードでは次のようになっている:
std::string s = ...; //カウンタの文字列表現を格納
{
Buffer* pOut = pChannel->beginResponse(s.size());
if (pOut == NULL) {
pChannel->closeLater();
return;
}
pOut->writeArray(s.c_str(), s.size());
pChannel->endResponse();
}