HTTP POST, читая стандартный ввод (CGI в C) - PullRequest
4 голосов
/ 11 июля 2010

Какой безошибочный способ получить HTTP POST в CGI в C?

Я сейчас использую это. Это нормально? Что если «CONTENT_LENGTH» неверно и больше, чем stdin; как будет вести себя чтение тогда?

<code>
char *STDIN = NULL;
char *pointer = getenv("CONTENT_LENGTH");
if(pointer != NULL)
{
    char charlength[5] = "";
    strncat(charlength, pointer, 4); // limit length to a reasonable number
    unsigned long int length = strtoul(charlength, NULL, 0);
    STDIN = malloc(length + 2);
    ssize_t readbytes = read(0, STDIN, length);
    STDIN[readbytes] = '&'; // for use later on in my program
    memset(STDIN + readbytes + 1, (int)'\0', (length + 2) - (size_t)(readbytes + 1));
}

Ответы [ 2 ]

2 голосов
/ 11 июля 2010

read(2) вернет не больше байтов, чем вы просили. Это может оставить больше данных в дескрипторе файла stdin для чтения (в случае, если клиент отправляет CONTENT_LENGTH 0, но вручает вам их / dev / urandom), но это нормально. Ваш процесс свободен, не читая все это.

read(2) может вернуть меньше байтов, чем вы просите. Это может быть связано с тем, что еще не все данные поступили, а ядру надоело блокировать, или может быть, что содержимое меньше, чем CONTENT_LENGTH. Я рад, что вы ограничиваете длину чем-то «разумным», так как было бы довольно легко передать CONTENT_LENGTH, который является максимальным значением size_t, или этим значением минус один, или этим значением минус два, и играть в игры. с помощью функции malloc (), выделяющей 0, 1 или 2 байта, и позволяющей вам с радостью писать по всей вашей памяти.

1 голос
/ 11 июля 2010

Вы должны вызвать read в цикле.

Это в целом верно и особенно при чтении из сокета. Вполне вероятно, что для получения средних и больших объемов данных потребуется некоторое время, но read обычно возвращается как можно скорее (я не могу вспомнить, требуется это или нет). Если первый TCP-пакет содержит около 1 тыс. Данных из 9 тыс., То первый вызов read, скорее всего, вернет этот 1 тыс. До прибытия следующего пакета, а ваш текущий код никогда не прочитает остальные.

Итак, продолжайте вызывать read (и каждый раз передвигайте указатель, который вы передаете, на количество прочитанных байтов, и уменьшайте количество байтов для чтения аналогичным образом), пока не произойдет одно из следующих действий:

  • вы прочитали байтов CONTENT_LENGTH.
  • read возвращает 0 (в этом случае данные POST короче, чем обещано CONTENT_LENGTH).
  • read возвращает -1 (означает, что произошла ошибка), а errno - это что-то отличное от EINTR (или EAGAIN, если установлено значение O_NONBLOCK, и в этом случае вы захотите спать или подобное перед следующим чтением Но в этом случае нет смысла устанавливать O_NONBLOCK).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...