編寫REST API

REST API規範

編寫REST API,實際上就是編寫處理HTTP請求的async函數,不過,REST請求和普通的HTTP請求有幾個特殊的地方:

  1. REST請求仍然是標準的HTTP請求,但是,除了GET請求外,POST、PUT等請求的body是JSON數據格式,請求的Content-Typeapplication/json
  2. REST響應返回的結果是JSON數據格式,因此,響應的Content-Type也是application/json

REST規範定義了資源的通用訪問格式,雖然它不是一個強制要求,但遵守該規範可以讓人易於理解。

例如,商品Product就是一種資源。獲取所有Product的URL如下:

GET /api/products

而獲取某個指定的Product,例如,id爲123的Product,其URL如下:

GET /api/products/123

新建一個Product使用POST請求,JSON數據包含在body中,URL如下:

POST /api/products

更新一個Product使用PUT請求,例如,更新id爲123的Product,其URL如下:

PUT /api/products/123

刪除一個Product使用DELETE請求,例如,刪除id爲123的Product,其URL如下:

DELETE /api/products/123

資源還可以按層次組織。例如,獲取某個Product的所有評論,使用:

GET /api/products/123/reviews

當我們只需要獲取部分數據時,可通過參數限制返回的結果集,例如,返回第2頁評論,每頁10項,按時間排序:

GET /api/products/123/reviews?page=2&size=10&sort=time

koa處理REST

既然我們已經使用koa作爲Web框架處理HTTP請求,因此,我們仍然可以在koa中響應並處理REST請求。

我們先創建一個rest-hello的工程,結構如下:

rest-hello/
|
+- .vscode/
|  |
|  +- launch.json <-- VSCode 配置文件
|
+- controllers/
|  |
|  +- api.js <-- REST API
|
+- app.js <-- 使用koa的js
|
+- controller.js <-- 掃描註冊Controller
|
+- package.json <-- 項目描述文件
|
+- node_modules/ <-- npm安裝的所有依賴包

package.json中,我們需要如下依賴包:

"dependencies": {
    "koa": "2.0.0",
    "koa-bodyparser": "3.2.0",
    "koa-router": "7.0.0"
}

運行npm install安裝依賴包。

app.js中,我們仍然使用標準的koa組件,並自動掃描加載controllers目錄下的所有js文件:

const app = new Koa();

const controller = require('./controller');

// parse request body:
app.use(bodyParser());

// add controller:
app.use(controller());

app.listen(3000);
console.log('app started at port 3000...');

注意到app.use(bodyParser());這個語句,它給koa安裝了一個解析HTTP請求body的處理函數。如果HTTP請求是JSON數據,我們就可以通過ctx.request.body直接訪問解析後的JavaScript對象。

下面我們編寫api.js,添加一個GET請求:

// 存儲Product列表,相當於模擬數據庫:
var products = [{
    name: 'iPhone',
    price: 6999
}, {
    name: 'Kindle',
    price: 999
}];

module.exports = {
    'GET /api/products': async (ctx, next) => {
        // 設置Content-Type:
        ctx.response.type = 'application/json';
        // 設置Response Body:
        ctx.response.body = {
            products: products
        };
    }
}

在koa中,我們只需要給ctx.response.body賦值一個JavaScript對象,koa會自動把該對象序列化爲JSON並輸出到客戶端。

我們在瀏覽器中訪問http://localhost:3000/api/products,可以得到如下輸出:

{"products":[{"name":"iPhone","price":6999},{"name":"Kindle","price":999}]}

緊接着,我們再添加一個創建Product的API:

module.exports = {
    'GET /api/products': async (ctx, next) => {
        ...
    },

    'POST /api/products': async (ctx, next) => {
        var p = {
            name: ctx.request.body.name,
            price: ctx.request.body.price
        };
        products.push(p);
        ctx.response.type = 'application/json';
        ctx.response.body = p;
    }
};

這個POST請求無法在瀏覽器中直接測試。但是我們可以通過curl命令在命令提示符窗口測試這個API。我們輸入如下命令:

curl -H 'Content-Type: application/json' -X POST -d '{"name":"XBox","price":3999}' http://localhost:3000/api/products

得到的返回內容如下:

{"name":"XBox","price":3999}

我們再在瀏覽器中訪問http://localhost:3000/api/products,可以得到更新後的輸出如下:

{"products":[{"name":"iPhone","price":6999},{"name":"Kindle","price":999},{"name":"XBox","price":3999}]}

可見,在koa中處理REST請求是非常簡單的。bodyParser()這個middleware可以解析請求的JSON數據並綁定到ctx.request.body上,輸出JSON時我們先指定ctx.response.type = 'application/json',然後把JavaScript對象賦值給ctx.response.body就完成了REST請求的處理。

參考源碼

rest-hello

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章