Рассказываем об основах создания простого бэкенда для сайта на обычном шаред-хостинге с помощью языка 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.
Комментарии