RFC 3875: The Common Gateway Interface (CGI) Version 1.1

2026-08-24

RFC: RFC 3875

Published: 2004

Authors: D. Robinson, K. Coar

CGI is one of those technologies that quietly shaped the modern web and then got politely shoved into the attic. RFC 3875 is not the invention of CGI — NCSA's HTTPd team, led by Rob McCool, had already sketched it out in 1993. What RFC 3875 does is finally standardize, a full decade later, the de facto contract that thousands of scripts and web servers had already been speaking. It is a rare RFC that documents an accomplished fact rather than proposing a design.

The problem. Early HTTP servers only served static files. To make the web dynamic, someone needed to answer: how does an HTTP server invoke an arbitrary external program, hand it a request, and pipe the program's output back to the client? The answer had to work in any language — Perl, C, shell, Tcl — without linking against the server. CGI's solution is almost aggressively simple: fork a process, put the request in environment variables and stdin, read the response from stdout.

The design decisions. Section 4 defines the meta-variables — the environment variables every CGI script can rely on:

Request bodies arrive on stdin. The script writes back a small header block (at minimum Content-Type or a Status: line or a Location: redirect), a blank line, then the body. The server splices this into a proper HTTP response. No sockets, no HTTP parsing in the script, no library dependency. You could write a working CGI program in six lines of shell.

Why it mattered. CGI is what turned the web from a document delivery system into an application platform. Every guestbook, every form-mail script, every early PHP page, every 1990s search engine ran through this interface. Perl's dominance in the late 90s is inseparable from CGI: it was the language that let a sysadmin bolt dynamic behavior onto Apache in an afternoon.

Why it died — and didn't. The fork-per-request model is brutal under load. Spinning up a Perl interpreter for every hit made CGI a punchline by 2000. The replacements — mod_perl, FastCGI, WSGI, Rack, PSGI, Servlets, PHP's SAPI, and eventually Node and Go serving HTTP directly — all inherited CGI's vocabulary even as they abandoned its process model. Open any WSGI environ dict in Python today and you'll find REQUEST_METHOD, PATH_INFO, HTTP_HOST. Nginx's fastcgi_params file is a direct translation of Section 4. AWS Lambda's API Gateway event, if you squint, is a JSON re-encoding of the same idea.

The quirky history. RFC 3875 is classified as Informational, not a Standard. By 2004 CGI was already legacy, and the IETF wasn't going to bless it as the future. Ken Coar spent years chasing down every ambiguity the original NCSA spec had left — how exactly do you percent-decode PATH_INFO? What happens with NPH (non-parsed-header) scripts? — and produced a document that is essentially archaeological. It's the RFC as historical marker: this is what we all actually did, written down at last so the next generation can understand why their web framework's request object looks the way it does.

Why it matters: CGI's process model is dead, but its request vocabulary — REQUEST_METHOD, PATH_INFO, HTTP_* headers — is the ancestral DNA of every modern web framework's request object.

All newsletters