nixp.ru v3.0

19 октября 2017,
четверг,
03:03:10 MSK

DevOps с компанией «Флант»
Longobard написал 31 марта 2004 года в 00:03 (424 просмотра) Ведет себя как мужчина; открыл 291 тему в форуме, оставил 2499 комментариев на сайте.

У меня такая трабла: мой веб-сервер не показывает размер файла когда его скачиваешь. То есть клиент не может узнать этот размер. Я зачитал до дыр RFC2068, но так и не узнал, каким макаром этот самый размер клиенту указать. Как это сделать? Например есть файл test.tar.bz2 и лежит он в корне. Сервер получает запрос GET /test.tar.bz2 HTTP/1.0. Сервер успешно отсылает файл и он скачиается. Однако ни один браузер (Пробовал Оперу, Мазилу, Конкуерор) не определяют его размер при скачивании. Чего делать?

Longobard

При этом серверу не приходит какого-либо запроса. То есть я поставил логирование всего что приходит в сокет серверу — так там сплошной GET и при закачке файла посылается только один запрос по типу GET /test.tar.bz2 HTTP/1.1

anonymous

Ну что тебе сказать… Все правильно, по запросу GET /test.tar.bz2 HTTP/1.1 и приходит размер файла от Апача, протокол требует. Просто ты полного ответа сервера не видишь, вот и кажется, что не приходит…

А ты сделай вот что:

->telnet 127.0.0.1 80

Trying 127.0.0.1…

Connected to 127.0.0.1.

Escape character is '^]’.

->GET /test.bb HTTP/1.1

->Host: 127.0.0.1

->

HTTP/1.1 200 OK

Date: Tue, 30 Mar 2004 23:02:14 GMT

Server: Apache/1.3.29 (Unix)

Last-Modified: Tue, 30 Mar 2004 22:06:59 GMT

ETag: «1a39b-b-4069ef83»

Accept-Ranges: bytes

Content-Length: 11

Content-Type: text/plain

yalabubuda

Connection closed by foreign host.

Здесь «->» обозначает строку введенную с терминала и закончившуюся Enter’ом. Обрати внимание на строку «Content-Length: 11» в ответе сервера. Это — размер моего тестового файла test.bb, который содержит лишь строку «yalabubuda»

Все это в RFC 2068…

Good Luck,

UT

Genie

Есть ещё запрос HEAD, который, в отличие от GET, отдаёт только заголовки, как раз те, которые являются «server reply». Начинаются они всегда «HTTP/1.x xxx …..»

Longobard

Все, ясно, всем спасибо. Проглядел я это как-то в RFC2068 :(

Longobard

Хм. Выяснилсь что у меня RFC было неполным. У меня в нем только 9 глав было, а об этом рассказывается в главе номер 14 :)

Longobard

А как узнать MIME-тип файла (например text/plain и т.д.). Наверняка ведь есть функция какая-то. Не по расширению мне ведь определять. И как получается ETag?

An entity tag MUST be unique across all versions of all entities

  associated with a particular resource. A given entity tag value may

  be used for entities obtained by requests on different URIs without

  implying anything about the equivalence of those entities.

Как его сгенерить? Что он из себя представляет? Контрольную сумму файла?

Апач этот етаг генерит так:

char *etag;
    char *weak;
    core_dir_config *cfg;
    etag_components_t etag_bits;
    cfg = (core_dir_config *)ap_get_module_config(r->per_dir_config,
                                                  &core_module);
    etag_bits = (cfg->etag_bits & (~ cfg->etag_remove)) | cfg->etag_add;
    if (etag_bits == ETAG_UNSET) {
        etag_bits = ETAG_BACKWARD;
    }
    /*
     * Make an ETag header out of various pieces of information. We use
     * the last-modified date and, if we have a real file, the
     * length and inode number - note that this doesn't have to match
     * the content-length (i.e. includes), it just has to be unique
     * for the file.
     *
     * If the request was made within a second of the last-modified date,
     * we send a weak tag instead of a strong one, since it could
     * be modified again later in the second, and the validation
     * would be incorrect.
     */
    
    weak = ((r->request_time - r->mtime > 1) && !force_weak) ? "" : "W/";
    if (r->finfo.st_mode != 0) {
        char **ent;
        array_header *components;
        int i;
        /*
         * If it's a file (or we wouldn't be here) and no ETags
         * should be set for files, return an empty string and
         * note it for ap_send_header_field() to ignore.
         */
        if (etag_bits & ETAG_NONE) {
            ap_table_setn(r->notes, "no-etag", "omit");
            return "";
        }
        components = ap_make_array(r->pool, 4, sizeof(char *));
        if (etag_bits & ETAG_INODE) {
            ent = (char **) ap_push_array(components);
            *ent = ap_psprintf(r->pool, "%lx",
                               (unsigned long) r->finfo.st_ino);
        }
        if (etag_bits & ETAG_SIZE) {
            ent = (char **) ap_push_array(components);
            *ent = ap_psprintf(r->pool, "%lx",
                               (unsigned long) r->finfo.st_size);
        }
        if (etag_bits & ETAG_MTIME) {
            ent = (char **) ap_push_array(components);
            *ent = ap_psprintf(r->pool, "%lx", (unsigned long) r->mtime);
        }
        ent = (char **) components->elts;
        etag = ap_pstrcat(r->pool, weak, "\"", NULL);
        for (i = 0; i < components->nelts; ++i) {
            etag = ap_psprintf(r->pool, "%s%s%s", etag,
                               (i == 0 ? "" : "-"),
                               ent[i]);
        }
        etag = ap_pstrcat(r->pool, etag, "\"", NULL);
    }
    else {
        etag = ap_psprintf(r->pool, "%s\"%lx\"", weak,
                    (unsigned long) r->mtime);
    }
    return etag;