位元詩人 [Pascal] 網頁設計教學:Fano Framework 入門

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

前言

Pascal 早期的經典應用是用 Delphi 搭配 VCL (Visual Component Library) 寫 Windows 圖形界面程式。當時這種型態的應用程式是主流。

近年來,一般使用者 (end user) 層級的軟體轉成網頁程式 (web application) 和行動程式 (mobile application)。然而,Delphi 當時沒有加強網頁程式相關的應用,未能及時趕上這波風潮。

不過,如果想用 Pascal 寫網頁程式,仍然有一些方案可選擇。本文介紹了數個用 Pascal 寫網頁程式的方案。並展示 Fano Framework 的使用方式。

Pascal 網頁程式設計方案

CGI

Free Pascal 官方的 fcl-web 模組就是用來撰寫 CGI 或 FastCGI 程式的模組。或者,也可以像我們先前的文章般,不使用 CGI 模組,僅使用 CGI 的概念手刻 CGI 程式。

然而,現在甚少網頁程式設計師會繼續使用 CGI 來撰寫網頁程式。通常只用在小型網頁程式或嵌入式網頁程式中。我們在前文有展示過簡單的 CGI 程式,本文不繼續使用 CGI。

Brook Framework 和 Brook for Free Pascal

Brook 網頁程式有兩個版本,一種是純粹以 Pascal 實作的 Brook for Free Pascal,一種是混合 Pascal 和 C 的 Brook Framework。目前無法確定之後會兩者並行或是以 Brook Framework 為主。根據 Brook Framework 的說明,該框架是微框架 (micro-framework)。

目前 (西元 2020 年三月) Brook 似乎還在建置中,文件相當缺乏,只能透過一些範例及 Brook 的範例及原始碼來學習。所以我們不使用這套框架,或許過一陣子再注意一下 Brook 的發展。

Fano Framework

Fano Framework 比較符合程式設計者對現代化網頁框架的預期,有 MVC 模式、資料庫連接、表單檢查、使用者權限等。而且,Fano Framework 也有官網,用來說明該網頁框架的使用方式。

雖然目前 Fano Framework 只能在 GNU/Linux 上運作,但大部分的網頁程式也是架設在某種 GNU/Linux 發行版上,所以這項限制的影響不若想像地大。

本文會使用 Fano Framework 來展示以 Pascal 建立網頁程式的過程。

Synopse mORMot Framework

mORMot Framework 是一個完整的網頁框架,該框架強調 ORM (Object Relational Mapping)、SOA (Service-Oriented Architecture) 等概念。不限於網頁程式,mORMot 的客戶端也可能是 Delphi 程式或其他的程式。

由於 mORMot Framework 比較複雜,導致該框架的官方文件十分冗長、不易閱讀。所以筆者未選擇該框架。有興趣的讀者可以自行到 mORMot 的官網看看。

Delphi RAD Server

Delphi 在 Enterprise (含) 以上的版本加上網頁程式的功能。從 Delphi 的官網來看,RAD Server 加調 REST API 服務,可連結資料庫等外部服務,可管理使用者權限等,也有製作使用者界面的功能。

由於 Delphi Enterprise 版本是商業軟體,對於第一次學習用 Pascal 寫網頁程式的程式設計者來說,應該不會馬上使用該方案。故我們不介紹該軟體。

Fano Framework 的系統需求

Fano Framework 的系統需求如下:

雖然 Fano Framework 的官方 repo 中可見到一些 Windows 終端機腳本,經筆者實測,目前 Fano Framework 仍然無法在 Windows 上編譯。這可能是日後會加入的支援平台。

此外,Fano Framework 也無法在 macOS 或 FreeBSD 中編譯。目前應該只能在 GNU/Linux 系統下編譯和運行。

雖然 Fano Framework 的官網沒有提到 libmicrohttpd,經筆者實測,發現未安裝該函式庫時會無法編譯 Fano 專案,故我們將其列入相依性。在主流 GNU/Linux 發行版上,都有預編好的 libmicrohttpd 套件,不會太難安裝。

編譯 Fano CLI

Fano CLI 是 Fano Framework 的專案生成器 (scaffolding tool)。透過 Fano CLI,我們可以取得相對一致的專案架構,減少重覆的專案建置任務。

目前 Fano CLI 沒有發佈 GNU/Linux 套件,得自行編譯。以下是編譯 Fano CLI 的步驟:

$ git clone https://github.com/fanoframework/fano-cli.git
$ cd fano-cli
$ ./tools/config.setup.sh
$ ./build.sh

編譯完成後,可在 bin/out 目錄取得 fanocli。將該命令列工具移至 PATH 所在的目錄即可。

建立 Fano 網頁程式專案

Fano CLI 所生成的專案大同小異,主要的差別在其部署 (deployment) 方式。以下是生成 Fano 專案時可選的部署方式:

  • CGI
  • FastCGI
  • SCGI
  • uWSGI
  • 內嵌網頁伺服器 (embedded web server)

前三者皆基於 CGI 界面。而 uWSGI 主要是 Python 社群的網頁程式所用的界面。至於內建伺服器則是現代網頁框架常見的方式。

原本的 CGI 程式每次回應時都要開新的行程,在網站訪問者多時開銷較大,故不建議使用。其他的界面則可依讀者的喜好來選擇。

Fano 專案的內嵌網頁伺服器是 libmicrohttpd,該函式庫是以 C 實作的輕量內嵌網頁伺服器,應該足以直接上線使用,而不僅僅是開發時期伺服器。

根據上述的部署模式,可使用相對應的命令列參數:

  • --project-cgi=:使用 CGI 界面
  • --project-fcgi=:使用 FastCGI 界面
  • --project-fcgid=:使用 FastCGI 界面,生成 Apache 模組
  • --project-scgi=:使用 SCGI 界面
  • --project-uwsgi=:使用 uWSGI 界面
  • --project-mhd=:使用內嵌網頁伺服器

假定專案為 myapp ,使用以下指令來建立基於 FastCGI 的 Fano 專案:

$ fanocli --project-fcgi=myapp

這時候 fanocli 會建立 myapp 目錄,並將建好的專案放入該目錄。

若想用內嵌網頁伺服器,則改用以下指令:

$ fanocli --project-mhd=myapp

管理 Fano 專案時,會假定工作目錄為 Fano 專案的根目錄,故我們將工作目錄移至建好的 Fano 專案的根目錄:

$ cd path/to/myapp

假定我們已經對該專案做好適當的增修,使用專案內附的命令稿來編譯網頁程式:

$ ./build.sh

基本上,每次有更動時,都要重新編譯以產生新的網頁程式。由於 Free Pascal 編譯的速度還算快,而且每次編譯時只會修改異動的部分,故編譯時的等待時間不會太長。

如果仔細觀察 Fano 專案,會發現其實 Fano Framework 把整個函式庫放在 vendor 子目錄中,在編譯時會一併編入網頁程式中。所以我們不需要額外安裝 Fano Framework。

編譯完後,網頁程式為 bin/app.cgipublic/app.cgi ,視專案設定而定。請注意一下編譯的訊息。

如果讀者想先試用一下 Fano Framework,也可以不修改專案的程式碼直接編譯,這時候會在網站的根目錄看到 Fano 網頁程式的內建測試頁。

雖然清除目的檔 (object file) 不是必要的,若讀者為了某些考量想清掉目的檔,可使用以下命令稿:

$ ./tools/clean.sh

部署 Fano 網頁程式

使用新的網頁框架時,最好先練習在內部部署程式。程式能動是最基本的,之後再來求功能完整,更進一步時再求效能良好。

在本節中,我們會使用 Debian 相容系統,將網頁程式部署到 Nginx 上,分別使用 FastCGI 和內嵌網頁伺服器。

使用 FastCGI

/etc/nginx/site-enabled/default 修改如下:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www;

    server_name localhost;

    location / {
        fastcgi_pass 127.0.0.1:20477;
        include fastcgi_params;
    }
}

由於 Nginx 支援 FastCGI 界面,可以直接和我們寫好的網頁程式溝通。若讀者使用 SCGI 或 uWSGI 來部署程式,只要對設定檔略為修改即可。但 Nginx 不支援 CGI 界面,得用先前介紹的 FCGI wrap 來包 CGI 程式。

設置好後,重開 Nginx 伺服器:

$ sudo systemctl restart nginx

移動到 Fano 專案所在的根目錄,並啟動 Fano 網頁程式:

$ cd path/to/myapp
$ ./bin/app.cgi

用瀏覽器或 HTTP 客戶端程式拜訪 http://localhost 即可看到 Fano 網頁程式的內建測試頁。經筆者測試,使用 PUTDELETE 也可存取該頁面,不受傳統 CGI 程式的限制。

使用內建網頁伺服器

當我們使用內建網頁伺服器來部署網頁程式時,Nginx 的角色變成反向代理者 (reverse proxy)。只要網頁框架內建的網頁伺服器的效能不要太差,使用這種方式來部署網頁程式反而更簡單。

/etc/nginx/site-enabled/default 修改如下:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www;

    server_name localhost;

    location / {
        proxy_pass http://127.0.0.1:20477;
    }
}

設置好後,重開 Nginx 伺服器:

$ sudo systemctl restart nginx

移動到 Fano 專案所在的根目錄,並啟動 Fano 網頁程式:

$ cd path/to/myapp
$ ./bin/app.cgi

拜訪 http://localhost 即可看到 Fano 網頁程式的測試頁。

關於作者

身為資訊領域碩士,位元詩人 (ByteBard) 認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

位元詩人喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,位元詩人將所學寫成文章,放在這個網站上和大家分享。