Wt, библиотека C++ для разработки веб-приложений

в 8:38, , рубрики: ajax, c++, Веб-разработка, веб-сервер, метки: , , ,

Всем привет!

Так случилось, что на Хабре не было ни одного упоминания Wt, C++ Web Toolkit, кроме одного комментария.

Библиотека Wt может заинтересовать тех, кто пишет на C++ и захотел посмотреть в сторону Web, но не хочет изучать и/или использовать HTML, CSS, JavaScript, SQL и дополнительные технологии, связанные с веб-разработкой и работой с БД. В данной статье моей целью было обратить внимание сообщества на Wt, а не освещать все его возможности.

Если Вы жаждете посмотреть, как это работает, вот пример, демонстрирующий различные виджеты: www.webtoolkit.eu/widgets

Обзор возможностей библиотеки на русском языке: www.webtoolkit.eu/wt/ru/features

Возможности Wt

Здесь я приведу некоторые из особенностей, которые мне кажутся наиболее привлекательными.

Wt является кроссплатформенной свободной поддерживаемой C++ библиотекой. Релизы выходят несколько раз в год. Доступна на условиях лицензии GNU GPL 2 или коммерческой лицензии. Напомню, что лицензия GNU GPL 2 не запрещает создавать приложение с закрытым кодом, чтобы пользоваться им лично, в частности для разворачивания на своем сервере.

Программирование с использованием Wt строится вокруг виджетов, подобно Qt. Многие вещи похожи на Qt, что делает Wt простым для изучения для тех, кто знаком с Qt. В отличие от Qt, не происходит кодогенерации — используются сигналы, основанные на boost.signals, которые представляют собой обычный код C++, не требующий генерации. Сигналы виджетов (например, сигнал нажатия на кнопку) можно присоединять к любым функциям C++ (и функциональным объектам). Полностью асинхронный вход/выход (на основе библиотеки boost.asio) управляется событиями. Не происходит постоянного порождения и завершения потоков выполнения. Для каждой сессии на сервере хранится объект WApplication, через который доступно всё дерево виджетов. Доступ к виджетам сессии осуществляется способом, защищенным от «гонок», благодаря чему возможно безопасное взаимодействие сессий между собой и с сервером. Это продемонстрировано в примере чата. В этом же примере показано использование событий, инициируемых сервером (а не клиентом) и возможность включения приложения в другие страницы или сайты в виде загружаемого скрипта (вроде того, как виджет google maps может встраиваться в друге сайты).

Wt-приложения работают в основных браузерах, причем если JavaScript работает, выдается Ajax-версия, а если не работает — аналогичный HTML код, что является уникальной возможностью Wt, по крайней мере среди C++ фреймворков. Это позволяет без дополнительных усилий со стороны разработчика создавать приложение, использующее преимущества таких технологий, как Ajax, Comet, WebSocket, но в то же время работающее, если они недоступны. Кроме того, есть возможность оптимизации выдачи для поисковых роботов (речь идет не о клоакинге, а об улучшениях вроде отказа от случайных идентификаторов объектов). Wt может использовать такие новшества HTML5, как переписывание URL в браузере (для создания REST-приложений), выбор нескольких файлов, теги video и audio, но если их нет, по возможности используются обходные пути (к примеру, звук и видео через flash вместо тегов video и audio).

Возможно создание веб-приложений, подключаемых через http, fastcgi или ISAPI (последний только для платформ Win32). Какой именно способ соединения будет использоваться, определяется на этапе компоновки, выбором нужной библиотеки. Компонуя свой код с библиотекой встроенного http-сервера, получаем полноценный Веб-сервер, который удобно использовать при отладке, но можно запускать и на production, хотя в последнем случае стоит также рассмотреть возможность использования других способов соединения.

В Wt встроено использование Юникода и локализации.

Низкое потребление ресурсов позволяет запускать приложения на устройствах с ограниченными ресурсами, например, на роутерах.

Библиотеку удобно использовать для создания веб-интерфейсов для существующих программ, написанных на C++.

Библиотека обеспечивает высокий уровень безопасности, в частности защиту от атак XSS или SQL-injection. К примеру, виджет WText, отвечающий за отображение текста, убеждается, что его текст не содержит «опасных» атрибутов и тегов (вроде script), и вычищает их при необходимости. Имеется поддержка HTTPS. Есть защита от DDoS атак.

Библиотека также включает ряд надстроек, полезных при веб-разработке, в частности, систему рисования, систему построения диаграмм, ORM (отображение классов C++ на структуры баз данных), систему аутентификации.

Вообще хочется отметить чистоту и высокое качество кода библиотеки: легко читается не только документация, но при необходимости и код реализации. Сделано общо и гибко. Нигде (даже при компиляции кода, связанного с БД) не происходит кодогенерации. Часть библиотеки, ответственная за работу с БД, может быть использована (или куплена лицензия) отдельно от остальных компонентов. Эта часть библиотеки заслуживает отдельной статьи.

Для Wt доступны версии на Java и других языках, но тут я ограничусь рассмотрением C++ версии. Версия 1.0.0 была опубликована в 2005 году, так что по своей «зрелости» Wt может соперничать с Django и Ruby on Rails. Стоит отметить, что на C++ существует ещё как минимум два активных проекта: CppCMS и Tntnet. Сравнение возможностей представлено в википедии. Мой выбор пал на Wt в первую очередь за возможность полного абстрагирования от HTML, CSS, JavaScript в пользу одного языка — C++, а также за автоматическую поддержку как Ajax браузеров, так и браузеров без Ajax.

Пример простого приложения

Пример взят отсюда: www.webtoolkit.eu/wt/ru/examples/

#include <Wt/WApplication>
#include <Wt/WBreak>
#include <Wt/WContainerWidget>
#include <Wt/WLineEdit>
#include <Wt/WPushButton>
#include <Wt/WText>

using namespace Wt;

/*
 * A simple hello world application class which demonstrates
 * how to react to events, read input, and give feed-back.
 */
class HelloApplication : public WApplication
{
public:
  HelloApplication(const WEnvironment& env);

private:
  WLineEdit *nameEdit_;
  WText *greeting_;

  void greet();
};

/*
 * The env argument contains information about the new session, and
 * the initial request. It must be passed to the WApplication
 * constructor so it is typically also an argument for your custom
 * application constructor.
*/
HelloApplication::HelloApplication(const WEnvironment& env)
  : WApplication(env)
{
  setTitle("Hello world");                               // application title

  root()->addWidget(new WText("Your name, please ? "));  // show some text
  nameEdit_ = new WLineEdit(root());                     // allow text input
  nameEdit_->setFocus();                                 // give focus

  WPushButton *button
    = new WPushButton("Greet me.", root());              // create a button
  button->setMargin(5, Left);                            // add 5 pixels margin

  root()->addWidget(new WBreak());                       // insert a line break

  greeting_ = new WText(root());                         // empty text

  /*
   * Connect signals with slots
   *
   * - simple Wt-way
   */
  button->clicked().connect(this, &HelloApplication::greet);

  /*
   * using an arbitrary function object
   * (binding values with boost::bind())
   */
  nameEdit_->enterPressed().connect
    (boost::bind(&HelloApplication::greet, this));
}

void HelloApplication::greet()
{
  /*
   * Update the text, using text input into the nameEdit_ field.
   */
  greeting_->setText("Hello there, " + nameEdit_->text());
}

WApplication *createApplication(const WEnvironment& env)
{
  /*
   * You could read information from the environment to decide whether
   * the user has permission to start a new application
   */
  return new HelloApplication(env);
}

int main(int argc, char **argv)
{
  /*
   * Your main method may set up some shared resources, but should then
   * start the server application (FastCGI or httpd) that starts listening
   * for requests, and handles all of the application life cycles.
   *
   * The last argument to WRun specifies the function that will instantiate
   * new application objects. That function is executed when a new user surfs
   * to the Wt application, and after the library has negotiated browser
   * support. The function should return a newly instantiated application
   * object.
   */
  return WRun(argc, argv, &createApplication);
}

Это пример простого приложения, спрашивающего имя пользователя. Когда пользователь вводит имя и нажимает Enter или кнопку «Greet me.», приложение привествует его: «Hello there, %USERNAME%». Думаю, разбирать код подробно смысла нет, тем более в нем есть комментарии.

Посмотреть запущенный пример можно тут: www.webtoolkit.eu/wt/examples/hello/hello.wt

Чтобы скомпилировать этот пример, нам потребуется компилятор C++ и установленная библиотека Wt. Везучие пользователи Debian и Ubuntu могут просто установить пакет witty-dev.

В линуксе команда компиляции выглядит так:

g++ -lwt -lwthttp -lboost_signals hello.cpp -o hello

Команда запуска:

./hello --docroot . --http-address 127.0.0.1 --http-port 8000

После чего приложени можно будет открыть в браузере по адресу 127.0.0.1:8000

Ссылки

Сайт проекта: www.webtoolkit.eu/
Блог: www.webtoolkit.eu/wt/blog
Введение: www.webtoolkit.eu/wt/doc/tutorial/wt.html
Примеры: www.webtoolkit.eu/wt/examples/
Скачать: www.webtoolkit.eu/wt/download
Документация: www.webtoolkit.eu/wt/documentation
Система отслеживания ошибок: redmine.emweb.be/
Проект также представлен на гитхабе github.com/kdeforche/wt

Автор: starius

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js