Сайт на C++ своими руками с помощью библиотеки cgicc
Рассказываем об основах создания простого бэкенда для сайта на обычном шаред-хостинге с помощью языка C++ и библиотеки cgicc.
Серверное окружение
Если вы думаете, что бэк на C++ возможен только на выделенном сервере, это не так: большинство шаред-хостингов имеют такую возможность. Любой веб-хост, который поддерживает CGI, поддерживает и C++ скрипты.
В зависимости от провайдера вы можете иметь или не иметь возможность компилировать сайт локально. Если вы собираетесь редактировать и компилировать скрипты через SSH, заранее об этом узнайте.
Простой пример
В примере будет рассматриваться шаред-хостинг с панелью на cPanel, но описание легко адаптируется под любой другой. cPanel предоставляет отдельный каталог cgi-bin, но использовать именно его не обязательно.
Любой файл с расширением .cgi будет автоматически обработан, если имеет корректные права доступа (обычно 0755). Ниже описаны необходимые файлы (убедитесь что используете табуляцию для отступов в Makefile).
Makefile:
all: g++ -O3 -s hello.cpp -o hello.cgi clean: rm -f hello.cgi
hello.cpp:
#include <iostream> #include <string> #include <stdlib.h> using namespace std; void set_content_type(string content_type) { cout << “Content-type: “ << content_type << “\r\n\r\n”; } void set_page_title(string title) { cout << “<title>” << title << “</title>\n”; } void h1_text(string text) { cout << text << “\n”; } int main() { set_content_type(“text/html”); cout << “<!doctype html>\n”; cout << “<html lang=\”en\”>\n”; cout << “<head>\n”; set_page_title(“Hello, World!”); cout << “</head>\n”; cout << “<body>\n”; h1_text(“Hello, World!”); cout << “</body>\n”; cout << “</html>”; return 0; }
Если на вашем аккаунте доступен компилятор (можно уточнить в техподдержке хостера), просто подключитесь к серверу по SSH переместите файлы в каталог public_html (можно и по FTP) и запустите в консоли:
make
Теперь попробуйте открыть файл в браузере:
http://your-test-site.com/hello.cgi
Вы должны увидеть на экране «Hello World».
Прежде, чем начать разбираться с кодом, давайте выясним, что происходит на сервере. Когда Apache получает запрос, он первым делом проверяет встроенный обработчик или RewriteRule, затем проверяет наличие запрашиваемого файла на диске. В нашем случае, он найдет hello.cgi и исполнит его: программа не принимает никаких данных, а просто возвращает строку. Apache возвращает строку в виде корректного ответа для браузера.
Что касается кода в текущем виде, то он написан не лучшим образом. Все, что он может делать, – отдавать строку текста, и при этом никак не структурирован. Чтобы обработка тегов выглядела опрятней и была более расширяемой, можно добавить функции для выдачи тегов, например:
void p(string text) { cout << “<p>” << text << “</p>\n”; }
Таким образом, получается аккуратная обертка для параграфа:
p(“This would be paragraph text.”);
Входные данные
Обрабатывая запросы, веб-сервер передает огромное количество информации, которая хранится в переменных окружения. Чтобы получить к ней доступ, можно воспользоваться функцией getenv() из стандартной библиотеки C (не забудьте про #include <stdlib.h> в шапке файла).
К примеру, если нужно узнать запрашиваемый URI целиком, можно использовать:
string request_uri = getenv(“REQUEST_URI”);
Вот еще несколько полезных примеров:
- REMOTE_ADDR – получить IP адрес посетителя.
- REQUEST_METHOD – вернет метод запроса (GET, POST и так далее).
- DOCUMENT_ROOT – получить путь к корневому каталогу.
- QUERY_STRING – можно использовать для получения переменных из GET.
Пример с использованием cgicc
Разбираться с переменными из GET и POST-запросами, конечно, можно и вручную, но это утомительное занятие. Нужно либо писать собственные обертки, либо использовать существующую библиотеку (в нашем примере – cgicc), которая поможет работать с HTML и обрабатывать данные форм. Использование библиотек для крупных проектов позволит сохранить уйму времени.
На Debian и Ubuntu можно устанавливать библиотеки из консоли, используя утилиту apt:
apt install libcgicc5 libcgicc5-dev
На CentOS/RHEL с установкой пакетов сложнее, так что придется использовать:
cd /usr/local/src wget ftp://ftp.gnu.org/gnu/cgicc/cgicc-3.2.19.tar.gz tar xfz cgicc*.tar.gz cd cgicc* ./configure — prefix=/usr make make install
Обратите внимание, что версия 3.2.19 актуальна на момент написания заметки. Актуальную версию можно найти в ftp://ftp.gnu.org/gnu/cgicc/ (подключитесь по через ваш FTP-клиент).
Как только библиотека установлена, можно использовать ее в проекте. Рассмотрим пример, который принимает и обрабатывает пользовательский ввод в браузере.
Makefile:
all: g++ -O3 -s hello.cpp -o hello.cgi g++ -O3 -s cgicc.cpp -o cgicc.cgi /usr/lib/libcgicc.a clean: rm -f hello.cgi cgicc.cgi
cgicc.html:
<!doctype html> <html lang="en"> <head> <title>cgicc Test</title> </head> <body> <form method="POST" action="cgicc.cgi"> <label for="name">Name</label> <input name="name" type="text" value=""> <input name="submit" type="submit" value="Submit"> </form> </body> </html>
cgicc.cpp:
#include <iostream> #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; void set_content_type(string content_type) { cout << “Content-type: “ << content_type << “\r\n\r\n”; } void set_page_title(string title) { cout << “<title>” << title << “</title>\n”; } void h1_text(string text) { cout << text << “\n”; } int main() { Cgicc cgi; string name; set_content_type(“text/html”); cout << “<!doctype html>\n”; cout << “<html lang=\”en\”>\n”; cout << “<head>\n”; set_page_title(“cgicc Test”); cout << “</head>\n”; cout << “<body>\n”; cout << “<p>”; name = cgi(“name”); if (!name.empty()) { cout << “Name is “ << name << “\n”; } else { cout << “Name was not provided.”; } cout << “</p>\n”; cout << “</body>\n”; cout << “</html>”; return 0; }
В этом примере cgicc помогает нам парсить POST и возвращает поле name. Этот пример упрощен и данные поле при попадании на сервер не проходят дополнительную обработку, что необходимо сделать на рабочем сайте, особенно, если будет взаимодействовать с базой данных.
Производительность
C++ известен своей быстротой, но это справедливо, если вы умеете писать на нем хороший код. Интерфейс CGI также несколько замедляет скорость работы приложения, но вы все равно получаете преимущество в скорости над интерпретируемыми языками, вроде PHP.