Node.js: Node.js + express - Server & Routing
之前有一篇用Node.js原生語法建立伺服器的文章提過說,一般都會使用express這個模組去建立伺服器,因為用express建立伺服器更簡單、更便利😂
這篇就是記錄如何用express設定伺服器、靜態文件和路由(routing)。
Server
從以下範例可以看出用express設定伺服器確實比使用Node.js原生語法設定伺服器來的簡單許多,但是express的伺服器回應(response)每次都只能 send
或 sendFile
一次。
const path = require('path');
const express = require('express');
const app = express();
/* Request handling */
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, index.html));
// res.send(<h3>Welcome</h3>); // 錯誤
});
app.get('/about', (req, res) => {
res.send('About page');
});
// ... other routing
// 讓伺服器監聽port 3000的請求
app.listen(3000, () => {
console.log('Server is running on the port 3000');
});
Static files
靜態文件(static files)是任何非伺服器端產生、需要提供給網站的資源,譬如像是CSS、圖片檔等,都可稱作是靜態文件。
在express中,靜態文件的處理是要透過middleware機制去設定放置靜態文件的資料夾,假設放置靜態文件的資料夾名為"public",我們要在路由(routing)之前設定middleware:
// middleware
app.use(express.static('public'));
app.use()
表示要使用middle ware;而 express.static()
括號內則表示要放置靜態文件的資料夾。
Routing & Status Code
當使用者透過連結或者自行輸入網址會導向至相對應的頁面,而路由就是用來達成這樣的事情,這一小節分為三種類型的路由:
- Routing for patterns
- Routing for query
- Routing for all
Routing for patterns
第一個要來處理動態路由,可以透過 req.params
取得參數物件,而範例以解構(destructuring)的方式去取得參數product:
// Routing for patterns
app.get('/products/:product', (req, res) => {
const { product } = req.params;
res.send(`The entered product is ${product}.`);
});
Routing for query
第二種路由類型則是要處理表單送出的路由,假設已經在首頁設定好一個表單,表單的action可以設定送出請求後的路由:
<form action="/formHandling" method="GET">
...
</form>
以下範例考慮表單的method可設定為GET或POST兩種請求:
method = "GET"
GET請求比較容易,只需要將路由設定成 app.get('/* 表單送出路由 */', ...);
app.get('/formHandling', (req, res) => {
const { fullname, age } = req.query; // 取得表單欄位值
res.send(`Hi, ${fullname}. Your age is ${age}.`)
});
method = "POST"
在express裡面,表單的POST請求則是要多設定一個middleware:
const bodyParser = require('body-parser');
// middleware
app.use(bodyParser.urlencoded({ extended: true }));
// Handle POST request
app.post('/formHandling', (req, res) => {
const { fullname, age } = req.body;
res.send(`Hi, ${fullname}. Thanks for posting.`);
});
Routing for all
最後一個要處理的是任一路由,也就是假設使用者輸入沒有特別設定(或者亂打一通)的網址列,可以使用 *
顯示常見的 "404" 畫面:
// Routing for all
app.get('*', (req, res) => {
res.status(404) // 設定 404 狀態碼
.send(<h1> 404 NOT FOUND </h1>);
});
設定這種路由要注意的是,只能放在其他路由的最下面,否則不管輸入什麼網址都會直接轉向至這個路由。
HTTP Requests
常用的HTTP Requests有以下幾種:
- GET: Read
- POST: Create
- PUT: Replace/ Update ALL
- PATCH: Replace/ Update Partial Data
- DELETE
在此之前都只用到 GET
和 POST
requests,後端的server可以處理以上提到的五種需求,但是如果前端HTML頁面建立了一個表格提供修改資料,不過HTML Form的method卻只有GET和POST,這種時候可以借助第三方套件來處理其他類型的requests。
這篇文章以method-override
示範,根據文件express要新增以下資訊:
const methodOcerride = require("method-override");
// override with POST having ?_method=PUT
app.use(methodOverride("_method"));
然後HTML的form method可以設定成POST,但是action後面要新增參數:
<form action="/update/:id?_method=PUT" method="POST">
...
</form>
References Using middleware @express Serving static files in Express @express 2022網頁開發全攻略(HTML, CSS, JavaScript, React, SQL, Node, more)