<!--toc-->
|
|
## Introduction
|
|
Now we will learn how to easily connect different URLs to their associated functions.
|
We will learn how to easily connect different URLs to their associated functions.
|
|
When a client requests a specific URL from the HTTP server,
|
it divides it into several parts (CGI variables): `SCRIPT_NAME`, `PATH_INFO` and `QUERY_STRING`. For example
|
the URL `/foo/bar.php/test?x=10` is separated into:
|
|
- `SCRIPT_NAME` = `/foo/bar.php`
|
- `PATH_INFO` = `/test`
|
- `QUERY_STRING` = `x=10`
|
|
CppCMS web applications are not distributed into several
|
scripts, but rather they're written using a single FastCGI application that runs on a specific "script" url, like "/myapp". So generally URLs would look like `/myapp/page/10`, where
|
`SCRIPT_NAME` = "/myapp" would remain constant and `PATH_INFO` = `/page/10` is changed according to the user's needs.
|
scripts, but rather they're written using a single FastCGI application that runs on a specific "script" url, like "/myapp". So, generally, URLs will look like `/myapp/page/10`, where
|
`SCRIPT_NAME` = "/myapp" remains constant and `PATH_INFO` = `/page/10` is changed according to the user's needs.
|
|
So the mapping between the URL and the application's member functions is done by matching a regular expression against the `PATH_INFO` part of the URL, even though this behaviour can be changed by using the `mount_point` class.
|
|
This job is done by the `cppcms::url_dispatcher` class.
|
|
The opposite of dispatching is "mapping", where the names of the application parts are converted to URLs that can be given to the user.
|
|
## Code
|
|
### Mapping
|
|
Lets rewrite our [hello class](/wikipp/en/page/cppcms_1x_tut_hello):
|
|
Since we will be routing URLs, let's include the `url_dispatcher.h` and `url_mapper.h` header file. Your include list should look like:
|
Since we will be routing URLs, let's include the `url_dispatcher.h` and `url_mapper.h` header file. Your include list should look like this:
|
|
#include <cppcms/application.h>
|
#include <cppcms/service.h>
|
#include <cppcms/http_response.h>
|
#include <cppcms/url_dispatcher.h>
|
#include <cppcms/url_mapper.h>
|
#include <cppcms/applications_pool.h>
|
#include <iostream>
|
#include <stdlib.h>
|
|
Now in our constructor, let's map some URLs to member functions:
|
|
hello(cppcms::service &srv) :
|
cppcms::application(srv)
|
{
|
dispatcher().assign("/number/(\\d+)",&hello::number,this,1);
|
mapper().assign("number","/number/{1}");
|
|
dispatcher().assign("/smile",&hello::smile,this);
|
mapper().assign("smile","/smile");
|
|
dispatcher().assign("",&hello::welcome,this);
|
mapper().assign("");
|
|
mapper().root("/hello");
|
}
|
|
|
In the fourth line we connect the regular expression `/number/(\d+)` to the member function `number` of `this`
|
instance that receives `std::string` as parameter,
|
and the 1st captured subexpression is passed to it (note the parameter 1 that represents the 1st subexpression as a parameter)
|
|
In this case the subexpression is a nonempty string that contains digits.
|
|
In the 5th line we create a name for this part called
|
"number" and we provide an URL formatting pattern of `/number/{1}` - the opposite of the regular expression where `{1}` is a placeholder for the first parameter for formatting the appropriate URL.
|
|
In the lines 7-8 we connect the member function `smile`
|
to its URL and create a mapping. Because this URL
|
does not have any parameters it does not have
|
any placeholders.
|
|
On line 10 we connect the empty URL to the
|
`welcome` member function, and on line 11 we define the default empty mapping pattern for the URL. Note, because
|
we pass only one parameter to the `assign()` function,
|
we define the default URL for the application.
|
|
|
On line 13 we define the "root" of all the URLs for the
|
`url_mapper` class, in our case it should be identical to
|
the `SCRIPT_NAME` CGI variable.
|
|
### Description
|
|
|
So when the web server receives requests that match
|
a script name `/hello` it forwards them to the application:
|
|
- `/hello` - `welcome` function would be called
|
- `/hello/smile` - `smile` function would be called
|
- `/hello/number/10` - `number` function would be called and receive a string "10" as a parameter.
|
|
Because the "routing table" between the URL and the
|
application's member functions is done, we don't need
|
to override the `cppcms::application::main` member
|
function as it does all the dispatching for us.
|
|
### Actions
|
|
The "number" member function.
|
|
void number(std::string num)
|
{
|
int no = atoi(num.c_str());
|
response().out() << "The number is " << no << "<br/>\n";
|
response().out() << "<a href='" << url("/") << "'>Go back</a>";
|
}
|
|
Note, we're using `url("/")` as an abstract URL for the default application entry point - the `/` part describes the root application (our single application) and the fact that nothing follows it shows that the default URL should be
|
given - the mapping to the `welcome` member function.
|
|
In the same way we create the `smile` member function:
|
|
void smile()
|
{
|
response().out() << ":-) <br/>\n";
|
response().out() << "<a href='" << url("/") << "'>Go back</a>";
|
}
|
|
Now we write out the `welcome` action:
|
|
void welcome()
|
{
|
response().out() <<
|
"<h1> Welcome To Page with links </h1>\n"
|
"<a href='" << url("/number",1) << "'>1</a><br>\n"
|
"<a href='" << url("/number",15) << "'>15</a><br>\n"
|
"<a href='" << url("/smile") << "' >:-)</a><br>\n";
|
}
|
|
Note, we show three URLs to the different application
|
parts: "number" - and we pass a parameter `1` to the `cppcms::application::url` function that will be rendered instead of the placeholder `{1}`, we do the same for
|
number 15 and pass an URL to "smile" without parameters.
|
|
Lets describe the actions that are taken in the example when we call `url("/number",15)`:
|
|
- First for "/" we go to the topmost application, in out case to `this` one.
|
- Next we match "number" against the known pattern "number" that was mapped to `"/number/{1}"`.
|
- We fetch the pattern and use the parameter that is passed to `url` function and convert: `/number/{1}` to `/number/15`.
|
- Finally we prepend the root URL path "/hello" and get our final URL `/hello/number/15`.
|
|
Note: the parameters to `url` family of functions can be anything that can be written to `std::ostream` - i.e. any object that defines operator `<<` with standard C++ streams.
|
|
## Running The Example
|
|
Recompile it:
|
|
c++ hello.cpp -lcppcms -o hello
|
|
And now for the exciting part, start your application:
|
|
./hello -c config.js
|
|
And hit the URL: <http://localhost:8080/hello>
|
|
---
|
|
← [Using Templates (v 1.x)][prev]
|
| [Top](#maincontent)
|
| [Applications Hierarchy][next] →
|
|
[prev]: /wikipp/en/page/cppcms_1x_tut_hello_templates
|
[next]: /wikipp/en/page/cppcms_1x_tut_hierarchy |