前言
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 的系統需求如下:
- GNU/Linux
- Free Pascal
- libmicrohttpd
雖然 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.cgi 或 public/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 網頁程式的內建測試頁。經筆者測試,使用 PUT
或 DELETE
也可存取該頁面,不受傳統 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 網頁程式的測試頁。