网站只可以返回预先写死的HTML文件,它就只是静态展示页面,所有访客看到内容完全相同。具备交互能力的网站不一样,提交表单能够保存填写内容,登录账号时后台去数据库校验密码。这种根据请求返回差异化内容的能力,早期依靠CGI实现。
CGI全称Common Gateway Interface,中文名称通用网关接口。名称看着晦涩,本质是一套交互约定。Web服务器本身仅能分发静态文件,无法做计算处理。服务器收到请求,判断请求不是获取静态页面,而是需要执行程序运算,就调用外部程序,CGI就是服务器和外部程序之间的通信标准。服务器依照规范传递请求信息给程序,程序处理完毕按规范回传结果。

这套约定具体执行逻辑如下。服务器将请求各类信息存入环境变量。表单提交内容放在QUERY_STRING或者标准输入流。请求方法GET、POST记录在REQUEST_METHOD。CGI程序运行,读取环境变量和标准输入获取数据,业务处理完成,把输出内容写入标准输出。服务器拿到标准输出内容,拼接HTTP头部,转发给浏览器。整套流程类似流水线,服务器接收访问请求,CGI程序承担计算任务,浏览器接收最终页面。
CGI最大特点就是通用性,不限制开发语言。Perl、C、Python,shell脚本都能编写CGI程序。只要程序支持读取环境变量,向标准输出写入内容,就可以作为CGI程序运行。早期网站留言板、访问计数器这类动态功能,大多是Perl编写的CGI脚本。每次用户访问页面,服务器创建Perl进程,程序执行完毕直接关闭进程。
每一次访问新建进程,资源开销很高。访问量上涨之后,服务器大量资源消耗在进程创建与销毁。之后FastCGI出现,应用程序常驻内存,不用反复新建销毁进程。各类编程语言配套Web框架与接口标准陆续推出,Python的WSGI、Ruby的Rack、Java的Servlet,都是CGI思路的衍生方案:服务器和应用程序约定通信规则,实现动态网页。只是不再依靠环境变量、标准输入这种原始交互方式,改用内存共享或者专门协议通信。
现在很少有人直接编写原生CGI程序,裸写CGI的方式已经过时。但CGI思想没有消失。配置Nginx会见到fastcgi_pass指令,PHP-FPM就是FastCGI的落地实现。编写Python Web应用,WSGI服务端和应用程序之间调用逻辑,延续CGI的设计思路。弄懂CGI,就能理解Web服务器与业务应用分工模式。服务器负责网络连接、静态文件分发、请求转发;应用程序处理业务逻辑、数据库读写、动态页面生成。这套分工从CGI诞生起没有发生改变。
看到CGI不用当成老旧技术。它就是一套接口,用来打通Web服务器和外部程序。缺少这套机制,网站只能存放静态文件,没法运算、存储用户数据。依靠CGI,网站才具备交互能力。