265 lines
9.3 KiB
HTML
265 lines
9.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang=en>
|
|
<head>
|
|
<title>Server-Side Scripting with CGI</title>
|
|
<!--# include file=".nav.html" -->
|
|
</head>
|
|
<body>
|
|
<header><h1>Server-Side Scripting with CGI</h1></header>
|
|
<nav></nav>
|
|
<main>
|
|
<p>
|
|
The basic website tutorial here describes how to set up a static
|
|
website — one that just serves HTML files saved on your server,
|
|
and until you change something manually, the same content will be served
|
|
each time a given page is requested. This is perfectly enough for most
|
|
personal website needs. This is how blogs should be implemented, instead
|
|
of relying on bloatware like WordPress!
|
|
</p>
|
|
|
|
<p>
|
|
But sometimes you genuinely <i>do</i> need something more. You need your
|
|
website to serve different contents depending on the time, on who the
|
|
requester is, on the contents of a database, or maybe process user input
|
|
from a form.
|
|
</p>
|
|
|
|
<h2>CGI</h2>
|
|
<p>
|
|
CGI, or the Common Gateway Interface, is a specification to allow you,
|
|
the server owner, to program your web server using pretty much any
|
|
programming language you might know. The specification is almost as old
|
|
as the Internet itself and for a long time CGI scripting was the primary
|
|
method of creating dynamic websites.
|
|
</p>
|
|
|
|
<p>
|
|
CGI is a very simple specification indeed. You write a script in your
|
|
favorite language, the script receives input about the request in
|
|
environment variables, and whatever you print to the standard output
|
|
will be the response. Most likely, though, you will want to use a
|
|
library for your language of choice that makes a lot of this
|
|
request/response handling simpler (e.g. parsing query parameters for
|
|
you, setting appropriate headers, etc.).
|
|
</p>
|
|
|
|
<h3>Limitations of CGI</h3>
|
|
<p>
|
|
While in theory you could implement any sort of functionality with CGI
|
|
scripts, it's going to get difficult managing a lot of separate scripts
|
|
if they're supposed to be working in tandem to implement a dynamic
|
|
website. If you want to build a full out web application, you'd probably
|
|
be better off learning a web framework than gluing together Perl
|
|
scripts.
|
|
</p>
|
|
|
|
<p>
|
|
That said, just as most of the web could be replaced with static
|
|
websites, much of the remaining non-static web could be replaced with a
|
|
few simple scripts, rather than bloated Ruby on Rails or Django
|
|
applications.
|
|
</p>
|
|
|
|
<h2>Let's write a CGI script!</h2>
|
|
|
|
<p>
|
|
We'll implement a simple example CGI script. I'll use Ruby for this
|
|
tutorial, but you'll be able to follow along even if you don't know
|
|
Ruby, just treat it as pseudocode then find a CGI library for your
|
|
language.
|
|
</p>
|
|
|
|
<h3>The working example</h3>
|
|
|
|
<p>
|
|
Our working example will be the Lazy Calculator. Yeah, you're probably
|
|
tired of seeing calculator examples in every programming tutorial, but
|
|
have you ever implemented one that takes the weekends off?
|
|
</p>
|
|
|
|
<p>
|
|
Here's how it will work. When in a browser you submit a request to your
|
|
website like
|
|
</p>
|
|
|
|
<pre><code>example.com/calculator.html?a=10&b=32</code></pre>
|
|
|
|
<p>
|
|
you will receive a page with the result of the addition of 10 and 32:
|
|
42.
|
|
</p>
|
|
|
|
<p>
|
|
<i>Unless</i> you send your request on a weekend. Then the website will
|
|
respond with
|
|
</p>
|
|
|
|
<pre><code>I don't get paid to work on weekends! Come back Monday.</code></pre>
|
|
|
|
<p>
|
|
This example will show a few things that CGI scripts can do that you
|
|
wouldn't have been able to get using just file hosting in your
|
|
web server:
|
|
|
|
<ul>
|
|
<li> getting inputs from the user; </li>
|
|
<li>
|
|
getting external information (here just the system time, but you
|
|
could imagine instead connecting to a database);
|
|
</li>
|
|
<li> using the above to create dynamic output. </li>
|
|
</ul>
|
|
|
|
<h3>The code</h3>
|
|
|
|
<p>
|
|
Here's an implementation of the lazy calculator as a Ruby CGI script:
|
|
</p>
|
|
|
|
<pre><code>#!/bin/env ruby
|
|
|
|
require 'cgi'
|
|
require 'date'
|
|
|
|
cgi = CGI.new
|
|
today = Date::today
|
|
|
|
a = cgi["a"].to_i
|
|
b = cgi["b"].to_i
|
|
|
|
if today.saturday? || today.sunday?
|
|
cgi.out do
|
|
"I don't get paid to work on weekends! Come back Monday."
|
|
end
|
|
else
|
|
cgi.out do
|
|
(a + b).to_s
|
|
end
|
|
end</code></pre>
|
|
|
|
<p>
|
|
Let's go through what's happening here.
|
|
</p>
|
|
|
|
<h3>The shebang line</h3>
|
|
<p>
|
|
CGI works by pointing your web server to an executable program. A Ruby
|
|
or Python script by itself is not immediately executable by a computer.
|
|
But on Unix-like systems you can specify the program that will be able
|
|
to execute your file in its first line if it starts with <code>#!</code>
|
|
(known as the shebang; read more about it on
|
|
<a href="https://en.wikipedia.org/wiki/Shebang_(Unix)">Wikipedia</a>).
|
|
</p>
|
|
|
|
<p>
|
|
So if you're going to be using a scripting language, you'll probably
|
|
need the appropriate shebang line at the top of your script. If you use
|
|
a compiled language, you'll just point your web server to the compiled
|
|
executable binary.
|
|
</p>
|
|
|
|
<h3>Query parameters</h3>
|
|
<p>
|
|
The next interesting lines of code are where we set the variables
|
|
<code>a</code> and <code>b</code>. Here we are getting user inputs from
|
|
the request.
|
|
</p>
|
|
|
|
<p>
|
|
In the example request we mentioned above
|
|
(<code>example.com/calculator.html?a=10&b=32</code>), the part
|
|
starting from the question mark, <code>?a=10&b=32</code>, is the
|
|
<i>query string</i>. This is how users can submit parameters with their
|
|
web requests. Usually these parameters are set by e.g. a form on your
|
|
website, but in our simple example we'll be just manually manipulating
|
|
the URL.
|
|
</p>
|
|
|
|
<p>
|
|
The query string contains key-value pairs. The Ruby CGI library makes
|
|
them available in the <code>CGI</code> object it provides. We just need
|
|
to index it with the desired key, and we'll get the corresponding value.
|
|
</p>
|
|
|
|
<h3>Wrapping it up</h3>
|
|
<p>
|
|
The remaining parts of the code should be pretty self-explanatory. We
|
|
get today's date, check if it's a Saturday or a Sunday, and depending on
|
|
that, we instruct the CGI library to output either the answer, or a
|
|
"come back later" message.
|
|
</p>
|
|
|
|
<p>
|
|
The Ruby library by default returns an HTML response, so we really
|
|
should have wrapped our outputs in some <code>html</code>,
|
|
<code>body</code>, etc. tags. Alternatively, we could have specified
|
|
that the response is just plain text with
|
|
</p>
|
|
|
|
<pre><code>cgi.out 'text/plain' do</code></pre>
|
|
|
|
<p>
|
|
In general, your CGI library will probably have ways of specifying all
|
|
sorts of HTTP response headers, like status code, content type, etc.
|
|
</p>
|
|
|
|
<h2>Making it work</h2>
|
|
<p>
|
|
We have a CGI script, now let's point our web server to it.
|
|
</p>
|
|
|
|
<h3>Installing FastCGI</h3>
|
|
|
|
<p>
|
|
If you're using Nginx, install <code>fcgiwrap</code>:
|
|
</p>
|
|
|
|
<pre><code>apt install fcgiwrap</code></pre>
|
|
|
|
<p>
|
|
This installs the necessary packages for Nginx to use FastCGI — a
|
|
layer between your web server and CGI script that allows for faster
|
|
handling of scripts than if the web server had to handle it all by
|
|
itself.
|
|
</p>
|
|
|
|
<p>
|
|
Other web servers will probably have a similarly simple way of enabling
|
|
FastCGI, or you can look into other methods for launching CGI scripts.
|
|
</p>
|
|
|
|
<h3>Nginx configuration</h3>
|
|
<p>
|
|
In the configuration file for your website, add something like the
|
|
following:
|
|
</p>
|
|
|
|
<pre><code>location /calculator.html {
|
|
include fastcgi_params;
|
|
fastcgi_param SCRIPT_FILENAME /usr/local/bin/lazy-calculator.rb;
|
|
fastcgi_param QUERY_STRING $query_string;
|
|
fastcgi_pass unix:/run/fcgiwrap.socket;
|
|
}</code></pre>
|
|
|
|
<p>
|
|
<code>fastcgi_param</code> directives specify various parameters for
|
|
FastCGI. <code>SCRIPT_FILENAME</code> should point to your executable.
|
|
For <code>QUERY_STRING</code>, we just copy Nginx's
|
|
<code>$query_string</code> variable. You might want to pass other
|
|
information to your CGI script as well, see for example
|
|
<a href="https://wiki.debian.org/nginx/FastCGI">the Debian wiki</a> for
|
|
a more detailed example, including pointing to an entire directory of
|
|
CGI scripts, rather than adding each one by hand to your web server
|
|
config.
|
|
</p>
|
|
|
|
<h2>Contribution</h2>
|
|
<ul>
|
|
<li>Martin Chrzanowski -- <a
|
|
href="https://m-chrzan.xyz">website</a>, <a href="https://m-chrzan.xyz/donate.html">donate</a></li>
|
|
</ul>
|
|
</main>
|
|
<!--# include file=".footer.html" -->
|
|
</body>
|
|
</html>
|