CGI(通用網關接口)是一種標準化的協議,定義了?Web服務器?與?外部程序(如腳本或可執行文件)之間的數據交互方式。它允許服務器動態生成網頁內容,而不僅僅是返回靜態文件。
1. CGI 的核心作用
-
動態內容生成:早期的Web服務器只能返回靜態HTML文件,CGI的出現使得服務器可以運行程序生成動態內容(如用戶登錄、數據庫查詢等)。
-
跨語言支持:可以用任何編程語言編寫(如Perl、Python、PHP、C、Bash等),只要程序能讀取環境變量和標準輸入(
stdin
),并輸出到標準輸出(stdout
)。 -
無狀態處理:每次HTTP請求都會啟動一個新的CGI進程,處理完畢后立即退出(現代方案如FastCGI優化了這一點)。
2. CGI 的工作原理
當用戶訪問一個CGI程序時(如?http://example.com/cgi-bin/script.py
),流程如下:
-
客戶端發送HTTP請求(如GET或POST)到Web服務器(如Apache/Nginx)。
-
服務器識別CGI請求(通常放在
/cgi-bin/
目錄或特定擴展名如.cgi
)。 -
服務器啟動CGI程序(如Python腳本),并設置環境變量(如
QUERY_STRING
、REQUEST_METHOD
)。 -
CGI程序執行:
-
讀取環境變量(如
$_SERVER
?in PHP、os.environ
?in Python)。 -
處理輸入數據(GET參數從環境變量讀取,POST數據從
stdin
讀取)。 -
生成動態內容,輸出到
stdout
(必須包含HTTP頭,如Content-Type: text/html
)。
-
-
服務器捕獲輸出,并返回HTTP響應給客戶端。
3. CGI 的關鍵組成部分
(1) 環境變量(由服務器傳遞給CGI程序)
變量名 | 說明 |
---|---|
REQUEST_METHOD | HTTP方法(GET/POST/PUT等) |
QUERY_STRING | URL中? 后的查詢參數(如name=foo&age=20 ) |
CONTENT_TYPE | POST/PUT請求的Body類型(如application/x-www-form-urlencoded ) |
CONTENT_LENGTH | POST數據的字節長度 |
HTTP_USER_AGENT | 客戶端瀏覽器信息(如Mozilla/5.0 ) |
REMOTE_ADDR | 客戶端IP地址 |
SCRIPT_NAME | CGI腳本的路徑(如/cgi-bin/hello.py ) |
(2) 輸入數據
-
GET請求:參數通過
QUERY_STRING
傳遞(如?id=123
)。 -
POST請求:數據通過標準輸入(
stdin
)傳遞,需讀取CONTENT_LENGTH
字節。
(3) 輸出規范
CGI程序必須:
-
先輸出HTTP頭(如
Content-Type: text/html
)。 -
空一行(
\n\n
),之后才是響應內容(HTML/JSON等)。
示例(Python CGI):
#!/usr/bin/env python print("Content-Type: text/html\n\n") # 必須的空行 print("<h1>Hello, CGI!</h1>")
4. CGI 的優缺點
優點
??簡單通用:任何語言都能寫,適合小型動態網頁。
??跨平臺:所有主流Web服務器(Apache/Nginx/IIS)均支持。
??無依賴:不要求特定框架或運行時(如PHP-FPM、uWSGI)。
缺點
??性能差:每次請求都啟動新進程,高并發時資源消耗大。
??無持久化:無法保持數據庫連接等長期狀態。
??安全性風險:需謹慎處理用戶輸入(如Shell注入)。
5. 現代替代方案
由于CGI的性能問題,現在更多使用:
技術 | 說明 |
---|---|
FastCGI | 持久化進程處理多個請求(PHP-FPM基于此)。 |
SCGI | 簡化版FastCGI,性能接近但協議更簡單。 |
WSGI | Python的Web服務器網關接口(如Flask/Django使用)。 |
PHP-FPM | PHP的FastCGI進程管理器,替代mod_php 。 |
嵌入式 | 如Apache的mod_php 、Nginx的uWSGI ,直接與服務器集成。 |
6. 示例:用不同語言實現CGI
(1) Bash CGI
#!/bin/bash echo "Content-Type: text/plain" echo "" echo "Hello from Bash CGI!"
(2) Python CGI
#!/usr/bin/env python import osprint("Content-Type: text/html\n\n") print(f"<p>QUERY_STRING: {os.environ.get('QUERY_STRING')}</p>")
(3) PHP CGI
<?php header("Content-Type: text/html"); echo "<h1>Hello, " . ($_GET['name'] ?? 'Guest') . "!</h1>"; ?>
7. 總結
-
CGI是早期動態網頁的核心技術,定義了Web服務器與外部程序的交互標準。
-
雖然性能較低,但所有Web開發語言都支持CGI模式(包括PHP、Python、Perl等)。
-
現代Web開發已轉向更高效的方案(如FastCGI、WSGI),但理解CGI仍有助于掌握底層HTTP交互機制。
如果你的目標是高性能Web應用,建議使用PHP-FPM或Python WSGI;如果只是簡單腳本,CGI仍然可用。