Fast-CGI for RESTful Endpoints
What is Fast-CGI?
Fast-CGI is a high-performance extension of the older Common Gateway
Interface (CGI) standard. Instead of creating a brand new process for
every incoming request, a Fast-CGI program stays alive and communicates
with the webserver through a persistent connection.
Traditional CGI not only created and destroyed a process for every
request, it also forced the application itself to restart completely.
This meant re-allocating memory, reinitializing variables, reconnecting
to databases, then on completion disconnecting and freeing everything
again. These steps are far more expensive than process creation alone.
Fast-CGI avoids this overhead by keeping the program alive between
requests. Memory stays allocated, variables remain in scope, and
database connections can be kept open for reuse. The result is a system
that is dramatically more efficient and responsive under load.
This design allows Sheerpower programs to respond quickly, handling
thousands of requests per second on a modern consumer-level computer,
and maintain state between calls if needed.
In practice, the SPINS_WEBSERVER places each incoming request
into a work queue specific to each named handler. Your Sheerpower Fast-CGI handler polls this queue,
reads the request, and writes the response. This gives you RESTful APIs
that are fast, efficient, and easy to extend.
This Tutorial Explained
This tutorial shows how to build a simple REST endpoint in
Sheerpower using the
SPINS_WEBSERVER
and a Fast-CGI interface. In this example, we will serve word definitions
from a CSV file and return a simple plain-text response.
What you’ll learn
- How Fast-CGI handlers are named (
cgi://NAME
)
- How the request queue is polled with
line input #cgi_ch:
- How to read query params via
getsymbol$()
- How to look up rows efficiently with
findrow()
- The SPINS_WEBSERVER automatically supplies the CGI headers if none are specified,
based on the filetype (.txt in this example).
1) Start SPINS
C:>spins_webserver
Sheerpower InterNet Services Web Server SPINS_WEBSERVER Vnn.nn
Copyright (c) 2005-2025 Touch Technologies, Inc.
Listening IP address is 0.0.0.0
Spoofed>> "Server: Apache/2.4.52 (Ubuntu)"
Port 4, wwwroot is C:\Sheerpower\sphandlers\wwwroot\
Port 80, wwwroot is C:\Sheerpower\sphandlers\wwwroot\
2) Create the data file
Place a
words.csv
next to your handler:
ZORI,"Japanese sandals"
ZOUK,"A Caribbean music style"
ZYME,"An enzyme"
AAHED,"to exclaim in surprise [v]"
3) Build and run this minimal Fast-CGI handler
// Program: word_handler.spsrc — minimal Fast-CGI demo
// Test: http://localhost/scripts/spiis.dll/word/get_def.txt?word=ZOUK
// Register the handler as "WORD"
handler_name$ = "cgi://WORD"
// Track persistence across requests
request_counter = 0
// Load dictionary into memory (runs once at startup)
cluster words: word$, def$
cluster input name "@words.csv", headers 0: words
print "Words loaded: "; size(words)
print sprintf$("%t WORD handler ready")
// Attach handler to SPINS_WEBSERVER
open file cgi_ch: name handler_name$
do
// Poll for next request (empty string = nothing yet)
line input #cgi_ch: method$
if method$ = "" then repeat do
request_counter++
// Get query symbol "word" (auto-trimmed by default)
word$ = getsymbol$("word")
if word$ = "" then
print #cgi_ch: "error,Missing 'word' parameter -- request "; request_counter
repeat do
end if
// Lookup (case-insensitive by default)
row = findrow(words->word$, word$)
if row = 0 then
print #cgi_ch: "error,Word not found: "; word$; " -- request "; request_counter
repeat do
end if
// Success: return definition, quoted for CSV safety
print #cgi_ch: "success,"; quote$(words->def$); " -- request "; request_counter
loop
end
4) Try it in your browser
Use this syntax:
http://localhost/scripts/spiis.dll/word/get_def.txt?word=ZOUK
Example response
success,"A Caribbean music style" -- request 1
SPINS I/O Handling and Asynchronous Design
line input #cgi_ch:
polls the SPINS work queue.
If the queue is empty, SPINS waits 1/100th of a second and checks again.
If it is still empty, the call returns an empty string (""
).
This design is efficient: it avoids wasting CPU cycles on busy polling,
while remaining non-blocking and responsive as soon as work arrives.
- All communication with
SPINS_WEBSERVER
is asynchronous,
using globally shared memory.
This makes I/O non-blocking and nearly instantaneous, allowing handlers
to keep working while exchanging data without delay.
Browser
⇄
SPINS_WEBSERVER
⇄
Handlers
Shared Memory (non-blocking I/O)
All handler communication with SPINS_WEBSERVER
is asynchronous
through shared memory, making data exchange nearly instantaneous.
Scaling with Multiple Handlers
Fast-CGI handlers in Sheerpower can be scaled to match the power of
your system. There are two main approaches:
-
Multiple instances of the same handler: You can
start several copies of the same Fast-CGI program (for example,
word_handler.spsrc
). Each instance will attach to the
same handler name and pull requests from the same queue. On a
multi-processor system, this allows requests to be processed in
parallel, taking full advantage of available CPUs.
-
Non-blocking polling:
Within each handler process, the
do ... loop
uses
non-blocking polling to check for work, which is highly
efficient. The processing of each request is
synchronous. A task that takes significant time to complete
will tie up that handler instance, allowing other handler
instances to pick up subsequent requests.
-
Different handlers with unique names: You can run
multiple Fast-CGI programs simultaneously, each with a different
handler name. For example, one handler may provide
word definitions, while another handles logging or JSON responses.
Each handler has its own request queue managed by the webserver.
This flexibility means you can design your Sheerpower web applications
to scale easily with hardware resources, or separate tasks into cleanly
defined services.
Summary: With just a few lines of code you can create a
RESTful API using Fast-CGI in Sheerpower. Extend this to JSON, CORS,
authentication, or larger datasets by changing the body logic.
Unlike other major development environments, this Fast-CGI demo requires
no external dependencies, frameworks, or libraries.
Everything you need is built directly into Sheerpower, so once
the SPINS_WEBSERVER is running the handler runs immediately.
(Show/Hide Fast-CGI Takeaways)
Takeaways
-
Fast-CGI keeps programs alive between requests, making responses
very fast.
-
SPINS places requests into handler-specific work queues that
handlers poll for work.
-
Each handler is given a name, e.g.
handler_name$ = "cgi://WORD"
.
-
Use
getsymbol$()
to read query parameters directly.
-
findrow()
searches clusters quickly, ignoring case by
default.
-
The example returns simple CSV-style responses
(
success
/error
).
-
Extend easily to JSON, add CORS headers, or support multiple
handlers.
-
Fast-CGI avoids restarting the application on every request. This
eliminates repeated process creation, memory allocation, and variable
reinitialization, as well as database reconnect/disconnect cycles —
all of which are very costly operations.
-
For higher performance, run multiple instances of the same handler
to utilize all CPUs on a multi-processor system, or run different
handlers with unique names to perform separate tasks in parallel.