[ic] Interchange with nginx

Gert van der Spoel gert at 3edge.com
Tue Apr 12 20:33:05 UTC 2011


Due to an unforseen circumstance I ended up needing to run Interchange with
nginx ... 

Disclaimer:
1) I do not currently run this in a production environment. I expect it
should work there fine, but if not then well .. not 
2) I have not tested every inch of Interchange (who ever has?) so it could
be that functionality stops working.
    If so, be a sport and give the solution instead of providing the issue
only.
3) It's a lot of steps, I wrote them as I went and debugged and added etc,
so there is a possibility that I missed a spot.
   But with all below you'll get close enough I believe.
4) The steps are as is, I do not claim it to work for anybody else. No
liability on me if your wife will divorce you while you spent 
24 hours to try and get things to work with the below steps, or any
liability in any other case etc .. 

Well, with that out of the way, here we go.

Credits first. Thanks go out to:
- Hartog de Mik ( hartog.de.mik AT simplic.it ) for sending me down the
right track for the nginx configuration.
- http://library.linode.com/web-servers/nginx/perl-fastcgi/debian-5-lenny
for the basic steps of the fastcgi set up
- http://moinmo.in/IvanBoldyrev/MoinMoinWithNginxServer for the workaround
regarding the path_info encoding
- my wife, because she so far has been able to keep up with the hours trying
to get this to work :)

Environment:
- Debian squeeze
- Interchange 5.7.6
- Perl 5.12.3
- nginx 0.8.54

Prerequisites:
- nginx installed (paths used below are pretty much those of the version
that comes via apt-get ... installing from source could possibly yield other
paths)
- Perl installed
- Interchange installed
- Catalog set up  (in /export/www/my.domain.com/catalog in this set up)
- vlink program to have extension .cgi and to be in your documentroot

No doubt it will work with other set ups with a bit of a tweak left and
right.

Open issues:
- In my test I was not able to complete an order using the test creditcard
on the standard Interchange demo. 
  I blame it for now on misconfiguration of my test setup. Check payment did
complete and send e-mail etc.

Steps to fame and fortune:

1)  configure the virtual host for using fastcgi

update nginx configuration file:

a couple of notes:
- try_files is used to determine if a file exists in the document root. if
not found it will make a rewrite and will add the vlink script to the path.
this basically does what one usually does to hide the vlink script from the
URL.
- Interchange needs the PATH_INFO environment variable to be able to process
URLs containing 'process', such as:
  http://my.domain.com/process/locale/nl_NL/page/index.html
  There is a 'fastcgi_split_path_info' call available, but somehow that did
not seem to work for me, so I did my own.
- Interchange also needs the HTTP_COOKIE for passing around mv_session_id
(unless you run your whole site without cookies) ...
- fastcgi_param SERVER_SOFTWARE NginxEncoded/$nginx_version;   is needed to
make sure the PATH_INFO gets correctly decoded else a variety of things
(such as searches) do not want to do what they are supposed to do (see
below)

server {

        listen   80; 

        server_name  my.domain.com;

        access_log  /var/log/nginx/my.domain.com/access.log;
        error_log  /var/log/nginx/my.domain.com/error.log;

        location / {
                root   /export/www/my.domain.com/htdocs;
                index  [vlink] index.html;
                try_files $uri $uri/ @handler;
        }

        location @handler {
                rewrite / /[vlink];
        }

        location ~ .cgi($|/) {

                gzip off;
                expires off;

                set $path_info $request_uri;
                if ($path_info ~ "^([^\?]*)\?") {
                          set $path_info $1;
                }

                include /etc/nginx/fastcgi_params;

                fastcgi_pass  127.0.0.1:8999;
                fastcgi_index [vlink];

                fastcgi_param SERVER_SOFTWARE NginxEncoded/$nginx_version;
                fastcgi_param SCRIPT_NAME $fastcgi_script_name;
                fastcgi_param SCRIPT_FILENAME
/export/www/my.domain.com/htdocs/[vlink];

                fastcgi_param PATH_INFO $path_info;
                fastcgi_param HTTP_COOKIE $http_cookie;
}


2)
configure fastcgi wrapper

cd ~/tmp   (or wherever you want to temporarily store the following files,
credit: Denis S. Filimonov (http://www.ruby-forum.com/topic/145858))
wget
https://library.linode.com/web-servers/nginx/perl-fastcgi/reference/fastcgi-
wrapper
wget
https://library.linode.com/web-servers/nginx/perl-fastcgi/reference/init-deb
.sh

mv fastcgi-wrapper /usr/bin/fastcgi-wrapper.pl
mv init-deb.sh /etc/init.d/perl-fastcgi
chmod +x /usr/bin/fastcgi-wrapper.pl
chmod +x /etc/init.d/perl-fastcgi
update-rc.d perl-fastcgi defaults
/etc/init.d/perl-fastcgi start


3) 
set up vlink to cooperate nicely

3.1) use the vlink.pl script to pass the requests on to Interchange, should
work out of the box, but vlink.pl is not the fastest way to 

run Interchange.

cp /path/to/interchange/src/vlink.pl
/export/www/my.domain.com/htdocs/[vlink]
chown [interchange user].[web user] /export/www/my.domain.com/htdocs/[vlink]
chmod u+s /export/www/my.domain.com/htdocs/[vlink]

3.2)
to make the vlink c program work with the fastcgi libraries we'll have to
compile vlink.c with some modifications.

cd ~/src   (or wherever you store your downloaded source files to
configure/make/install)
wget http://www.fastcgi.com/dist/fcgi.tar.gz
tar xvzf fcgi.tar.gz
cd fcgi-2.4.0
./configure
make
-- at this point make failed with the following error:
fcgio.cpp: In destructor 'virtual fcgi_streambuf::~fcgi_streambuf()':
fcgio.cpp:50: error: 'EOF' was not declared in this scope

edit include/fcgio.h and add the following at line #34:
#include <cstdio>

(this is after #include <iostream>)
make again and it should complete
--
make install

cd /path/to/interchange/src

edit syscfg and change $DEFS and $LIBS.
* old (in my set up, possibly different in others):
...
$DEFS="-DHAVE_CONFIG_H";
$LIBS="-lnsl";
...

* new
...
$DEFS="-DHAVE_CONFIG_H -B fcgi/ -Lfcgi/libfcgi/.libs/";
$LIBS="-lnsl -lfcgi";
...

edit vlink.c
* add after #include <unistd.h>
#include <fcgi_stdio.h>

* add before  /* Give us an EPIPE error instead of a SIGPIPE signal if the
server 
while(FCGI_Accept() >= 0) {

* add after return 0;
}

(basically wrapping the interchange vlink 'main' program into the FCGI
blanket)

cd /path/to/interchange/bin
./compile_link   
cp /path/to/interchange/src/vlink /export/www/my.domain.com/htdocs/[vlink]
chown interchangeuser /export/www/my.domain.com/htdocs/[vlink]
chmod u+s /export/www/my.domain.com/htdocs/[vlink]

4) Patch for Dispatch.pm 

The following will need to be added to Dispatch.pm. I have added it after
the # Fix Cobalt/CGIwrap problem  if block.

        if ($CGI::server_software =~ /^NginxEncoded/) {
                $CGI::path_info =~ tr/+/ /;
                while ($CGI::path_info =~ /%([a-fA-F0-9]{2,2})/ ) {
                        $CGI::path_info =~
s/%([a-fA-F0-9]{2,2})/chr(hex($1))/eg;
                }
        }

5) Patch for Server.pm

The following will need to be added to Server.pm.
    server_software       SERVER_SOFTWARE

I have added this after 
    server_port           SERVER_PORT
in the @Map definition.

Further more in Server.pm I had to make the following update:
old: (around line 538)
      $out .= "Set-Cookie: $name=$value;";
     $out .= " path=$p;";
new:
      $out .= "Set-Cookie: $name=$value;";
      $out .= ' path=/;';

I do expect that this will cause issues for those who are doing a lot of
different cookies throughout the site beside the standard MV_SESSION_ID, but
else $p is set to the interchange vlink script and that is filtered out in
the nginx set up I believe so nginx will not pick the cookie up in
$http_cookie otherwise (from my tests at least).


6) Test , test, test, test, test ...... and hopefully have a beer
afterwards. 

7) Tips etc ...

* If your main page loads but in all other links on your site the vlink
script is showing again then have a look at your variable.txt (or site.txt)
for CGI_URL  ... Clear the value of CGI_URL and things should work better.

* If you get: 502 Bad Gateway, check the permissions on your vlink script
and make sure the setuid bit is set (chmod u+s [vlink script]) ... If that
is not the problem, check if your fastcgi process is (still) running.

* If you get: The Interchange server is busy .... message, then make sure
your vlink.c script has been compiled with the correct location for the
socket file: ./compile_link -s /path/to/interchange/socket/file

Hope it is of use for someone at some point.

CU,

Gert





More information about the interchange-users mailing list