2023/12/08

Node.js 製作 RESTful API 服務 (含 Express 套件介紹)

作者:吳祐賓 

 


 

這期要來開始製作第一個 Http 服務程式。首先,先建立一個名為 "HelloHttp" 資料夾。


在資料夾新建專案 - 初始化專案

Node.js 新建專案的方式叫「初始化專案」,使用 Terminal 在前面建立的 HelloHttp 資料夾輸入:

npm init


輸入完成後 npm 會啟動互動式介面詢問我們這個專案的基本資料,原則上可以一直按 ENTER 來輸入預設值,這裡由於我的進入點想和一般網頁區隔,以便於識別服務的入口,所以命名為 "server.js"。完成後會在專案目錄下建立 package.json。



建立並編輯 server.js

接著使用編譯器新增 "server.js",並將底下的程式碼複製到該檔案中並存檔。

// 引入 http 模組
const http = require('http');

// 建立一個 HTTP 伺服器
const server = http.createServer((req, res) => {
  // 處理請求
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello, World!\n');
});

// 監聽 3000 port
const PORT = 3000;
server.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}/`);
});

 

啟動第一支 Http 服務

使用以下指令來啟動服務。啟動服務後再開啟瀏覽器,在網址列輸入:http://localhost:3000,就可以看到如下圖的結果。

node server.js

 


 

建立計算機模組

在專案資料夾建立 "app" 目錄,並建立 "calc.js" 檔案,將底下的程式碼貼上後存檔。

// app/calc.js
function add(a, b) {
    return a + b;
}

module.exports = {
    add,
};

 

增加 sum 路由

修改 http.createServer 內的程式,加入 /sum 路由,並且讀取 request 裡的參數 a 和 參數 b,接著呼叫 add 函式將 a 和 b 加總,加總結果寫入 json 物件並回傳給客戶端。修改的程式碼可能長成下面的模樣。

// 引入 http 模組
const http = require('http');
const url = require('url');

// 引入 calc 模組
const calc = require('./app/calc');

// 建立一個 HTTP 伺服器
const server = http.createServer((req, res) => {
  // 解析 URL
  const parsedUrl = url.parse(req.url, true);

  // 處理路由
  if (parsedUrl.pathname === '/sum' && req.method === 'GET') {
    // 取得 URL 參數
    const { a, b } = parsedUrl.query;

    // 將字串轉為數字
    const numA = parseInt(a, 10);
    const numB = parseInt(b, 10);

    // 使用 calc 模組計算結果
    const result = calc.add(numA, numB);

    // 回傳結果
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ result }));
  } else {
    // 其它路由都回傳 Hello World
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello, World!\n');
  }
});

// 監聽 3000 port
const PORT = 3000;
server.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}/`);
});

程式運行結果

 

 

建立第一個 Http 服務總結

Node.js 透過幾個步驟就可以完成 Http Server 專案,和 Delphi WebBroker 專案相同,能夠在彈指之間建立專案,並且建立了 "/sum" 路由 (在 Delphi 中被稱為 action)。實際建構後你會發現程式碼全集中在 http.createServer 函式中,當專案需求功能越來越多,此函式會越來越難以維護。

下一篇文章會介紹 Express 套件如何來幫助我們完成原來的工作。


使用 Express 套件來升級 Http 服務為 RESTful API 專案

在建立 Node.js HTTP 伺服器的過程中,我們通常會面臨隨著專案成長,程式碼集中在 http.createServer 函式中,難以維護的情況。為了更有效地處理路由和中介軟體 (Middleware),我們可以引入 Express 框架。

Express 是一個快速、靈活且精簡的 Node.js Web 應用程式框架,它提供了一組強大的功能,讓你可以更輕鬆地組織和延伸你的應用程式。以下是如何使用 Express 來改進你的程式碼:

首先,你需要安裝 Express 套件。在 Terminal 中執行以下指令:

npm install express

接著 npm 就會安裝 express 套件,並把它安裝在 node_modules 中。

網路上很著名的 node_modules 迷因圖


此時專案資料夾結構應如下圖所示。




 

接著把 server.js 裡的程式碼以下面的程式碼替代。

const express = require('express');
const app = express();

// 引入 calc 模組
const calc = require('./app/calc');

// 設定 "/sum" 路由
app.get('/sum', (req, res) => {
  // 取得 URL 參數
  const { a, b } = req.query;

  // 將字串轉為數字
  const numA = parseInt(a, 10);
  const numB = parseInt(b, 10);

  // 使用 calc 模組計算結果
  const result = calc.add(numA, numB);

  // 回傳結果
  res.json({ result });
});

// 加上 root 路由

app.get('/', (req, res) => {
    res.end('Hello, World!\n');
});

// 啟動伺服器
const PORT = 3000;
app.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}/`);
});


這段程式碼使用 Express 框架建立一個簡單的 HTTP 伺服器。以下是程式碼的主要部分的解釋:

1. 引入 Express 框架:

這裡引入了 Express 框架並創建一個應用程式實例。

const express = require('express');
const app = express();


2. 引入 calc 模組:

 引入了 calc 模組,該模組包含一個 add 函數,用於執行兩數相加的操作。

 const calc = require('./app/calc');


3. 設定 "/sum" 路由:

這個路由處理函數處理 GET 請求,接收 /sum 路由中的 URL 參數 a 和 b,然後使用 calc 模組的 add 函數計算結果,最後以 JSON 格式回傳結果。

app.get('/sum', (req, res) => {
  // 處理 "/sum" 路由的 GET 請求
  const { a, b } = req.query; // 從 URL 參數中取得 a 和 b

  // 將字串轉為數字
  const numA = parseInt(a, 10);
  const numB = parseInt(b, 10);

  // 使用 calc 模組計算結果
  const result = calc.add(numA, numB);

  // 回傳結果
  res.json({ result });
});


4. 設定 "/" 路由:

這個路由就是還原根路徑的 GET 請求,回傳 Hello World 文字訊息。

app.get('/', (req, res) => {
    res.end('Hello, World!\n');
});


5. 啟動伺服器:

啟動伺服器,使其監聽在本地端口 3000 上,並在伺服器啟動時輸出一條訊息到 Terminal 中。

const PORT = 3000;
app.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}/`);
});



使用 Express 套件來升級 Http 服務為 RESTful API 專案總結

使用 Express 框架的優點在於它提供了一個強大而靈活的 RESTful API 開發環境,我們可以在短時間內完成 Delphi WebBroker 和 DataSnap REST 框架所整合的效果。以下是我個人的總結:

    中介軟體的優勢: Express 提供了一個稱為中介軟體(Middleware)的概念,這是一個處理 HTTP 請求和回應的功能強大機制。這使我們能夠在請求到達路由處理之前或之後,執行額外的操作。例如,身份驗證、日誌記錄和錯誤處理等功能都可以方便地透過中介軟體實現。

    簡化的路由系統: Express 的路由系統相當簡單而直觀,對於建立 RESTful API 和處理複雜的路由配置都提供了極大的方便。這使得整合各種端點和資源變得輕鬆,並且易於擴展。

    簡潔的程式碼風格: Express 的 API 設計簡潔,使得開發者能夠以一種清晰且易讀的方式組織和編寫程式碼。這種風格的程式碼結構使得專案的維護和擴充更加輕鬆。

    豐富的社群技術支援: Express 是一個廣泛應用的框架,除了擁有龐大的社群和豐富的官方文件外,Stack Overflow 更有許多大神和無數追隨者的經驗傳承。這保證了開發者可以輕鬆找到解決問題的方法,並能夠分享最佳實戰之路。

    快速整合的效果: 使用 Express 能夠讓開發者迅速構建出符合需求的後端服務。這種快速整合的效果特別迎合 Delphi WebBroker 和 DataSnap REST 框架轉換的要求,讓原 Delphi 開發者在業務需求變動時更容易應對。

Express 提供了一個優雅的開發環境,對於中介軟體、簡潔的路由系統和整合效果的需求都提供了令人滿意的解決方案。在未來的後端開發中,這種風格的開發方式將有助於保持程式碼的清晰度,提升延伸的可能性,並帶來更高效的開發流程。這種轉變同時也能夠讓開發者更容易維護並有效地應對專案的需求變化。


和你分享。


See also

文首圖片來源:攝影師:Klaus Nielsen: https://www.pexels.com/zh-tw/photo/6287465/

 

 

 

2023/12/07

Visual Studio Code 延伸模組推薦

作者:吳祐賓





Visual Studio Code 是開發 Web 前後端很好用的文字編輯器,搭配上許多好用的延伸模組,可以節省很多輸入程式碼的時間。以下是我目前整理後還在使用的延伸模組:



1. Prettier

Prettier 是一個程式碼格式化工具,支援多種語言,確保你的程式碼風格一致,提升可讀性。


2. Todo Highlight

Todo Highlight 用於在程式碼中突顯顯示 TODO、FIXME 等註解,幫助你快速定位和處理待辦事項。


3. Chinese (Traditional) Language Pack for Visual Studio Code

Chinese (Traditional) Language Pack 將 Visual Studio Code 介面繁體中文化,提供更友善的使用體驗。

4. Auto Close Tag

Auto Close Tag 在輸入 HTML/XML 標籤時自動閉合標籤,提高撰寫效率,減少錯誤。


5. Auto Import

Auto Import 自動導入所需的模組或類別,減少手動引入的繁瑣步驟。

6. Auto Rename Tag

Auto Rename Tag 在修改 HTML/XML 標籤名稱時,自動修改對應的閉合標籤,保持標籤一致性。


7. ErrorLens

ErrorLens 透過直白的方式展示程式碼中的錯誤和警告,提高程式碼品質和可讀性。


8. ES6 String HTML

ES6 String HTML 提供對 ES6 模板字串中 HTML 的高亮和語法支援。


9. ES6 String JSX

ES6 String JSX 類似於 ES6 String HTML,但專注於 JSX 語法的高亮和支援。


10. Path Intellisense

Path Intellisense 自動提示檔案路徑,減少手動輸入和查找檔案的時間。


11. Debugger for Firefox

Debugger for Firefox 用於在 Visual Studio Code 中偵錯 Firefox 瀏覽器中的 JavaScript 程式碼。

12. ESLint

ESLint 整合 ESLint,用於靜態程式碼分析和檢測 JavaScript/TypeScript 程式碼中的潛在問題。

希望這些延伸模組能夠提升你在 Visual Studio Code 中的開發體驗!和你分享。



See also

文首圖片來源:攝影師:Karolina Grabowska: https://www.pexels.com/zh-tw/photo/usb-5882581/

2023/12/06

Node.js 入門

作者:吳祐賓




 

我們的目標是使用 Node.js 建立專屬於自己的 Web 應用程式 (Web Application)。在這第一個 Node.js 教學中,您將了解 Node 是什麼、如何在電腦上安裝它以及如何開始使用它。因此在接下來的教學中我們可以進行實際開發。讓我們開始吧!

Node.js 是什麼

  • Node.js 是開源、跨平台的 JavaScript 執行環境
  • Node.js 的授權方式為 MIT 授權,用於開發伺服器端 (後端) 和網路應用程式 (前端)
  • Node.js 是基於 Chrome V8 JavaScript 引擎來執行 JavaScript 程式碼
  • Node.js 使用事件驅動的非阻塞 I/O 模型,使其輕量且有效率
  • Node.js 使用 libuv 函式庫,這是一個專注於非同步 I/O 的多平台支援函式庫


Node.js 可執行 JavaScript 程式碼,JavaScript 屬於單執行緒程式語言,然而透過 libuv 函式庫讓它具備多執行緒的處理能力。在絕大多數的情況下我們並不會接觸到 libuv 這類底層。

libuv 官方 LOGO




為什麼要使用 Node.js

  • Node.js 讓開發人員能夠在前端和後端都使用 JavaScript。每個開發人員都可以了解專案裡的程式碼,並在必要時進行更改
  • Node.js 開發高吞吐量伺服器端應用程式經過許多大公司驗證使用它不會出太多怪手
  • Node.js 採取 MIT 授權,並可以完美運作在各大平台上,因此它可以幫助您節省基礎設施成本
  • Node.js 在 StackOverflow 上較容易取得各大高手的解決方案


安裝 Node.js

Windows: Node.js 官網下載 LTS (Long-term support 長期支援) 版本安裝即可

Linux (本文使用 Lubuntu 環境) 使用下列指令安裝:

# 安裝 Node.js
sudo apt-get install nodejs
# 安裝 NPM (Node Package Manager,是 Node.js 的套件(package)管理工具)
sudo apt-get install npm


安裝後先確認 Node.js 版本:

# 確認版本
node -v
npm -v






使用 Node.js 建立第一個 Hello World 程式

在建立專案前,我們可以在命令提示字元 (Terminal) 下體驗 JavaScript 開發,就像在 Browser 下測試 JavaScript 一樣。使用以下命令啟動 Node.js:

$ node
Welcome to Node.js v12.22.9.
Type ".help" for more information.
>

在 > 後面輸入 "console.log('Hello World')",就可以看到我們第一支 Hello World 程式執行的結果了!


這裡作為 Node.js 執行程式展示,還不會寫入任何檔案。


建立 index.js

在系統建立一個目錄,並使用任何一款的編輯軟體在該目錄建立 index.js,並把上一步驟的程式碼貼上去,如下圖:


接下來在 Terminal 裡輸入 "node index.js",即可看到執行結果。




接下來呢?

接下來我們會開始建立我們第一支 Web API 應用程式。敬請期待!

 

和你分享。

 

 

See also


2023/12/01

Lazarus ZeosLib 7.2 轉換 Delphi 專案初體驗

作者:吳祐賓



Lazarus 發展到現在也很長的一段時間,雖然進度很慢,但 Lazarus 確實是存活著。作為 Delphi 7 替代品,也許它 -- Lazarus Free Pascal IDE 已經具備足夠的實力。

很奇怪的是,Lazarus 連結 MSSQL (SQL SERVER) 的資料是又少又零碎,和現在持續使用 Lazarus 的朋友請教後得到其連結法是:

  1. 使用 TMSSQLConnection 和 TSQLConnector 可以連結 MSSQL
  2. 必須搭配 TSQLTransaction 才能將異動資料寫回資料庫
  3. 需要有 DBLib 驅動程式 (32bit, 64bit) 才能連結資料庫

dbExpress 佈署到客戶端的即視感又回來了,這熟悉的感覺有點不妙。

記得 KTOP 蕭沖大俠曾經提過與其使用 Delphi 官方資料庫元件,不如直接採用 ZeosLib 這種開源專案會來得高效穩定。有想法,就來實際驗證看看。


什麼是 ZeosLib

ZeosLib 是一組資料庫元件,適用於MySQL、MariaDB、PostgreSQL、Interbase、Firebird、MS SQL Server、SAP Adaptive Server Enterprise 和Adaptive Server Anywhere(以前稱為Sybase)、Oracle 和SQLite for Delphi、FreePascal/Lazarus 和C++ Builder 。
--翻譯自 ZeosLib 官網
ZeosLib 也被稱為 ZeosDBO,現在穩定版本為 zeosdbo-7.2.14 版。ZeosLib 7.3 已改名版本為 8.x 版,8 多了 Transcation 元件,而且支援 OleDB 連線方式 (Windows 平台限定),只是目前仍在內部實驗中,建議使用 7.2.14 版本。元件如下表所示。

 




ZeosLib 連結 MSSQL 方式

首先,TZConnection.Protocol 設為 "ado",接著設定 TZConnection.Database 屬性,但設計模式下不會開啟 ConnectionString Builder Dialog (ZeosLib 8 開始加入),所以必須自己研究 ConnectionString 組合方式,這個網站有詳細的說明。如下圖所示。


其它的操作方式就和 Delphi 7 ADO 元件完全相同,使用 Lazarus 內建的 "Delphi Conversion",並將 ADO Type 指定以 ZeosLib Type 替換,之後就自動完成。

拿個小專案來轉換,使用者也沒感覺到太大的問題。


總結

雖然 Lazarus 的進展緩慢,但它確實存活並發展著。作為 Delphi 7 的替代品,Lazarus 在持續努力中展現出了足夠的實力。

在連結 MSSQL 資料庫方面,我理解到使用 TMSSQLConnection 和 TSQLConnector 可以成功連結 MSSQL,同時需要 TSQLTransaction 來確保異動資料能夠順利寫回資料庫。此外,安裝 32bit 和 64bit 的 DBLib 驅動程式是不可或缺的一步。

相較於 dbExpress 帶來的客戶端即視感,KTOP 蕭沖大俠的建議是采用 ZeosLib,這也讓我感到好奇。ZeosLib,或稱 ZeosDBO,是一組跨平台、跨開發工具的資料庫元件,支援多種資料庫,包括 MySQL、PostgreSQL、MS SQL Server 等。穩定版本 zeosdbo-7.2.14 已經在開發者中廣泛使用,而 ZeosLib 8.x 版本則帶來了更多新特性,例如 Transcation 元件和支援 OleDB 連線方式(僅限於 Windows 平台)。

在實際驗證中,我發現將 TZConnection 的 Protocol 設為 "ado",然後手動設定 TZConnection 的 Database 屬性,可以成功連結 MSSQL。儘管在設計模式下無法使用 ConnectionString Builder Dialog(ZeosLib 8 加入的新功能),但通過研究 ConnectionString 的組合方式,我能夠順利設定連線。

最後,透過 Lazarus 內建的 "Delphi Conversion" 工具,將 ADO 元件轉換為 ZeosLib Type,轉換小專案的過程相對順利,使用者幾乎感受不到太大的問題。

綜合而言,我見證了 Lazarus 的堅持與發展,還深入研究了 ZeosLib 作為一個強大的資料庫元件的表現。這樣的探索與實作,讓我更深刻地了解了 Lazarus 的價值與潛力。

和你分享


See also

 


2023/11/25

Node.js 學習筆記

作者:吳祐賓




Node.js NPM(Node Package Manager Node 套件管理器) 安裝

官方網站下載最新版本:Node.js 官方網站 


NPM 專案目錄初始化

npm init

之後會跳出互動式指令設定專案,可按預設值以 ENTER 鍵下一步到結束即可。


NPM 套件安裝指令

npm install <package name>
npm i <pacakge name>

install 和 i 等效。以安裝 Express 為例,可以執行:

npm install express
npm i express

可以附加 -g 參數將套件全域化,這通常用於指令型套件,如 yarn 套件,這是封裝 npm 指令的套件。


NPM 套件移除指令

npm uninstall <package name>

和 uninstall 等效的指令有:remove, r, un, unlink。以移除 Express 為例,可以執行:

npm uninstall express

npm r express



NPM 套件更新到最新版指令

npm update <package name>@latest

update 和 up 等效。以更新 Express 為例,可以執行:

npm update express@latest



未完,持續更新中


See also

2023/10/06

[CB][Delphi]解決跨國小數點符號不同的程式處理

作者:吳祐賓





多數歐洲國家的數字浮點數,會使用逗號「,」作為小數點基點。

這陣子接獲客戶反應他們開發的軟體遇上 "Invalid floating point operation" 的錯誤

雖然最後並沒有採用程式解法來撫平此問題,只是這解決過程太有趣,一定要和你分享!



2023/06/30

PHP Slim 4 framework 初體驗

作者:吳祐賓


Delphi WebBroker 屬於 Web 微服務的一種,自 D7 到現在的 Delphi 社群版都有此框架,挾帶著性能優異的 TDataSet 物件,將微服務提升到商業應用的等級也是分分鐘鐘的事情。

還記得那很久以前被遺忘的 RadPHP?讓我聯想到 PHP 是不是也有類似的框架,能夠將 WebBroker 的概念也套用在上頭,同時 PHP 也擁有和 ADO 概念近似的 PDO,或許可以將某些 WebBroker 專案轉到 PHP 上也說不定。

截至 2023/06,Slim 已發展到 4 版,看了一下手冊的 Hello World,感覺相當容易,結果手冊和實際設計還是有點落差,既然都為 HelloWorld Debug 過一輪了,就順手把 Slim 4 Hello World 設定過程寫下來和各位分享。

安裝

XAMPP 安裝和設定就不提了,PHP 版本資訊:



第一步:安裝 Composer

部署 Slim 4 Web Application 需要使用 Composer 進行安裝,所以要先安裝 Composer



第二步:建立網站目錄,並使用 Composer 安裝 Slim 4

 建立 Slim Web Application 目錄,如 myapp,並在該目錄路徑下執行指令:

1
composer require slim/slim:"4.*"


第三步:安裝 PSR-7 Implementation and ServerRequest Creator

PSR-7 套件用來處理 ServerRequest,省下我們處理它的時間,PSR-7 套件有四款:

  • Slim PSR-7
  • Nyholm PSR-7 and Nyholm PSR-7 Server
  • Guzzle PSR-7 (Version 1 or 2)
  • Laminas Diactoros

這四款只要挑選一款來安裝即可,這裡我選擇 Slim PSR-7:

1
composer require slim/psr7





Hello World

按照官方手冊的作法建立 public/index.php 檔案,程式碼:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

require __DIR__ . '/../vendor/autoload.php';

$app = AppFactory::create();

$app->get('/', function (Request $request, Response $response, $args) {
    $response->getBody()->write("Hello world!");
    return $response;
});

$app->run();

然後就出錯了:

官方手冊上就到這邊,也不知道為何會錯。詢問 ChatGPT 後,它是這樣解釋的:

這個錯誤信息表明你的Slim應用程序在處理一個HTTP請求時未能找到匹配的路由,因此拋出了一個HttpNotFoundException。這通常意味著URL路徑不匹配你在應用程序中定義的任何路由

stackoverflow 則有高手指出使用「setBasePath」就能夠排除此問題,調整之後程式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

require __DIR__ . '/../vendor/autoload.php';

$app = AppFactory::create();

$app->setBasePath("/myapp/public");

$app->get('/', function (Request $request, Response $response, $args) {
    $response->getBody()->write("Hello, World!");
    return $response;
});

$app->run();


透過 BasePath 和路由設定,這裡要注意不要將 index.php 寫上,如此我們就可以使用 URL:http://127.0.0.1/myapp/public/ 進行連結:



總結

Slim 官方推薦的樣板 (Slim skeleton) 在 Slim 4 下已經無法使用,要使用 Slim 4 還是從官方手冊著手會比較容易。

而且 Slim 4 的起手式已經比 Slim 3 以前還要來得簡單,作為 Web 微服務非常合適。

和你分享。



作者新書在這裡