summaryrefslogtreecommitdiff
path: root/cgi.html
blob: f54d5475fe25e2cf710426ee4d43afcb04613726 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
<!DOCTYPE html>
<html lang=en>
    <head>
        <title>Server-Side Scripting with CGI</title>
        <meta charset="utf-8"/>
        <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
        <link rel='stylesheet' type='text/css' href='style.css'>
        <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel='alternate' type='application/rss+xml' title='Land Chad RSS' href='/rss.xml'>
    </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 &mdash; 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&amp;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&amp;b=32</code>), the part
        starting from the question mark, <code>?a=10&amp;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 &mdash; 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/crypto.html">donate</a></li>
        </ul>
    </main>
	<footer><a href="https://landchad.net">LandChad.net</a></br>Because Everyone should be an Internet LandChad.</br><a href="index.html"><li><img src="pix/chad.gif" alt="chad"></li></a><a href="rss.xml"><li><img src="pix/rss.svg" alt="RSS"></li></a><a href="pix/btc.png"><li><img src="pix/btc.svg" alt="BTC"></li></a><a href="pix/xmr.png"><li><img src="pix/xmr.svg" alt="XMR"></li></a><a href="https://github.com/lukesmithxyz/landchad"><li><img src="pix/git.svg" alt="Github"></li></a></footer>
</body>
</html>