Руководство: URL Mapping (v 1.x)
Введение
Теперь научимся проще соединять различные URL и функции приложения.
Когда клиент запрашивает определенный URL у HTTP-сервера он делится на несколько частей: SCRIPT_NAME
, PATH_INFO
и QUERY_STRING
. Например
URL /foo/bar.php/test?x=10
разделяется на:
SCRIPT_NAME
=/foo/bar.php
PATH_INFO
=/test
QUERY_STRING
=x=10
Современные веб-приложения не разделены на несколько скриптов, а чаще пишутся одним FastCGI-приложением, запущенным на определенном URL типа "/myapp". Т.о. обычно
URL выглядит как /myapp/page/10
, где
SCRIPT_NAME
= "/myapp" остается постоянным и PATH_INFO
= /page/10
- изменяется в соответствии с потребностями пользователя.
Т.о. соответствие между URL и функциями-членами приложения делается по совпадению регулярного выражения с PATH_INFO
частью URL, хотя такое поведение может быть изменено использованием класса mount_point
.
Пример
Давайте перепишем наш класс hello:
Т.к. мы собираемся маршрутизировать URL, добавим заголовочный файл url_dispatcher.h
. Список подключаемых заголовочных файлов будет выглядеть так:
#include <cppcms/application.h> #include <cppcms/applications_pool.h> #include <cppcms/service.h> #include <cppcms/http_response.h> #include <cppcms/url_dispatcher.h> #include <iostream>
Теперь, соединим некоторые URL с функциями-членами в конструкторе:
hello(cppcms::service &srv) : cppcms::application(srv) { dispatcher().assign("/number/(\\d+)", &hello::number, this, 1); dispatcher().assign("/smile", &hello::smile, this); dispatcher().assign("", &hello::welcome, this); }
В четвертой строке мы соединяем регулярное выражение /number/(\d+)
с функцией-членом number
экземпляра this
, получающего std::string
как параметр и переданное в него первое подходящее подвыражение.
В этом случае - подвыражение не пустое, содержащее цифры.
В следующих двух строках соединяются функции-члены smile
и welcome
с предназначенными для них URL.
Т.о., когда имя скрипта HTTP-сервера совпадет с /hello
, тогда для URL
/hello
- будет вызвана функцияwelcome
/hello/smile
- будет вызвана функцияsmile
/hello/number/10
- будет вызвана функцияnumber
со строкой "10" в качестве параметра.
Теперь, когда мы сообщили диспетчеру как маршрутизировать диспетчерские запросы, мы хотим, чтобы наше родительское приложение обрабатывало их. Однако, нам еще требуется определить эти функции-члены.
Замените старую функцию-член main
:
virtual void main(std::string url);
. . . следующими (действиями) функциями-членами:
void number(std::string num) { int no = atoi(num.c_str()); response().out() << "The number is " << no << "\n"; } void smile() { response().out() << ":-)"; } void welcome() { response().out() << "<h1> Wellcome To Page with links </h1>\n" "<a href=\"/hello/number/1\">1</a><br>\n" "<a href=\"/hello/number/15\">15</a><br>\n" "<a href=\"/hello/smile\">:-)</a><br>\n"; }
Не забудьте перекомпилировать проект:
c++ hello.cpp -lcppcms -o hello
А теперь самый интересный момент - запускайте приложение:
./hello -c config.js
И наберите URL: http://localhost:8080/hello