位元詩人 [Web] 程式設計教學:用 Nginx 搭配 fcgiwrap 執行 CGI 程式

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

前言

本文介紹在 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:將請求交給 fcgiwrap
  • include fastcgi_params:提供必要環境變數
  • SCRIPT_FILENAME:指定 CGI 檔案路徑(此例中非必要,保留作參考)

重新啟動:

$ sudo systemctl restart nginx

完成後即可透過瀏覽器看到 Hello World

另見

關於作者

位元詩人 (ByteBard) 是資訊領域碩士,喜歡用開源技術來解決各式各樣的問題。這類技術跨平台、重用性高、技術生命長。

除了開源技術以外,位元詩人喜歡日本料理和黑咖啡,會一些日文,有時會自助旅行。