Веб-программирование на C++ с CGI: полное руководство
Что такое CGI?
Common Gateway Interface (CGI) — это набор стандартов, определяющих обмен информацией между веб-сервером и пользовательским скриптом. Спецификации CGI поддерживает NCSA. Текущая версия — CGI/1.1, CGI/1.2 в разработке.
Как работает веб-просмотр
- Браузер запрашивает URL у HTTP-сервера.
- Сервер разбирает URL, ищет файл. Если найден — отправляет его браузеру, иначе — ошибку.
- Браузер отображает полученный файл или сообщение об ошибке.
Однако сервер можно настроить так, чтобы файлы в определённой директории выполнялись как программы, а их вывод отправлялся браузеру. CGI-программы могут быть написаны на Python, Perl, Shell, C, C++ и др.
Архитектура CGI

Настройка веб-сервера
Перед началом убедитесь, что сервер поддерживает CGI и настроен на выполнение CGI-программ. По умолчанию Apache использует директорию /var/www/cgi-bin. CGI-файлы обычно имеют расширение .cgi (даже если это скомпилированные C++ программы).
Для изменения директории отредактируйте httpd.conf:
<Directory "/var/www/cgi-bin">
AllowOverride None
Options ExecCGI
Order allow,deny
Allow from all
</Directory>
<Directory "/var/www/cgi-bin">
Options All
</Directory>
Первая CGI-программа на C++
#include <iostream>
using namespace std;
int main() {
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>Hello World - First CGI Program</title>\n";
cout << "</head>\n";
cout << "<body>\n";
cout << "<h2>Hello World! This is my first CGI program</h2>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
Скомпилируйте и назовите исполняемый файл cplusplus.cgi. Поместите в /var/www/cgi-bin и сделайте исполняемым: chmod 755 cplusplus.cgi.
Ключевая строка — Content-type:text/html\r\n\r\n. Она сообщает браузеру тип содержимого (MIME). Без неё браузер не поймёт, как отобрать вывод.
HTTP-заголовки
Заголовки имеют формат Имя: Значение. Основные заголовки:
| № | Заголовок и описание |
|---|---|
| 1 | Content-type: MIME-тип возвращаемого файла (например, text/html). |
| 2 | Expires: дата, когда информация устаревает (формат: 01 Jan 1998 12:00:00 GMT). |
| 3 | Location: URL для перенаправления запроса. |
| 4 | Last-modified: дата последнего изменения ресурса. |
| 5 | Content-length: длина данных в байтах. |
| 6 | Set-Cookie: установка cookie. |
Переменные окружения CGI
CGI-программы имеют доступ к переменным окружения, важным для обработки запросов:
| № | Переменная и описание |
|---|---|
| 1 | CONTENT_TYPE — тип данных, отправляемых клиентом (например, при загрузке файлов). |
| 2 | CONTENT_LENGTH — длина данных запроса (только для POST). |
| 3 | HTTP_COOKIE — установленные cookie в виде пар ключ-значение. |
| 4 | HTTP_USER_AGENT — информация о браузере клиента. |
| 5 | PATH_INFO — путь к CGI-скрипту. |
| 6 | QUERY_STRING — URL-закодированные данные метода GET. |
| 7 | REMOTE_ADDR — IP-адрес клиента. |
| 8 | REMOTE_HOST — полное имя хоста клиента. |
| 9 | REQUEST_METHOD — метод запроса (GET, POST). |
| 10 | SCRIPT_FILENAME — полный путь к скрипту. |
| 11 | SCRIPT_NAME — имя скрипта. |
| 12 | SERVER_NAME — имя хоста или IP сервера. |
| 13 | SERVER_SOFTWARE — название и версия ПО сервера. |
Пример программы для вывода всех переменных окружения:
#include <iostream>
#include <stdlib.h>
using namespace std;
const string ENV[24] = {
"COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE", "HTTP_ACCEPT",
"HTTP_ACCEPT_ENCODING", "HTTP_ACCEPT_LANGUAGE", "HTTP_CONNECTION",
"HTTP_HOST", "HTTP_USER_AGENT", "PATH", "QUERY_STRING", "REMOTE_ADDR",
"REMOTE_PORT", "REQUEST_METHOD", "REQUEST_URI", "SCRIPT_FILENAME",
"SCRIPT_NAME", "SERVER_ADDR", "SERVER_ADMIN", "SERVER_NAME",
"SERVER_PORT", "SERVER_PROTOCOL", "SERVER_SIGNATURE", "SERVER_SOFTWARE"
};
int main() {
cout << "Content-type:text/html\r\n\r\n";
cout << "<html><head><title>CGI Environment Variables</title></head><body>";
cout << "<table border=\"0\" cellspacing=\"2\">";
for (int i = 0; i < 24; i++) {
cout << "<tr><td>" << ENV[i] << "</td><td>";
char *value = getenv(ENV[i].c_str());
if (value) cout << value;
else cout << "Environment variable does not exist.";
cout << "</td></tr>\n";
}
cout << "</table></body></html>";
return 0;
}
Библиотека C++ CGI (cgicc)
Для реальных задач удобно использовать библиотеку cgicc. Установка:
$ tar xzf cgicc-X.X.X.tar.gz
$ cd cgicc-X.X.X/
$ ./configure --prefix=/usr
$ make
$ make install
Методы GET и POST
Браузеры передают данные на сервер двумя основными способами: GET и POST.
GET-метод
Данные добавляются к URL после ?: https://example.com/cgi-bin/cpp.cgi?key1=value1&key2=value2. Ограничение — до 1024 символов. Не используйте для паролей. Данные доступны через переменную окружения QUERY_STRING.
Пример с библиотекой cgicc
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;
int main() {
Cgicc formData;
cout << "Content-type:text/html\r\n\r\n";
cout << "<html><head><title>Using GET and POST Methods</title></head><body>";
form_iterator fi = formData.getElement("first_name");
if (!fi->isEmpty() && fi != (*formData).end()) {
cout << "First name: " << **fi << endl;
} else {
cout << "No text entered for first name" << endl;
}
cout << "<br/>\n";
fi = formData.getElement("last_name");
if (!fi->isEmpty() && fi != (*formData).end()) {
cout << "Last name: " << **fi << endl;
} else {
cout << "No text entered for last name" << endl;
}
cout << "<br/>\n</body></html>";
return 0;
}
Компиляция: g++ -o cpp_get.cgi cpp_get.cpp -lcgicc
Вызов: /cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI
POST-метод
Более надёжный: данные передаются в теле запроса (stdin), а не в URL. Тот же CGI-скрипт обрабатывает и GET, и POST.
Передача данных формы: чекбоксы, радиокнопки, текстовые области, выпадающие списки
Для каждого типа элемента формы приводятся HTML-примеры и соответствующие C++ CGI-скрипты с использованием библиотеки cgicc. Основные методы:
queryCheckbox("name")— проверка состояния чекбокса.getElement("name")— получение значения радиокнопки, текстовой области или выпадающего списка.
Работа с Cookie
HTTP — протокол без состояния. Cookie позволяют сохранять информацию между страницами. Cookie устанавливаются через заголовок Set-Cookie перед строкой Content-type.
Установка cookie
cout << "Set-Cookie:UserID = XYZ;\r\n";
cout << "Set-Cookie:Password = XYZ123;\r\n";
cout << "Set-Cookie:Domain = www.example.com;\r\n";
cout << "Set-Cookie:Path = /perl;\n";
cout << "Content-type:text/html\r\n\r\n";
Получение cookie
Cookie хранятся в переменной окружения HTTP_COOKIE. Библиотека cgicc предоставляет итератор const_cookie_iterator для перебора.
Загрузка файлов
HTML-форма должна иметь enctype="multipart/form-data". В C++ используйте cgi.getFile("userfile") для получения загруженного файла и записи его в поток или сохранения на диск.
Язык C
- Освоение пространств имен в C#: организация, область видимости и лучшие практики
- Освоение операторов C++: полное руководство с практическими примерами
- Комментарии в C++: лучшие практики для читаемого и поддерживаемого кода
- Как передавать массивы в функции в C++: практическое руководство
- Освоение программирования на C: подробное руководство для начинающих
- Язык программирования C++: обзор и ключевые особенности
- Константы и литералы в C++: типы, синтаксис и лучшие практики
- Полное руководство по операторам C++: типы, использование и лучшие практики
- Работа с числовыми типами в C++: практическое руководство
- Ссылки в C++: ключевые концепции и отличия от указателей