Main  /  Edit version 31  /  Edit version 32  /   /  Users Area

Difference "Configure CppCMS to run with different web servers" ver. 31 versus ver. 32

Content:

<!--toc-->
## Introduction
There are many options to connect CppCMS application to web server:
- Protocol: you can use FastCGI or SCGI protocols,
you can also run over HTTP protocol behind proxy.
Recommendation: use FastCGI as it has best support
over various web servers.
- Application start: it can be started by the web server
and controlled by it or it can run as independent
service when web server only connects to it.
- Communication method: you can use Unix domain sockets
or tcp/ip sockets. For local communication unix sockets
are preferred.
Please note, this tutorial is provided for running
CppCMS based systems in production environment.
It is less friendly for debugging. If you want to debug
your application behind web server, use `cppcms_run`
utility which allows you to prepare web server configurations automatically and run web servers themselves.
It allows you to run your web application behind 3 most popular web servers: Apache, Lighttpd and Nginx using FastCGI, SCGI protocols or use them as Reverse HTTP Proxy.
## Using HTTP Protocol
CppCMS provides basic implementation of HTTP protocol and thus it can run behind reverse HTTP Proxy or be used
in embedded environments. This option is not recommended for use in production environment as internal web
server has quite weak performance in serving static
files and it is very limited options in comparison
to widely used web servers.
## Assumptions
In all our examples we assume:
- Application's executable placed in `/opt/app/bin/hello`
- Application's configuration file placed in `/opt/app/etc/config.js`
- The document root is `/var/www`
- Our application's URL (script) is `/hello`
## Lighttpd
Lighttpd supports both fastcgi/scgi protocols over unix and tcp/ip sockets. It can start the application for you and use external FastCGI/SCGI application.
### Lighttpd, FastCGI
#### Lighttpd, FastCGI, Start by Web Server
You should enable mod-fastcgi and then use this Configuration file:
fastcgi.server = (
## The script name of the application
"/hello" => ((
## Command line to run
"bin-path" => "/opt/app/bin/hello -c /opt/app/etc/config.js",
"socket" => "/tmp/hello-fcgi-socket",
## Important - only one process should start
"max-procs" => 1,
"check-local" => "disable"
))
)
CppCMS configuration:
{
"service" : {
"api" : "fastcgi",
"socket" : "stdin" // use server's socket
}
}
#### Lighttpd, FastCGI, External Start
You should enable mod-scgi and then use this Configuration file:
fastcgi.server = (
## The script name of the application
"/hello" => ((
"socket" => "/tmp/hello-fastcgi-socket",
## Important - only one process should start
"max-procs" => 1,
"check-local" => "disable"
))
)
CppCMS configuration:
{
"service" : {
"api" : "fastcgi",
"socket" : "/tmp/hello-fastcgi-socket"
}
}
If you want to use TCP/IP rather then Unix sockets, replace
- In lighttpd configuration: `"socket" => "/tmp/hello-fastcgi-socket",` by `"host" => "127.0.0.1", "port" => 8081,`
- In cppcms configuration: `"socket" : "/tmp/hello-fastcgi-socket"`, by `"ip": "127.0.0.1" , "port" : 8081,`
### Lighttpd, SCGI
#### Lighttpd, SCGI, Start by Web Server (lighttpd >=1.4.23)
You should enable mod-scgi and then use this Configuration file:
scgi.server = (
## The script name of the application
"/hello" => ((
## Command line to run
"bin-path" => "/opt/app/bin/hello -c /opt/app/etc/config.js",
"socket" => "/tmp/hello-fcgi-socket",
## Important - only one process should start
"max-procs" => 1,
"check-local" => "disable"
))
)
CppCMS configuration:
{
"service" : {
"api" : "scgi",
"socket" : "stdin" // use server's socket
}
}
#### Lighttpd, SCGI, External Start
You should enable mod-scgi and then use this Configuration file:
scgi.server = (
## The script name of the application
"/hello" => ((
"socket" => "/tmp/hello-scgi-socket",
## Important - only one process should start
"max-procs" => 1,
"check-local" => "disable"
))
)
CppCMS configuration:
{
"service" : {
"api" : "scgi",
"socket" : "/tmp/hello-scgi-socket" // use server's socket
}
}
If you want to use TCP/IP rather then Unix sockets, replace
- In lighttpd configuration: `"socket" => "/tmp/hello-scgi-socket",` by `"host" => "127.0.0.1", "port" => 8081,`
- In cppcms configuration: `"socket" : "/tmp/hello-scgi-socket"`, by `"ip": "127.0.0.1" , "port" : 8081,`
## Apache
### Apache, FastCGI
You need to enable at least two modules: `mod_fastcgi` and `mod_alias`
For each case we prepare `mod_fastcgi` configuration file
and out config.js.
**Note:** below we present you an example fastcgi.conf configuration. Be aware that these settings will affect your whole web server. If instead you desire to set these to affect only one specific virtual host, you must place the settings in your virtual host's configuration file (e.g. within `/etc/apache2/sites-available` on a Debian system). Check the official Apache documentation for details.
#### Apache, FastCGI, Start by Web Server
Apache configuration:
FastCgiIpcDir /var/lib/apache2/fastcgi
# Usually it is given in fastcgi.conf by default
FastCgiServer /opt/app/bin/hello -initial-env CPPCMS_CONFIG=/opt/app/etc/config.js -socket /tmp/hello-fcgi-socket
# CPPCMS_CONFIG should hold the path to configuration file.
# Note: you can't pass command line parameter
# so you pass the location of configuration file
# via CPPCMS_CONFIG environment variable
FastCGIConfig -maxProcesses 1 -processSlack 1
# This is important - we want apache to use only
# one process as we have cache and many other
# goodies handled by outsefs
ScriptAliasMatch ^/hello(.*)$ /opt/app/bin/hello$1
# We map script "/hello" to our application
AddHandler fastcgi-script /opt/app/bin/hello
CppCMS configuration:
{
"service" : {
"api" : "fastcgi",
"socket": "stdin" // we use socket given by server
}
}
#### Apache, FastCGI, Independent start
Apache configuration:
FastCgiIpcDir /var/lib/apache2/fastcgi
# Usually it is given in fastcgi.conf by default
FastCgiExternalServer /opt/app/bin/hello -socket /tmp/hello-fcgi-socket
# We provide a socket the application listens on.
ScriptAliasMatch ^/hello(.*)$ /opt/app/bin/hello$1
# We map script "/hello" to our application
AddHandler fastcgi-script /opt/app/bin/hello
CppCMS configuration:
{
"service" : {
"api" : "fastcgi",
"socket": "/tmp/hello-fcgi-socket"
// Same as in apache config
}
}
Now you should run the CppCMS application independently
as `/opt/app/bin/hello -c /opt/app/etc/config.js`
If you want to use TCP/IP sockets and not Unix one change
- in `FastCgiExternalServer` line parameter `-socket` to `-host 127.0.0.1:8081`
- in CppCMS config change `"socket": "/tmp/hello-fcgi-socket"` to `"ip" : "127.0.0.1", "port" : 8081`
### Apache, SCGI
Apache's `mod_scgi` supports only in-depended/external start and works over TCP/IP sockets, so the configuration is quite simple:
Apache's module configuration:
SCGIMount /hello 127.0.0.1:8081
We pass the script name as mount point and ip:port as
point to connect cppcms application.
CppCMS configuration:
{
"service" : {
"api" : "scgi",
"ip" : "127.0.0.1",
"port" : 8081
}
}
Now you should run the CppCMS application independently
as `/opt/app/bin/hello -c /opt/app/etc/config.js` and Apache would connect to it.
## Nginx
Nginx supports only FastCGI protocol with external application start.
Note: Nginx's SCGI module is broken as it does not confirm SCGI specifications: it requires rather HTTP response then CGI one. It does not generate `SCRIPT_NAME` and `PATH_INFO` variables at all. Don't use it!
Also Nginx's fastcgi module require manual generation
of `SCRIPT_NAME` and `PATH_INFO` variables.
### Nginx, FastCGI
Web Server Configuration under `server` section:
# Specify UTL to match
location ~ ^/hello.*$ {
# Socket to communicate
fastcgi_pass unix:/tmp/hello-fcgi-socket;
# Setup value of PATH_INFO variable
fastcgi_split_path_info ^(/hello)((?:/.*))?$;
fastcgi_param PATH_INFO $fastcgi_path_info;
#
# You can either use "include fastcgi_params;"
# or set the variables below manually
#
# All supported CGI variables
fastcgi_param SCRIPT_NAME /hello;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
# Setup value of PATH_INFO variable
fastcgi_split_path_info ^(/hello)((?:/.*))?$;
# Rest CGI variales
fastcgi_param SCRIPT_NAME /hello;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# end of server variables
}
And the usual CppCMS's config:
{
"service" : {
"api" : "fastcgi",
"socket" : "/tmp/hello-fcgi-socket"
}
}
Of course the CppCMS's service should be started independently.
For using TCP/IP protocol replace:
- In nginx's configuration replace the line `fastcgi_pass unix:/tmp/hello-fcgi-socket;` by `fastcgi_pass 127.0.0.1:8081;`
- In CppCMS's configuration as usual: `"socket" : "/tmp/hello-fcgi-socket"`, by `"ip": "127.0.0.1" , "port" : 8081,`
### Nginx, SCGI
First of all before you tru use SCGI I'd recommend
to use FastCGI protocol unless you have very good
reasons.
SCGI protocol implementation for Nginx as several
limitations:
1. It does not define PATH_INFO properly, and thus the
rewriting trick shown below does not fully simulate
it as it does not urldecode PATH_INFO variable
as it is required by CGI specifications.
2. It does not handle CGI headers as expected so
CppCMS should create HTTP headers instead of
CGI ones.
Thus `service.generate_http_headers` option
should be set to true
Web Server Configuration under `server` section:
# Small hack to create something close to PATH_INFO
set $path_info "";
if ( $document_uri ~ ^/hello(.*)$ ) {
set $path_info $1;
}
location ~ ^/hello.*$ {
# Communication protocol
scgi_pass unix:/tmp/hello-scgi-socket;
# Setup CGI variables
scgi_param SCRIPT_NAME /hello;
scgi_param PATH_INFO $path_info;
#
# You can either use "include scgi_params;"
# or set the variables below manually
#
scgi_param QUERY_STRING $query_string;
scgi_param REQUEST_METHOD $request_method;
scgi_param CONTENT_TYPE $content_type;
scgi_param CONTENT_LENGTH $content_length;
scgi_param SCRIPT_NAME /hello;
scgi_param PATH_INFO $path_info;
scgi_param REQUEST_URI $request_uri;
scgi_param DOCUMENT_URI $document_uri;
scgi_param DOCUMENT_ROOT $document_root;
scgi_param SERVER_PROTOCOL $server_protocol;
scgi_param GATEWAY_INTERFACE CGI/1.1;
scgi_param SERVER_SOFTWARE nginx;
scgi_param REMOTE_ADDR $remote_addr;
scgi_param REMOTE_PORT $remote_port;
scgi_param SERVER_ADDR $server_addr;
scgi_param SERVER_PORT $server_port;
scgi_param SERVER_NAME $server_name;
# end of scgi_params
}
And the special CppCMS's configuration for Nginx.
{
"service" : {
"api" : "fastcgi",
"socket" : "/tmp/hello-fcgi-socket",
"generate_http_headers" : true
}
}
Of course the CppCMS's service should be started independently.
For using TCP/IP protocol replace:
In nginx's configuration replace the line `scgi_pass unix:/tmp/hello-fcgi-socket;` by `scgi_pass 127.0.0.1:8081;`
## IIS
Before you try to use IIS in front of CppCMS I'd recommend
you to chose another web server that is more friendly
to web developers who use web server independent
API like FastCGI.
### Best Approach
Configure CppCMS with some other good web server like
Apache or Nginx and forward requests from IIS to it.
### HTTP Connectivity
Is probably the most solid option. Forward all requests
relevant to the web application the the CppCMS
internal web server - use IIS as reverse proxy.
Note: give IIS the job of serving static files. It
would likely do it better then CppCMS internal
web server.
### FastCGI Connectivity
FastCGI - don't use it, it was designed to run PHP and
nothing more.
IIS's FastCGI implementation is broken and
[does not support](http://forums.iis.net/t/1155551.aspx)
multi-threaded FastCGI applications.
It also does not provide an option to configure
specific port making it even impossible to use
CppCMS application with IIS.
### SCGI Connectivity
#### Using with ISAPI SCGI.
There is SCGI ISAPI extension that allows to use
external SCGI applications:
[isapi\_scgi](http://woof.magicsplat.com/isapi_scgi/home)
However it has two big limitations:
1. It does not support real CGI response from the client
and expects HTTP response.
Starting from CppCMS 0.99.10 it is possible to
set an option `service.generate_http_headers` to `true`.
This option tells CppCMS to generate HTTP rather
then CGI response headers.
Using this option it was possible to run successfully
CppCMS application with IIS.
2. It supports only predefined set of HTTP headers
so if you will need to get custom headers from
for example AJAX responses you'll need to alter
`isapi_scgi` sources.
In order to configure ISAPI extension follow
the instructions on this
[web site](http://woof.magicsplat.com/isapi_scgi/home).
The CppCMS configuration should look like this:
{
"service" : {
"api" : "scgi",
"ip" : "127.0.0.1",
"port" : 9999,
"generate_http_headers" : true
}
}
#### Troubleshooting ISAPI SCGI extension.
First of all you can get sources for `isapi_scgi.dll`
at:
<http://twapi.cvs.sourceforge.net/viewvc/twapi/isapi/>
Just click download GNU Tarball.
There are several reasons to build it on your own:
- Currently the project provides only 32 bit builds of
this dll, if you need 64 bit or you'll need to build
it manually.
- If you need support of custom HTTP headers you'll have
to add them in scgi.c.
If you want to build it with gcc you need to apply
following changes:
--- scgi_old.h 2011-08-17 10:48:32.109547500 +0300
+++ scgi.h 2011-08-17 10:50:26.184022000 +0300
@@ -37,3 +37,3 @@
*/
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) || defined(__GNUC__)
# define COPY_MEMORY(d, s, n) memcpy((d), (s), (n))
@@ -48,3 +48,3 @@
ZLINK_CREATE_TYPEDEFS(context_t);
-typedef struct context {
+struct context {
OVERLAPPED ovl; /* Must be first structure */
@@ -81,3 +81,3 @@
buffer_t buf; /* Data buffer */
-} context_t;
+};
And the you'll be able to build the DLL as:
gcc -O2 -shared buffer.c scgi.c logger.c -lws2_32 -o isapi_scgi.dll
## Configuring Other Web Servers
When it comes to configuration of the web servers not mentioned above you should consider following points:
1. If the web server allows you to start the application
you should make sure it starts only a single process.
Otherwise you may experience problems with cache
invalidation, session management and your asynchronous
applications would likely not work as they don't
share the same process.
2. Make sure that the FastCGI or SCGI support confirm
to the standard. For example: Nginx's
SCGI connectors do not parse `Status` HTTP header
and create correct response; IIS's SCGI module
does not send HTTP status line at all and expect
HTTP like CGI output.
3. Prefer FastCGI protocol if available as implementations
of SCGI usually have lower quality.
4. Under Microsoft Windows platform, named pipes
are not supported, only TCP/IP connections
should be used.
Note: under Windows named pipes are frequently
used as replacement of Unix sockets, they are not
supported as they have very different behavior.
5. Make sure that `SCRIPT_NAME` and `PATH_INFO` CGI
variables are set correctly.
In our case, given URL `/hello/you`
`SCRIPT_NAME` should be `/hello` and `PATH_INFO`
should be `/you`
## Notes for CppCMS 0.0.x users
CppCMS 0.0.x's web server setup is similar to CppCMS 1.x.x
one, as both support FastCGI and SCGI protocols, however
the configuration file of the 0.0.x version is quite different.
See:
- [CppCMS 0.0.x Configuration](/wikipp/en/page/ref_config#server-api)
- [CppCMS 1.x.x Configuration](/wikipp/en/page/cppcms_1x_config#service)
The protocol is specified as "service.api" and allows options "fastcgi" and "scgi".
However the communication is different.
- Unix domain socket defined as:
`service.socket = "/path/to/socket"`
- TCP/IP socket defined as
`service.socket = "IP:PORT"`
- Socket taken from standard input - just make sure that `service.socket` is not defined.
For example:
1. FastCGI, TCP/IP
CppCMS 1.x.x
{
"service" : {
"api" : "fastcgi",
"ip" : "127.0.0.1",
"port" : 6000
}
}
CppCMS 0.0.x
service.api = "fastcgi"
service.socket = "127.0.0.1:6000"
2. SCGI, Unix Socket
CppCMS 1.x.x
{
"service" : {
"api" : "scgi",
"socket" : "/tmp/app.sock",
}
}
CppCMS 0.0.x
service.api = "scgi"
service.socket = "/tmp/app.sock"
3. FastCGI, standard input (started by web server)
CppCMS 1.x.x
{
"service" : {
"api" : "fastcgi",
"socket" : "stdin",
}
}
CppCMS 0.0.x
service.api = "fastcgi"
# service.socket - undefined

About

CppCMS is a web development framework for performance demanding applications.

Support This Project

SourceForge.net Logo

Поддержать проект

CppCMS needs You


Navigation

Main Page


Valid CSS | Valid XHTML 1.0