Table of Contents
The Complete Guide in Getting FastCGI running with C++ on Ubuntu/NGINX
Intro
I’m old school. I’ve programmed web-sites using C++ and CGI, and I can hear people groaning. Even with fork-exec, my programs ran multiple times faster than the equivalent in Php. With FastCGI and C++, I will put all doubt to rest and will publish tests when I get around to it. It should also be noted that C++ as a CGI programming language is inherently more secure than the equivalent in other interpreted languages.
DISCLAIMER - I’m not a C++ developer. There’s stuff I just don’t know well enough, but I do know enough to write some pretty awesome code, without worrying about memory leaks. In other words, I keep things simple and readable.
DISCLAIMER 2 - Like many of you, I’ve cobbled code together from different sources, because in many examples, I found their code just didn’t work. This code WILL work !
WHAT ALL THIS DOES
A C++ Program that runs as a fastCGI code, reads and parses the QUERY_STRING, and runs with either POST or GET
How FastCGI differs from Regular CGI
Regular CGI
In regular CGI, a request comes in. One of the web servers forks a new process, which then becomes it’s processing and returns the response. The forking and then mutating into the process (fork-exec is an interesting side conversation) is a time consuming process and doesn’t scale well.
Added Read: All About fork/exec.
FastCGI
In fastCGI, the program you wrote is always running. The webserver gets a request, sees it’s fastCGI routine and hands off the work to the program, which then returns the response. In this example, we are using port 8000 and the firewall is closed to that port, indicating that no communication between the program and the calling unit occurs.
Requirements for this paper
- Debian flavored Linux (debian, Ubuntu, Mint, etc.)
- NGINX (not Apache)
- The following packages
- sudo apt-get install libfcgi-devsudo
- apt-get install spawn-fcgisudo
- apt-get install nginxsudo
- apt-get install curl
The Gnu C++ compiler Configuring the Web Server Create a Directory First, create a directory for your fastCGI binary. It should be under your DOCUMENT_ROOT directory. Ie. For me, my site was located under /var/www/mikelivolsi.com/public_html, so I created a directory: mkdir /var/www/mikelivolsi.com/public_html/fcgichown www-data:www-data /var/www/mikelivolsi.com/public_html/fcgi
Configuring NGINX Config On Ubuntu (this should run on releases 18 and up), just add the following to any of your configuration files under /etc/nginx/sites-available, under the server bracket. server { … location /fcgi/ { gzip off; fastcgi_pass 127.0.0.1:8000; include fastcgi_params; } # Other listening stuff
Restart nginx: sudo systemctl restart nginx Explanation Location is where you will place your fastCGI scripts. The 127.0.0.1:8000 is how the web server will connect to the fastCGI program that will listen on port 8000 Factcgi_params come with nginx/ubuntu and have all the goodness to make your fastCGI stuff work You are now done with the NGINX webserver. Getting ready to Test You’re going to want to test POST and GET form submission. So for the POST, let’s create a basic page that will submit a form. Place this under any place you store your HTML
<!DOCTYPE html>
<html lang="en">
<head><title>Testing fast CGI</title></head>
<body>
<form method="post" action="/fcgi/fast.cgi">
<input length=20 id='inputField' name="fastInput">
<input name="subButton" type=button onClick="form.submit()" value='Submit'>
<form>
</body>
</html>
NOTE: I called this fast.html Hmmm.. it looks like I’m going to call a program called “fast.cgi” under the fcgi directory Create Compile Scripts Before we get to coding, let’s set up the compile scripts. The program will create an object file whose purpose is to break up the query string into name/value pairs. This will be helpful later on in your code to find out the values for each field in your HTML form. g++ common.cpp -c -Wall -Wno-deprecatedmv common.o ./objects
The meat and potatoes program. This will compile the fast.cpp into fast.cgi using the object file above. If everything is cool, it will spawn the process (here it’s port 8000, but can be anything) and wait for incoming connections from NGINX.
g++ fast.cpp objects/parse.o -lfcgi++ -lfcgi -Wall -Wno-write-strings -o fast.cgi
typeset -i Rc=$?
if (( $Rc == 0 )); then
echo "Installing ..."
sudo pkill -9 fast.cgi
sudo cp ./fast.cgi /var/www/mikelivolsi.com/public_html/fcgi/fast.cgi
sudo chown www-data:www-data /var/www/mikelivolsi.com/public_html/fcgi/fast.cgi
echo "Spawning ..."
sudo spawn-fcgi -p 8000 -n /var/www/mikelivolsi.com/public_html/fcgi/fast.cgi &
echo "Done"
fi
The Program
Because this is what you want and don’t need a long winded explanation.
- The parser code:
The actual CGI code
Just some notes
- The fast.cpp is a combination of two pieces of code I found.
- The first one (which didn’t work correctly) didn’t really parse out the query string (which is what you really want).
- The second had different calls to stdout and stdin, so I used the code from one code that used cout and cin.
- If changing my code, don’t change cout to std::cout, otherwise output will be sent to the console and not returned to the calling program.
- You can also call this program via “get”. ie . fast.cgi?fastInput=abcdefg vs using the html form.
