ウォンツテック

そでやまのーと

昨日の続き

  • ap_read_request /server/protocol.c
    apr_brigade_destroy(tmp_bb);
    r->status = HTTP_OK;  /* Until further notice. */

brigadeのtmp_bbを削除してstatusをHTTP_REQUEST_TIME_OUTからHTTP_OKに変えている。requestをget出来たのでHTTP statusコードを変更し今度はさらなる通知?があるまでこのstatusにしておく。

次にVirtual Hostの設定修正を行う

    /* update what we think the virtual host is based 
     * on the headers we've now read. may update status.
     */
    ap_update_vhost_from_headers(r);

ap_update_vhost_from_headersでは

AP_DECLARE(void) ap_update_vhost_from_headers(request_rec *r)
{
    /* must set this for HTTP/1.1 support */
    if (r->hostname || (r->hostname = apr_table_get(r->headers_in, "Host"))) {
        fix_hostname(r);
        if (r->status != HTTP_OK)
            return;
    }
    /* check if we tucked away a name_chain */
    if (r->connection->vhost_lookup_data) {
        if (r->hostname)
            check_hostalias(r);
        else
            check_serverpath(r);
    }
}

となっており、今現在r->hostnameが設定されているか、apr_table_getでheaderからHost値を取得しそのHost値が存在している場合にはfix_hostnameでhostname部(host:port)を解析し修正している。

次は良くわからないけどtimeoutモードの設定を変える必要があるかどうか調べて、必要があれば変えている

    /* Toggle to the Host:-based vhost's timeout mode
     * to fetch the request body and send the response
     * body, if needed.
     */
    if (cur_timeout != r->server->timeout) {
        apr_socket_timeout_set(csd, r->server->timeout);
        cur_timeout = r->server->timeout;
    }
    /* we may have switched to another server */
    r->per_dir_config = r->server->lookup_defaults;

ここで設定されているper_dir_configの定義先を見ると

    /** Options set in config files, etc. */
    struct ap_conf_vector_t *per_dir_config;

とあるのでコンフィグファイルのあるディレクトリ先を変更しているっぽい。(他のサーバにスイッチしてるかもしれない。とある)

    if ((!r->hostname && (r->proto_num >=
         HTTP_VERSION(1, 1)))
        || ( (r->proto_num == HTTP_VERSION(1, 1) )
        && !apr_table_get(r->headers_in, "Host"))) {
        /*
         * Client sent us an HTTP/1.1 or later request
         * without telling us the
         * hostname, either with a full URL or a Host:
         * header. We therefore
         * need to (as per the 1.1 spec) send an error.
         * As a special case,
         * HTTP/1.1 mentions twice (S9, S14.23) that 
         * a request MUST contain
         * a Host: header, and the server MUST respond
         * with 400 if it doesn't.
         */
        r->status = HTTP_BAD_REQUEST;
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
        "client sent HTTP/1.1 request without hostname "
        "(see RFC2616 section 14.23): %s", r->uri);
    }

HTTP1.1以上でホスト名が設定されていない場合か、HTTP1.1でHostヘッダーフィールドが設定されていない場合HTTP_BAD_REQUEST(status 400)としてクライアントに返される。

次のコメントを呼んでみる

    /*
     * Add the HTTP_IN filter here to ensure that 
     * ap_discard_request_body called by ap_die and 
     * by ap_send_error_response works correctly on
     * status codes that do not cause the connection to
     * be dropped and in situations where the connection
     * should be kept alive.
     */

ここでHTTP_INのフィルターを追加してap_discard_request_bodyが正しく動いているか確かめている。

ap_add_input_filter_handle(ap_http_input_filter_handle,
                               NULL, r, r->connection);

フィルターの追加

    if (r->status != HTTP_OK) {
        ap_send_error_response(r, 0);
        ap_update_child_status(conn->sbh, 
                               SERVER_BUSY_LOG, r);
        ap_run_log_transaction(r);
        return r;
    }

さっき設定したHTTP_OKではなくなっている場合(途中どこかでstatusが変更されている場合)エラーなのでエラー処理を行ってる。

この後、ap_run_post_read_requestでpostの中身を読みに行っているっぽいけどこれはフック関数で登録されているのでそれをgrep-findしてみたけどいっぱいあってどれが本命かわからない。。とりあえず素通り

    if ((access_status = ap_run_post_read_request(r))) {
        ap_die(access_status, r);
        ap_update_child_status(conn->sbh,
                               SERVER_BUSY_LOG, r);
        ap_run_log_transaction(r);
        return NULL;
    }

ここでaccess_statusが何も設定されていないと次の処理が行われる。

if (((expect = apr_table_get(r->headers_in, "Expect"))
    != NULL) && (expect[0] != '\0')) {

Expectヘッダーが存在している場合。
ちなみにExpectヘッダーをRFC2616で調べてみると

The Expect request-header field is used to indicate that particular server behaviors are required by the client.

となっており、クライアントがサーバの特定の動作を期待しているとある。
またこのheader値が「100-continue」になっている場合はそのフラグを設定し、なっていない場合はHTTP_EXPECTATION_FAILED(status 417)をクライアントへ返す。

        if (strcasecmp(expect, "100-continue") == 0) {
            r->expecting_100 = 1;
        }
        else {
            r->status = HTTP_EXPECTATION_FAILED;
            ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
                         "client sent an unrecognized
                          expectation value of "
                          "Expect: %s", expect);
            ap_send_error_response(r, 0);
            ap_update_child_status(
              conn->sbhSERVER_BUSY_LOG, r);
            ap_run_log_transaction(r);
            return r;
        }

これはクライアントがサーバからstatus code 100を待っている事をサーバに教えるためにExpectヘッダーに「100-continue」という値を入れている。

最後はrequest_recへのポインタrを返して終わり。