<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
  1. <dfn id="afajh"></dfn>

        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
            <th id="afajh"><progress id="afajh"></progress></th>
            輕識Logo

            搜索

            下載APP
            目錄

              RESTful API 設(shè)計(jì)最佳實(shí)踐

              JavaScript之禪

              共 8982字,需瀏覽 18分鐘

               ·

              2021-04-15 08:07

              ?點(diǎn)擊上方藍(lán)字關(guān)注我們


              簡介

              RESTful API 是目前最流行的API設(shè)計(jì)規(guī)范,它用于Web數(shù)據(jù)接口的設(shè)計(jì)。它允許包括瀏覽器在內(nèi)的各種客戶端與服務(wù)器進(jìn)行通信。因此正確設(shè)計(jì)我們的RESTful是相當(dāng)重要的!我們的API必須安全、高性能、同時易于使用。

              在本文我們將探討如何設(shè)計(jì)出易于使用并且安全快速的的RESTful API。

              RESTful API 即是基于Rest構(gòu)建的API。那么在開始之前,我們先來看看 REST 是什么?

              REST與技術(shù)無關(guān),它代表的是一種軟件架構(gòu)風(fēng)格,REST它是 Representational State Transfer 的簡稱,中文的含義是:  表現(xiàn)層狀態(tài)轉(zhuǎn)移(轉(zhuǎn)移:通過HTTP動詞實(shí)現(xiàn))。即 URL 定位資源,HTTP動詞操作(GET,POST,PUT,DELETE)描述操作。

              確保接受并響應(yīng) JSON數(shù)據(jù)格式

              RESTful API 應(yīng)該接受 JSON 格式的請求,并返回的響應(yīng)體也應(yīng)該是JSON格式的。JSON 是一種數(shù)據(jù)傳輸標(biāo)準(zhǔn),主流編程語言幾乎都能很好的支持它。同時在瀏覽器中我們的JavaScript也能很輕松方便的操作這些數(shù)據(jù)。所以,以JSON 格式編寫的 RESTful API 具有簡單、易讀、易用的特點(diǎn)。

              為了確保當(dāng)我們的RESTful API 服務(wù)使用 JSON 格式響應(yīng),我們應(yīng)該將其響應(yīng)頭的Content-Type設(shè)置為application/json。

              讓我們來看一個接收 JSON 數(shù)據(jù)并返回 JSON 數(shù)據(jù)的 API 示例。本示例使用Node.js的 Express 框架。我們使用了 body-parser 中間件來解析 JSON 請求體,然后使用 res.json 返回傳入的 JSON 對象。

              const express = require('express');
              const bodyParser = require('body-parser');

              const app = express();

              app.use(bodyParser.json());

              app.post('/', (req, res) => {
                res.json(req.body);
              });

              app.listen(3000, () => console.log('server started'));

              在本示例中 bodyParser.json() 將 JSON 請求體的字符解析為 JavaScript 對象,然后將其分配給該req.body對象。

              在 API 路徑中使用名詞代替動詞

              RESTful API是面向資源的API,HTTP動詞操作(GET,POST,PUT,DELETE)描述操作。

              我們不應(yīng)該在URL路徑中使用動詞。我們應(yīng)該使用要操作的實(shí)體的名詞作為路徑名。因?yàn)槲覀兊腍TTP請求方法本身就是動詞,就能描述要進(jìn)行的操作,如常見的方法包括 GET,POST,PUT和 DELETE,這些請求方法即可完成 CRUD。

              • GET 檢索資源。

              • POST 將新數(shù)據(jù)提交到服務(wù)器。

              • PUT 更新現(xiàn)有數(shù)據(jù)。

              • DELETE 刪除數(shù)據(jù)。

              例如,我們有個文章(/articles/)資源。我們對其進(jìn)行CRUD的RESTful API如下:

              • 使用 GET  /articles/來獲取文章列表
              • 使用 POST /articles/添加新文章
              • 使用 PUT /articles/:id 更新給定ID的文章
              • 使用 DELETE/articles/:id 刪除具有給定ID的文章

              我們通過Express來實(shí)現(xiàn)上面這個增刪改查的例子,如下所示:

              const express = require('express');
              const bodyParser = require('body-parser');

              const app = express();

              app.use(bodyParser.json());

              app.get('/articles', (req, res) => {
                const articles = [];
                // code to retrieve an article...
                res.json(articles);
              });

              app.post('/articles', (req, res) => {
                // code to add a new article...
                res.json(req.body);
              });

              app.put('/articles/:id', (req, res) => {
                const { id } = req.params;
                // code to update an article...
                res.json(req.body);
              });

              app.delete('/articles/:id', (req, res) => {
                const { id } = req.params;
                // code to delete an article...
                res.json({ deleted: id });
              });

              app.listen(3000, () => console.log('server started'));

              在上面的示例代碼中,我們定義了API來操作文章(articles)資源。如我們所見,API URL路徑中使用的都是名詞,作為動詞的請求方法說明了API的操作意圖。

              使用名詞復(fù)數(shù)

              我們應(yīng)該使用復(fù)數(shù)名詞來命名集合。

              通常,我們想要取得的數(shù)據(jù)都是一個集合,而不是單個項(xiàng)目。同時數(shù)據(jù)庫中的表也是具有多個條目的。所以我們的API 也應(yīng)該使用復(fù)數(shù)名詞,這樣更合乎情理。

              嵌套分層的資源對象

              在處理嵌套資源的API時,應(yīng)該將嵌套資源附加到父資源的路徑之后。

              例如一個文章有評論列表,獲取某個文章的評論列表的API則為:

              GET /articles/:articleId/comments

              我們可以使用express來做個示范:

              const express = require('express');
              const bodyParser = require('body-parser');

              const app = express();

              app.use(bodyParser.json());

              app.get('/articles/:articleId/comments', (req, res) => {
                const { articleId } = req.params;
                const comments = [];
                // code to get comments by articleId
                res.json(comments);
              });


              app.listen(3000, () => console.log('server started'));

              使用標(biāo)準(zhǔn)的http狀態(tài)碼

              為了消除 API server 發(fā)生錯誤時用戶的困惑,我們應(yīng)該優(yōu)雅地處理錯誤,并返回指示發(fā)生了具體錯誤的HTTP響應(yīng)代碼以及明確的錯誤信息。這可以很好的為API使用者提供了足夠的信息來了解所發(fā)生的問題。

              常見的錯誤HTTP狀態(tài)代碼包括:

              • 400 錯誤的請求 – 這意味著客戶端輸入驗(yàn)證失敗。
              • 401 未經(jīng)授權(quán) - 這意味著用戶無權(quán)訪問資源。通常在用戶未通過身份驗(yàn)證時返回。
              • 403 禁止訪問 - 表示用戶已通過身份驗(yàn)證,但不允許其訪問資源。
              • 404 Not Found – 表示找不到資源。
              • 500 內(nèi)部服務(wù)器錯誤 – 這是一般服務(wù)器錯誤。它可能不應(yīng)該明確地拋出。
              • 502 錯誤的網(wǎng)關(guān) - 這表明來自上游服務(wù)器的無效響應(yīng)。
              • 503 服務(wù)不可用 – 這表示服務(wù)器端發(fā)生了意外情況(可能是服務(wù)器過載,系統(tǒng)某些部分發(fā)生故障等)。

              我們應(yīng)該拋出服務(wù)錯誤相對應(yīng)的錯誤碼。例如,如果我們要拒絕客服端發(fā)起的請求,則應(yīng)在Express API中返回如下所示的 400 響應(yīng):

              const express = require('express');
              const bodyParser = require('body-parser');

              const app = express();

              // existing users
              const users = [
                { email: '[email protected]' }
              ]

              app.use(bodyParser.json());

              app.post('/users', (req, res) => {
                const { email } = req.body;
                const userExists = users.find(u => u.email === email);
                if (userExists) {
                  return res.status(400).json({ error: 'User already exists' })
                }
                res.json(req.body);
              });


              app.listen(3000, () => console.log('server started'));

              在上面的示例中,用戶嘗試創(chuàng)建一個已經(jīng)存在的user,將獲得 400 響應(yīng)狀態(tài)代碼,并帶有一條'User already exists'的錯誤消息,讓用戶知道該用戶已經(jīng)存在。利用這些信息,用戶可以通過使用其他 email 來創(chuàng)建新用戶。

              通常錯誤代碼需要附帶明確錯誤消息,以便用戶有足夠的信息來了解自己遇到了什么問題。

              每當(dāng)我們的API未成功調(diào)用時,都應(yīng)通過發(fā)送明確的錯誤信息來幫助用戶采取糾正措施來完成操作。

              添加過濾,排序和分頁功能

              通常我們的數(shù)據(jù)都會非常龐大。我們不可能一次全部返回,這會非常慢也可能導(dǎo)致系統(tǒng)崩潰。因此,我們需要有過濾,分頁數(shù)據(jù)的方式。過濾和分頁都可以通過減少消耗服務(wù)器資源來提高性能。這些功能相當(dāng)基礎(chǔ)且重要。

              分頁、過濾、排序查詢都功能都應(yīng)該使用查詢參數(shù)來實(shí)現(xiàn)。如:

              /employees?page=1&pageSize=10&firstName=Xing

              下面這就是一個帶有過濾查詢的示例:

              const express = require('express');
              const bodyParser = require('body-parser');

              const app = express();

              // employees data in a database
              const employees = [
                { firstName: 'Jane', lastName: 'Smith', age: 20 },
                //...
                { firstName: 'John', lastName: 'Smith', age: 30 },
                { firstName: 'Mary', lastName: 'Green', age: 50 },
              ]

              app.use(bodyParser.json());

              app.get('/employees', (req, res) => {
                const { firstName, lastName, age } = req.query;
                let results = [...employees];
                if (firstName) {
                  results = results.filter(r => r.firstName === firstName);
                }

                if (lastName) {
                  results = results.filter(r => r.lastName === lastName);
                }

                if (age) {
                  results = results.filter(r => +r.age === +age);
                }
                res.json(results);
              });

              app.listen(3000, () => console.log('server started'));

              保持良好的安全意識

              客戶端和服務(wù)器之間的大多數(shù)通信應(yīng)該是私有的。因此,必須使用SSL/TLS進(jìn)行安全保護(hù)。現(xiàn)在加載SSL成本是相當(dāng)?shù)偷摹N覀儧]有理由不使用它。

              同時,不同的用戶具有不同的數(shù)據(jù)訪問權(quán)限。例如,普通用戶不應(yīng)該能夠訪問其他用戶的信息。他們也不應(yīng)該能夠訪問管理員的數(shù)據(jù)。

              適當(dāng)緩存數(shù)據(jù)以提高性能

              可以適當(dāng)添加緩存服務(wù),從緩存中返回常用數(shù)據(jù),而不是每次都從數(shù)據(jù)庫去讀取。緩存的好處是可以更快地獲取數(shù)據(jù),但是也讓我們獲取最新的數(shù)據(jù)變得復(fù)雜。緩存方式有很多如:Redis、內(nèi)存緩存( in-memory cache)等等,我們應(yīng)該根據(jù)自己的應(yīng)用具體情況來選擇是不是該用緩存,使用哪種緩存機(jī)制。

              這兒我們來使用Express的apicache中間件來實(shí)現(xiàn)一個簡單的內(nèi)存緩存:

              const express = require('express');
              const bodyParser = require('body-parser');
              const apicache = require('apicache');
              const app = express();
              let cache = apicache.middleware;
              app.use(cache('5 minutes'));

              // employees data in a database
              const employees = [
                { firstName: 'Jane', lastName: 'Smith', age: 20 },
                //...
                { firstName: 'John', lastName: 'Smith', age: 30 },
                { firstName: 'Mary', lastName: 'Green', age: 50 },
              ]

              app.use(bodyParser.json());

              app.get('/employees', (req, res) => {
                res.json(employees);
              });

              app.listen(3000, () => console.log('server started'));

              版本化我們的API

              原則上我們應(yīng)該盡量讓API避免破壞性變更,保持向后兼容。但是經(jīng)常有些時候破壞性的變更是不可避免的,這時版本化的API就派上用場了。當(dāng)我們發(fā)布了不兼容或重大更改變,則可以將其發(fā)布在新版本中的API。

              我們通常通過URL來實(shí)現(xiàn)版本化,及添加版本號在我們API路徑的開頭,例如:api.liuxing.io/v1 api.liuxing.io/v2

              我們可以在 express 很簡單的實(shí)現(xiàn)版本化的RESTful API:

              const express = require('express');
              const bodyParser = require('body-parser');
              const app = express();

              app.use(bodyParser.json());

              app.get('/v1/employees', (req, res) => {
                const employees = [];
                // code to get employees
                res.json(employees);
              });

              app.get('/v2/employees', (req, res) => {
                const employees = [];
                // different code to get employees
                res.json(employees);
              });

              app.listen(3000, () => console.log('server started'));

              總結(jié)

              設(shè)計(jì)高質(zhì)量RESTful API的最重要的一點(diǎn)是遵循Web標(biāo)準(zhǔn)和約定以保持一致性。JSON、SSL/TLS和HTTP狀態(tài)代碼都是現(xiàn)代Web的標(biāo)準(zhǔn)。性能也是重要的考慮因素。我們可以使用分頁、緩存等手段來提升性能。可維護(hù)性可擴(kuò)展性也是我們需要考慮的。


              往期精彩回顧:


              Git 工作流程及分支策略

              聊聊JavaScript單元測試

              開發(fā)并發(fā)布一個健壯的npm包

              這些JavaScript方法將在短短幾分鐘內(nèi)提升你的技能

              如何循序漸進(jìn)地學(xué)習(xí)JavaScript?





              左手代碼右手磚,拋磚引玉

              給點(diǎn)個贊,好不好啊


              瀏覽 63
              點(diǎn)贊
              評論
              收藏
              分享

              手機(jī)掃一掃分享

              分享
              舉報(bào)
              評論
              圖片
              表情
              視頻
              全部評論
              推薦
              RESTful API 設(shè)計(jì)最佳實(shí)踐
              JAVA樂園
              0
              Restful API 設(shè)計(jì)最佳實(shí)踐
              JAVA樂園
              0
              一文詳解 API 設(shè)計(jì)最佳實(shí)踐
              Java資料站
              0
              一文詳解 API 設(shè)計(jì)最佳實(shí)踐
              肉眼品世界
              0
              一文詳解 API 設(shè)計(jì)最佳實(shí)踐
              公眾號程序猿DD
              0
              一文詳解 API 設(shè)計(jì)最佳實(shí)踐
              架構(gòu)之美
              0
              一文詳解 API 設(shè)計(jì)最佳實(shí)踐
              IT牧場
              0
              系統(tǒng)設(shè)計(jì):API 接口的最佳實(shí)踐
              泥瓦匠BYSocket
              0
              設(shè)計(jì) API 的 22 條最佳實(shí)踐,實(shí)用!
              程序員內(nèi)點(diǎn)事
              0
              RESTful架構(gòu)和RESTful API設(shè)計(jì)總結(jié)
              開發(fā)者全社區(qū)
              0
              點(diǎn)贊
              評論
              收藏
              分享

              手機(jī)掃一掃分享

              分享
              舉報(bào)
              2023?輕識隱私協(xié)議用戶協(xié)議關(guān)于我們機(jī)器人浙ICP備19021730號-8浙公網(wǎng)安備 33011002017279號
              <kbd id="afajh"><form id="afajh"></form></kbd>
              <strong id="afajh"><dl id="afajh"></dl></strong>
                <del id="afajh"><form id="afajh"></form></del>
              1. <dfn id="afajh"></dfn>

                    1. <th id="afajh"><progress id="afajh"></progress></th>
                      <b id="afajh"><abbr id="afajh"></abbr></b>
                        <th id="afajh"><progress id="afajh"></progress></th>
                        韩日无码电影 | 亚洲成人欧美成人 | 日本成人A电影院 | 波多野结衣网站视频 | 亚洲一区中文字幕在线观看 |