Rest-сервиса на C++: РОКО+угловой ТОДО

Rest-сервиса на C++: РОКО+угловой ТОДО

476
ПОДЕЛИТЬСЯ

В данной статье описывается создание таковой службы на примере задачки». РОКО является кросс — платформенной библиотеки с открытым начальным кодом на C++ под буст лицензии на программное обеспечение: ru.wikipedia.org/wiki/POCO. РОКО входят инструменты для сотворения интернет-сервисов на C API для размеренного.

Обычный todo приложение-перечень задач с возможностью добавлять новейшие либо удалять завершенные задачки.
Управление перечень задач crud-способы для хранения перечня задач употребляется с STD::показать на карте. Основной способ вызывается из базисного класса РОКО ServerApplication. Задачка реализуется в CTodo. Список задач, реализуемых в CTodoList. Этот класс содержит способы crud, а также перечень задач и мьютекс для синхронизации доступа к нему. Для http-сервера реализуется в TodoServerApp. Для каждой задачки в перечне присваивается неповторимый идентификатор (ID) юзера и описание (текст).

TodoServerApp.сек#прагма раз

#включить <Роко/Мьютекс.ч>
#включить <Роко/сеть/HTTPServerRequest.ч>
#включить <Роко/сеть/HTTPRequestHandler.ч>
#включить <Роко/сеть/HTTPServerResponse.ч>
#включить <Роко/нетто/http-сервера.ч>
#включить <Роко/сеть/HTTPRequestHandlerFactory.ч>
#включить <Роко/сеть/HTMLForm.ч>
#включить <Роко/путь.ч>
#включить <Роко/ScopedLock.ч>
#включить <Роко/StringTokenizer.ч>
#включить <Роко/Ури.ч>
#включить <Роко/утиль/ServerApplication.ч>

с помощью места имен Роко;
с помощью места имен Роко::сеть;
с помощью места имен Роко::Утила;
внедрение имен STD;

/**
Тодо
*/
класс CTodo {
Тип size_t идентификатор;
строчки текста;
общественности:
CTodo(строчка текста): (текст){
}
/* геттеры & сеттеров */
Тип size_t получение ID(){ возврат ИД; }
в void setId(идентификатор Тип size_t){ это->идентификатор = идентификатор; }
строчка в формате gettext(){ возвращение текста; }
};

/**
Перечень Todo
*/
класс CTodoList {
Тип size_t идентификатор;
карта<Тип size_t, CTodo> тодос;

общественности:
CTodoList():с кодом(0){}
/* Падла */
пустота сделать(CTodo задач (todo){ todo-списков.setId (идентификатор++); тодос.вставки(пара<Тип size_t,CTodo>(«идентификатор», » что сделать)); };
карта<Тип size_t, CTodo>& readList(){ возвращение тодос; }
пустота дель(идентификатор Тип size_t){ тодос.стереть(идентификатор); };
};

/**
Сервер
*/
класс TodoServerApp : общественная ServerApplication
{
общественности:
/* Падла */
статической силы createTodo(CTodo задач (todo);
статические CTodoList& readTodoList();
//статической силы updateTodo(идентификатор Тип size_t, CTodo задач (todo);
статической силы deleteTodo(идентификатор Тип size_t);

защищены:
Тип int основной(константный вектор<строчка> &);
статические Мьютекс todoLock;
статические CTodoList приложения todolist;
};
Для способов поставить/удалить вычисляет идентификатор в URI. Опосля инициализации на сервере запускается нескончаемый цикл. Способ main в классе TodoServerApp делает http сервер с данными параметрами (порт 8000 и так дальше). Дальше идет формирование ответа в выходной поток сервера. В этом случае, завод TodoRequestHandlerFactory имеет лишь два обработчика: CFileHandler для отдачи статики и CTodoHandler на самом деле для API-интерфейса rest. В согласовании с типом запроса, выполненного нужные деяния с данными перечня. Также на сервер передается на фабрику обработки запросов TodoRequestHandlerFactory. С данной целью для задачки CTodo и перечень задач CTodoList перегруженного оператора <<. Предоставление инфы для получения идентификатора определенной работы также не выполнены. API-интерфейс rest обработчик CTodoHandler описывает тип запроса (Get/пост/поставить/удалить). Ведь приложение чрезвычайно просто, положите способ не употребляется.

TodoServerApp.cpp#включить <библиотеки iostream>
#включить <строчка>

#включить «TodoServerApp.сек»

Мьютекс TodoServerApp::todoLock;
CTodoList TodoServerApp::приложения todolist;

данных ostream& оператор<<(данных ostream& OS, то CTodo задач (todo)
{
ОС << «{ «_id»: «<< тодо.получение ID() << «, «текст»: «» << тодо.и gettext() << «» }»;
возврат ОС;
}

данных ostream& оператор<<(данных ostream& OS, то CTodoList& приложения todolist)
{
карта<Тип size_t, CTodo> тодос = приложения todolist.readList();

ОС << «[«;
раз(!тодос.пустая())
{
раз(тодос.Размер() == 1)
ОС << тодос.начать()->2-ой;
еще
для ( показать на карте<Тип size_t, CTodo>::итератор это = тодос.начать();;)
{
ОС << он->2-ой ;
раз(++это != тодос.конец())
ОС << ‘,’;
еще
перерыв;
}

}
ОС << «]п»;

возврат ОС;
}

класс CTodoHandler : общественная HTTPRequestHandler
{
общественности:
пустота handleRequest(HTTPServerRequest &тр, HTTPServerResponse &Респ)
{
Ури Ури(исх.getURI());
способ string = к тр.getMethod();

вывод << «Ури:» << Ури.способ tostring() << епо;
вывод << «способ:» << требуется.getMethod() << епо;

StringTokenizer токенизатор(Ури.getPath(), «/», StringTokenizer::TOK_TRIM);
HTMLForm форме(требуется,требуется.поток());

раз(!способ.сравните(«пост»))
{
вывод << «сделать:» << форма.получить(«текст») << епо;
CTodo тодо(форма.получить(«текст»));
TodoServerApp::createTodo(что сделать);
}
по другому раз(!способ.сравните(«поставить»))
{
вывод << «обновить ID:» << *(—токенизатор.конец()) << епо;
вывод << «обновление текста»:» < < форма.получить(«текст») << епо;
//идентификатор Тип size_t=stoull(*(—токенизатор.конец()));
//TodoServerApp::updateTodo(идентификатор, форму.получить(«текст»));
}
по другому раз(!способ.сравните(«удалить»))
{
вывод << «удалить с ID:» << *(—токенизатор.конец()) << епо;
Тип size_t идентификатор=stoull(*(—токенизатор.конец()));
TodoServerApp::deleteTodo(идентификатор);
}

отв.setStatus(объект httpresponse::HTTP_OK);
отв.setContentType(«приложение/json»);
поток и = отв.выслать();

вывод << TodoServerApp::readTodoList() << епо;
наш << TodoServerApp::readTodoList() << епо;

наш.флеш();
}
};

#включить <библиотеки iostream> // для STD::cout либо
к примеру: #include <fstream> // для STD::ifstream
#включить <карта> // для STD::ifstream

класс CFileHandler : общественная HTTPRequestHandler
{
typedef в с STD::Map<заглавие const и с STD::string, в константной функции STD::строчка> TStrStrMap;
TStrStrMap CONTENT_TYPE = {
#включить «типов MIME.сек»
};

строчка getPath(строчка& путь){

раз(путь == «/»){
path=»/index.html»;
}

путь.аннотация Insert(0, «./ВСП»);

обратный путь;
}

строчка getContentType(строчка& путь){

строковый Тип содержимого(«текст/равнина»);
Роко::путь p(путь);

TStrStrMap::const_iterator я=CONTENT_TYPE.отыскать(п.getExtension());

раз (I != CONTENT_TYPE.конец())
{ /* Отыскали, я->1-ая-Ф, я->2-ой — ++ — */
для contenttype = я->2-ой;
}

раз(Тип содержимого.отыскать(«текст»/»)! = с STD::строчки::НКО)
{
для contenttype+=»; Шифровка=utf-8 в»;
}

вывод << путь << » : «<< характеристики contenttype << епо;

возвращение для contenttype;
}

общественности:

пустота handleRequest(HTTPServerRequest &тр, HTTPServerResponse &Респ)
{
вывод << «получить статическую страничку: «;
//системы(«Эхо-н-1. Текущая директория ‘; инвалидов»);

Ури Ури(исх.getURI());
строчка пути(Ури.getPath());

ifstream ifs (глядеть getPath(путь).с c_str(), ifstream::в);

раз(ксф)
{
отв.setStatus(объект httpresponse::HTTP_OK);
отв.setContentType(getContentType(путь));
поток и = отв.выслать();

типа char с = ИФ.получить();

в то время как (ИС.отлично()) {
наш << с;
с = ИФ.получить();
}

наш.флеш();
}
еще
{
отв.setStatus(объект httpresponse::HTTP_NOT_FOUND);
поток и = отв.выслать();

наш << «файл не найден» << епо;

наш.флеш();
}

в ифи.закрыть();
}
};

класс TodoRequestHandlerFactory : общественная HTTPRequestHandlerFactory
{
общественности:
виртуальный HTTPRequestHandler* createRequestHandler(пост HTTPServerRequest & запросу)
{
раз (!запросу.getURI().отыскать(«/API-интерфейс/»))
возвращение новейшего CTodoHandler;
еще
возвращение новейшего CFileHandler;
}
};

пустота TodoServerApp::createTodo(CTodo задач (todo)
{
ScopedLock<Мьютекс> замок(todoLock);
приложения todolist.сделать(сделать);
}

CTodoList& TodoServerApp::readTodoList()
{
ScopedLock<Мьютекс> замок(todoLock);
возврат приложения todolist;
}

пустота TodoServerApp::deleteTodo(идентификатор Тип size_t)
{
ScopedLock<Мьютекс> замок(todoLock);
приложения todolist.дель(идентификатор);
}

инт TodoServerApp::основная(константный вектор<строчка> &)
{
HTTPServerParams* pParams = новейший HTTPServerParams;

pParams->setMaxQueued(100);
pParams->setmaxthreads способ(16);

Http-сервера с(новейший TodoRequestHandlerFactory, у serversocket(8000), pParams);

ы.способ Start();
вывод << «сервер запущен» << епо;

waitForTerminationRequest(); // ждать Ctrl-C либо уничтожить

вывод << «завершение работы…» << епо;
ы.стоп();

возвращение::EXIT_OK;
}
Независимо от типа услуг запрос постоянно возвращает текущий перечень задач в формате json.

Ответ.в формате json[
{
«_id»: 1,
«текст»: «во-первых»
},
{
«_id»: 2,
«текст»: «во-вторых»
}
]
Код фронтенда практически на сто процентов взят из статьи скотч.ИО/уроки/создание одной странички-todo-приложения-с-узла-и-угловой
Вид index.html состоит из заголовка с количеством рабочих мест, перечня заданий и формы прибавления новейшей задачки. Контроллер js/app.js звонки попасть в перечень во время инициализации. Фронтенд загружается из ./ВСП/ сборники приложения. Фронтэнда употребляется в angularjs. Последующий пост при добавлении новейшего задания в форме, либо удалить, нажав на флаг задания.

index.html<!— index.html —>
<!элемент doctype HTML>в

<!— НАЗНАЧИТЬ НАШЕГО УГЛОВОГО МОДУЛЯ —>
<HTML на НГ-приложение=»pocoTodo»>
<глава>
<!— Мета —>
<Мета шифровку=»Шифровка utf-8″>
<Мета имя=»область просмотра» содержание=»Ширина=устройство-Ширина, исходно-Масштаб=1″><!— Оптимизация мобильного просмотра —>

<заглавие>ПОКО/угловой todo Приложение</заглавие>

<!— Свитки —>
<ссылка отн=»стилей» в href=»//netdna.bootstrapcdn.сом/загрузочный/3.0.0/CSS и/исходной загрузки.мин.в CSS»><!— загрузки —>
<стиль>
в HTML { переполнение-й:прокрутки; }
тело { обивка-топ:в 50px; }
#todo-лист { маржи-вниз:30px; }
</стиль>

<!— Заклинания —>
<скрипт файле src=»// «Аякс».googleapis.сом/Аякс/библиотеки/библиотека jQuery/2.0.3/на jQuery.мин.в JS»></сценарий><!— загрузки jQuery —>
<скрипт файле src=»// «Аякс».googleapis.сом/Аякс/библиотеки/в angularjs/1.0.8/угловой.мин.в JS»></сценарий><!— перегрузки угловой —>
<скрипт файле src=»JS и/приложение.в JS»></скрипт>

</глава>
<!— УСТАНОВИТЕ КОНТРОЛЛЕР И ПОЛУЧИТЬ ВСЕ ТОДОС —>
<тело НГ-контроллер=»mainController»>
<div класс=»контейнер»>

<!— ЗАГОЛОВОК И TODO РАССЧИТЫВАТЬ —>
<div класс=»слонопотам текста-центр»>
<Н2>ПОКО/угловой todo Приложение <просвет класс=»метка метка-инфо»>{{ тодос.длина }}</span>с</Н2>
</дел>

<!— Перечень TODO —>
<див ИД=»todo-лист» класс=»строчка»>
<div класс=»коль-см-4, генерал-см-смещение-4″>

<!— Петли в ТОДОС-в $сферу.тодос —>
<div класс=»флаг» НГ-повтор=»todo в тодос»>
<метка>
<входной Тип=»флаг» НГ клавишей мыши=»deleteTodo(тодо._id)»> {{ todo-списков.текст }}
</ярлычек>
</дел>

</дел>
</дел>

<!— ФОРМА ПРЕДНАЗНАЧЕНА ДЛЯ Сотворения ТОДОС —>
<див ИД=»перечень дел», форма» класс=»строчка»>
<div класс=»коль-см-8-коль-см-смещение-2 текст-центр»>
<форма>
<div класс=»форма-групп»>

<!— Привязать это значение к formData.текст в угловых —>
<входной Тип=»текст» класс=»форма-управляющий вход-ЛГ «текст-центр» заполнитель=»я желаю приобрести щенка, который будет обожать меня вечно» НГ-модель=»formData.текст»>
</дел>

<!— createToDo() делает новейший ТОДОС —>
<Тип клавиши=»Выслать» класс=»бтн» бтн-первичная бтн-ЛГ» НГ клавишей мыши=»createTodo()»>Добавить</клавиша>
</форма>
</дел>
</дел>

</дел>

</тело>
тегом </HTML>

js/app.js// js/app.js
вар pocoTodo = угловой.модуль(‘pocoTodo’, []);

функция mainController($размер, $протоколу http) {
$область.formData = {};
$протокол http.значения по умолчанию.заголовков.пост[«содержимое-Тип»] = «применение/х-www-формы-urlencoded»;

// при высадке на страничке, получить все и показать им тодос
$протокол http.для Get(‘/API-интерфейс/тодос’)
.фуррор(функция(данные) {
$область.тодос — = данные;
консоли.журнальчика(данные);
})
.ошибка(функция(данные) {
консоли.журнальчика(‘ошибка:» + данные);
});

// при подаче добавить форму, отправьте сообщение на номер узла по API
$область.createTodo = функция() {
$протокол http.должность(‘/API-интерфейс/тодос’, $.парам($размер.formData)) // $область.formData)
.фуррор(функция(данные) {
$область.formData = {}; // очистить форму, потому наш юзер готов ввести иной
$область.тодос — = данные;
консоли.журнальчика(данные);
})
.ошибка(функция(данные) {
консоли.журнальчика(‘ошибка:» + данные);
});
};

// стереть этот опосля проверки
$область.deleteTodo = функция(идентификатор) {
$протокол http.удалить(‘/API-интерфейс/тодос/’ + ID (идентификатор)
.фуррор(функция(данные) {
$область.тодос — = данные;
консоли.журнальчика(данные);
})
.ошибка(функция(данные) {
консоли.журнальчика(‘ошибка:» + данные);
});
};

}
Проект репозитория: github.com/spot62/PocoAngularTodo habrahabr.ru