CGI or Common Gateway Interface (don't confuse yourself with Computer-Generated Imagery and again don't confuse yourself with imaginary) is an interface specification for web servers to execute programs like console applications. (source wikipedia). The examples are tested on a Apache web server and should, once build, be uploaded in the Apache cgi folder which, when unchanged is in /usr/lib/cgi-bin.
You can access, when all is done the right way, with http://localhost/cgi-bin/programname.

Installing Apache web server and cgi support

I'm not going to describe every step in the installation process of an Apache web server and cgi support. There is a lot of information on the internet with detailed explanations if you like. I just set the commands here to be able to start with your own examples.

sudo apt update
sudo apt install apache2 libapache2-mod-fastcgi
sudo a2enmod cgi fcgid
sudo a2enconf serve-cgi-bin

webpages, javascript files etc... go in /var/www/html
cgi scripts and binaries in /usr/lib/cgi-bin

Also for eas(y)(ier) access add your user to the www-data group.

Debugging cgi applications

Because Apache makes use of the environment variables and an access.log and error log you should make yourself familiar with it, to test the examples (or your own projects) without uploading each time the application to a web server. If you are completely new to the matter, it can be a bit confusing and demotivating. Therefor this page. Oh and before I forget it: test it on your localhost or an non-production Apache server if you intend to empty your log files quite often. There is other information stored in those files which can be useful for others beside yourself.

Default locations for Apache log files

error.log : most if not all errors go in this file, you can find it at /var/log/apache2/error.log
access.log : all access is stored here, the file itself is at /var/log/apache2/access.log

To empty the files truncate -s 0 /var/log/apache2/error.log (or access.log depend the one you want to make empty). You need root access.

Use tail -f /var/log/apache2/access.log in one terminal and tail -f /var/log/apache2/error.log in a second one to watch the progress of your cgi application can be a nice suggestion.

Debugging before deploying the applications

You cannot make use of the access and error log files of Apache when you run your application from a terminal. Indeed cgi applications are de facto console programs with that difference that a post of the result to a web browser needs a header.

"Content-type: text/html", 10, 10

This header should always be the first you send before anything else.

Four web variables are quite important: REQUEST_METHOD (either GET or POST as value), CONTENT_LENGTH if the REQUEST_METHOD is POST and QUERY_STRING when the REQUEST_METHOD is GET. These must be set with printenv when you want to run your application in a debugger or straight from the console. After the deployment of your application you don't have to do that anymore.

For example:

You want to run or debug an application which gets the querystring and does some operations on it, let us say an addition of a value in a with a value in b. The url send to the server is something like: http://localhost/add?a=10&b=20.

Before running your application open a terminal if not already opened and type:

export REQUEST_METHOD=GET
export QUERY_STRING='a=10&b=20'

and run your application. If your program works like a charm you should see the result on stdout surrounded by some tags and always preceeded by Content-type: text/html and one blank line.

Same as for REQUEST_METHOD=POST but then you have to set CONTENT_LENGTH to the length of your content that you want to post. One new problem: what about the content?

Because the content must be read from the page header, your application will suddenly stop. That's the moment you have to enter your content. As in our addition example above, you have to:

export REQUEST_METHOD=POST
and type in yourself: a=10&b=20 followed by enter.

That's all for the moment, feel free to look at the examples on my website. To build the examples as a whole you can use next Makefile.

All examples can be downloaded here.


TARGETS=cgiroot cookies downloaddata downloadfile jsonobject parsejsonobject postrequest querystring webvars

ASM=/usr/bin/nasm
LD=/usr/bin/ld
ASMOPTS=-felf64
LDOPTS=-m elf_x86_64 -lc --dynamic-linker /lib64/ld-linux-x86-64.so.2
LIBS= `pkg-config --libs gtk+-3.0`

.PHONY: all clean pristine

all: $(TARGETS)

clean:
	rm -f $(TARGETS) *.o

pristine: clean

%: %.asm
	$(ASM) $(ASMOPTS) -o $@.o $<
	$(LD) -o $@ $(LDOPTS) $@.o $(LIBS)

more on Apache CGI: https://httpd.apache.org/docs/2.4/howto/cgi.html