У меня появился новый интерес к созданию небольшого эффективного веб-сервера на C, и у меня возникли некоторые проблемы с синтаксическим анализом методов POST из заголовка HTTP. Кто-нибудь может посоветовать, как обрабатывать получение пар имя / значение из «опубликованных» данных?
POST /test HTTP/1.1
Host: test-domain.com:7017
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://test-domain.com:7017/index.html
Cookie: __utma=43166241.217413299.1220726314.1221171690.1221200181.16; __utmz=43166241.1220726314.1.1.utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)
Cache-Control: max-age=0
Content-Type: application/x-www-form-urlencoded
Content-Length: 25
field1=asfd&field2=a3f3f3
// ^-this
Я не вижу ощутимого способа получить прибыль в целом и убедиться, что она работает каждый раз. Я не поклонник жесткого кодирования в чем-либо.





Вы можете получить пары имя / значение, выполнив поиск новой строки новой строки или, более конкретно, \ r \ n \ r \ n (после этого начнется тело сообщения).
Затем вы можете просто разделить список с помощью &, а затем разделить каждую из этих возвращаемых строк между парами = для имени / значения.
См. HTTP 1.1 RFC.
@rofly: не вычисляйте два и два, просто прочтите стандарт (RFC 2616). Это в разделе 4.1.
Просто имейте в виду, что есть несовместимые клиенты, которые используют "интересный" конец заголовков, например '\ n \ n' или '\ n \ r \ n'.
Обратите внимание, что есть и другие типы контента, кроме application / x-www-form-urlencoded. Это может быть любой тип, например json популярен.
Вам нужно продолжать синтаксический анализ потока как заголовков, пока вы не увидите пустую строку. Остальное - это данные POST.
Вам нужно написать небольшой парсер для данных поста. Вы можете использовать подпрограммы библиотеки C, чтобы делать что-то быстрое и грязное, например index, strtok и sscanf. Если у вас есть место для этого в вашем определении «маленький», вы можете сделать что-то более сложное с библиотекой регулярных выражений или даже с flex и bison.
По крайней мере, я думаю, что это своего рода ответ на ваш вопрос.
Если у вас есть Content-Length в заголовке, вы знаете, сколько байтов нужно прочитать сразу после пустой строки. Если по какой-либо причине (GET или POST) Content-Length отсутствует в заголовке, это означает, что после пустой строки (crlf) читать нечего.
Несмотря на IETF RFC, вот более конкретный ответ. Предполагая, что вы понимаете, что всегда есть лишний /r/n после строки Content-Length в заголовке, вы сможете выполнить работу по изоляции его в переменной char* с именем data. Вот с чего мы начинаем.
char *data = "f1=asfd&f2=a3f3f3";
char f1[100],
char f2[100];
sscanf(data, "%s&%s", &f1, &f2); // get the field tuples
char f1_name[50];
char f1_data[50];
sscanf(f1, "%s=%s", f1_name, f1_data);
char f2_name[50];
char f2_data[50];
sscanf(f2, "%s=%s", f2_name, f2_data);
Ах, спасибо. Я заметил, что прямо перед строкой пар имя / значение был лишний пробел, но не складывал два и два вместе.