前言
本文介紹在 Nginx 上搭配 fcgiwrap 執行 CGI 程式的流程,供需要實作 CGI 的讀者參考。
什麼是 CGI?
CGI 是網頁伺服器與外部程式之間的介面規格。只要程式符合 CGI 介面,即可作為網頁程式執行。
若需細節可參考 RFC 3875。
撰寫 CGI 程式的程式語言
CGI 與語言無關,只要程式語言具備以下能力即可:
- 可執行命令列程式
- 有標準輸入/輸出
- 可讀取環境變數
撰寫第一個 CGI 程式
本文使用 Pascal 撰寫 CGI 程式(不使用任何 CGI 模組)。
program main;
const
newline = AnsiChar(#10);
begin
(* Response header *)
(* 200 is default HTTP status code. Hence, this line is optional. *)
write('HTTP/1.1 200 OK' + newline);
(* Content-Type is highly recommended for HTTP client. *)
write('Content-Type: text/plain; charset=utf-8' + newline + newline);
(* Two newlines is mandatory after HTTP response header. *)
(* Response body *)
writeLn('Hello World');
end.
重點是程式需輸出合法的 HTTP response:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Hello World
編譯:
$ fpc -oindex.cgi helloCGI.pas
在開發時期快速執行 CGI 程式
開發時可用 Python 內建 HTTP server 快速測試:
$ mkdir cgi-bin
$ mv index.cgi cgi-bin/
$ python -m http.server --cgi 8080
瀏覽:
http://localhost:8080/cgi-bin/index.cgi
此方式僅適用於開發環境。
使用 Nginx 搭配 FastCGI 協定
Nginx 不直接執行 CGI,而是透過 FastCGI 將請求轉交後端程式。因此需要一個 FastCGI 服務來執行 CGI,本例使用 fcgiwrap。
將 CGI 程式放上系統
安裝:
$ sudo apt install nginx fcgiwrap
部署:
$ sudo mv index.cgi /var/www
$ sudo chown www-data:www-data /var/www/index.cgi
啟動 fcgiwrap:
$ sudo nohup fcgiwrap -c 4 -s unix:/var/run/fcgiwrap.socket </dev/null &>/dev/null &
$ sudo chown www-data:www-data /var/run/fcgiwrap.socket
確認:
$ ps aux | grep fcgi
設定 Nginx
server {
listen 80;
server_name example.com;
root /var/www;
location ~ \.cgi$ {
gzip off;
try_files $uri/index.cgi $uri.cgi $uri/ $uri = 404;
index index.cgi;
include fastcgi_params;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location / {
try_files $uri/index.html $uri.html $uri/ $uri = 404;
}
}
關鍵設定:
fastcgi_pass:將請求交給fcgiwrapinclude fastcgi_params:提供必要環境變數SCRIPT_FILENAME:指定 CGI 檔案路徑(此例中非必要,保留作參考)
重新啟動:
$ sudo systemctl restart nginx
完成後即可透過瀏覽器看到 Hello World。