亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

前后端分離之更好的mock你的后端api

kohoh_ / 3139人閱讀

摘要:注意廣告警告廣告警告廣告警告在一個(gè)應(yīng)用的開發(fā)周期中一般前端與后端都是并行開發(fā)的各自完成自己的開發(fā)工作后進(jìn)行聯(lián)調(diào)聯(lián)調(diào)通過再進(jìn)行提測(cè)發(fā)布開發(fā)過程中前端都會(huì)以后端提供的文檔作為標(biāo)準(zhǔn)模擬返回?cái)?shù)據(jù)以確保在開發(fā)中就保證功能的完整性而關(guān)于如何更好的進(jìn)行業(yè)

注意! 廣告警告! 廣告警告! 廣告警告!

在一個(gè)web應(yīng)用的開發(fā)周期中, 一般前端與后端都是并行開發(fā)的, 各自完成自己的開發(fā)工作后進(jìn)行聯(lián)調(diào), 聯(lián)調(diào)通過再進(jìn)行提測(cè)/發(fā)布.

開發(fā)過程中, 前端都會(huì)以后端提供的 api 文檔作為標(biāo)準(zhǔn), mock 模擬 api 返回?cái)?shù)據(jù), 以確保在開發(fā)中就保證功能的完整性.

而關(guān)于如何更好的進(jìn)行 mock, 業(yè)界/開源社區(qū)可謂有相當(dāng)多質(zhì)量上乘的解決方案, 如easy-mock, yapi等.

但是越是大而全的工具很多時(shí)候功能會(huì)超越需求非常多, 要簡單實(shí)現(xiàn) mock api 的需求其實(shí)也有非常多小而美工具庫可以使用.

而本文主要介紹 mock-server 這個(gè)工具的使用

選用 mock-server 的主要原因除了是我開發(fā)的使用比較簡單之外, 更多的是滿足了下文提到的一些開發(fā)需求, 如果你也有同樣的需求而還沒找到解決方案的話, 不妨試用一下.

安裝 & 基本配置

可選全局安裝, 安裝完成過后, 就可以通過mock命令啟動(dòng)來 mock server

npm install -g mock-server-local

mock -h # 即安裝成功

# 用 -d 指定mock數(shù)據(jù)配置目錄, 為空時(shí)默認(rèn)為當(dāng)前目錄 `.`
mock -d ./mock

# 用 -p 指定server的端口, 默認(rèn)為8888, 如果8888被占用會(huì)端口號(hào)+1, 直至端口可用
# 注意如果指定了端口號(hào), 但是端口號(hào)被占用的話, 會(huì)拋出錯(cuò)誤
mock -d ./mock -p 8080

個(gè)人比較習(xí)慣在項(xiàng)目中進(jìn)行安裝, 并通過npm script啟動(dòng), 而 mock 數(shù)據(jù)也存放在項(xiàng)目當(dāng)中, 通過 git 等版本管理工具在項(xiàng)目成員當(dāng)中共享, 假設(shè)項(xiàng)目目錄為proj

// proj/package.json
{
  // ...
  "script": {
    "mock": "mock -d ./mock -p 8080"
  }
  // ...
}
# 本地安裝
npm install mock-server-local --save-dev

# 啟動(dòng)mock server
npm run mock

> mock@1.8.9 mock /path/to/proj
> mock -d ./mock -p 8080

you can access mock server:
http://127.0.0.1:8080
http://ww.xx.yy.zz:8080

you can access mock server view:
http://127.0.0.1:8080/view
http://ww.xx.yy.zz:8080/view

就這樣 mock server 就已經(jīng)啟動(dòng)了, 訪問127.0.0.1:8080/view即可看到 mock server 的控制頁面

就下來就是調(diào)整代理, 把應(yīng)用的請(qǐng)求轉(zhuǎn)發(fā)到 mock server 進(jìn)行處理

如果你使用webpack來構(gòu)建你的項(xiàng)目, 那你只需要改動(dòng)一下webpack.devServer的配置即可

假設(shè)我們的業(yè)務(wù)域名為target.mock.com, 而接口基本都是target.mock.com/api/**, 可以這樣進(jìn)行配置

devServer: {
  proxy: {
    "/api": {
      target: "http://127.0.0.1:8080", // mock server
      headers: {
        host: "target.mock.com" // 業(yè)務(wù)域名
      },
      onProxyReq: function(proxyReq, req, res) {
        proxyReq.setheader("host", "target.mock.com"); // 業(yè)務(wù)域名
      }
    }
  }
}

接著在開發(fā)中, 啟動(dòng) webpack 之后, 發(fā)出的請(qǐng)求/api/**都會(huì)被轉(zhuǎn)發(fā)到

而如果應(yīng)用本身不使用 webpack 或其他帶 server 功能的打包工具, 可以使用代理工具進(jìn)行請(qǐng)求轉(zhuǎn)發(fā)

如果是用 Chrome 瀏覽器調(diào)試應(yīng)用, 可以下載SwitchyOmega一類可配置, 把特定域名的請(qǐng)求進(jìn)行轉(zhuǎn)發(fā)

使用微信開發(fā)者工具的話, 可直接設(shè)置代理, 設(shè)置 -> 代理設(shè)置 -> 勾選手動(dòng)設(shè)置代理 -> 填寫代理配置

推薦使用 whistle, fiddler 一類功能完整代理工具, 類似配置如下

target.mock.com/api 127.0.0.1:8080 # 接口請(qǐng)求轉(zhuǎn)發(fā)到mock server

target.mock.com www.xx.yy.zz # 頁面從正常的開發(fā)測(cè)試機(jī)ip中獲取, 或本地調(diào)試服務(wù)器
mock 數(shù)據(jù)配置

mock server 的配置是根據(jù) mock 目錄的目錄結(jié)構(gòu)生成的, 假設(shè)需要進(jìn)行 mock 的 api 接口完整的 url 為target.mock.com/api/login

而且需要模擬以下三種情況的數(shù)據(jù)返回

登錄失敗, 返回錯(cuò)誤碼-1 及錯(cuò)誤信息

登錄成功, 返回錯(cuò)誤碼 0 和用戶信息, 且要帶上登錄態(tài) cookie

請(qǐng)求時(shí)間超過 8 秒, 導(dǎo)致前端請(qǐng)求超時(shí)

那么目錄結(jié)構(gòu)與數(shù)據(jù)配置文件應(yīng)該如下所示

|- proj
  |- mock
    |- target.mock.com
      |- api
        |- login
          |- 登錄成功
          |- 登錄失敗
          |- 請(qǐng)求超時(shí)

// 登錄失敗
// proj/mock/target.mock.com/api/login/登錄失敗/data.js
module.exports = {
  code: -1,
  msg: "登錄失敗!"
};

// 登錄成功
// proj/mock/target.mock.com/api/login/登錄成功/data.js
module.exports = {
  code: 0,
  msg: "登錄成功",
  username: "ahui"
};
// proj/mock/target.mock.com/api/login/登錄成功/http.js
module.exports = {
  header: {
    "Set-Cookie": "token=123456789;"
  }
};

// 請(qǐng)求超時(shí)
// proj/mock/target.mock.com/api/login/請(qǐng)求超時(shí)/data.js
module.exports = {};
// proj/mock/target.mock.com/api/login/請(qǐng)求超時(shí)/http.js
module.exports = {
  delay: 8
};

根據(jù)上面目錄配置, 訪問 mock server 頁面的 mock 面板127.0.0.1:8080/view/mocks, 就可以看到以下頁面

現(xiàn)在我們只需要勾選其中一個(gè)狀態(tài), 然后發(fā)出請(qǐng)求即可

mock完成之后就可以愉快編寫業(yè)務(wù)邏輯了

mock 配置詳解

看了上面的例子應(yīng)該也就大致可以了解到, data.js里面定義接口返回的數(shù)據(jù). 而http.js, 顧名思義就是定義 http 請(qǐng)求相關(guān)行為的, 例如可以定義響應(yīng)頭, http 狀態(tài)碼, 請(qǐng)求耗時(shí)等.

data 同時(shí)也支持使用 json 文件, 非 js/json 文件的一律當(dāng) json 格式處理, 而 http 則只支持通過 js 文件定義

http.js可選配置如下

module.exports = {
  delay: 8, // 耗時(shí)8秒
  status: 200 // http狀態(tài)碼
  header: {
    // ... http響應(yīng)頭
  }
}

data.js除了可以簡單定義返回?cái)?shù)據(jù)之外, 還可以直接返回模板, 如

module.exports = `



  
  
  
  Document


  這個(gè)是由mock server返回的模板


`;

并且可以返回一個(gè)方法, 通過腳本邏輯來處理最終要返回的數(shù)據(jù)

// ctx: https://koajs.com/#context
module.exports = function(ctx) {
  // 邏輯處理

  return {
    data: {}, // 響應(yīng)數(shù)據(jù)
    header: {}, // 如有需要可以配置, 同http.js#header
    delay: 0.1, // 如有需要可以配置, 同http.js#delay
    status: 200 // 如有需要可以配置, 同http.js#status
  };
};

// 如果當(dāng)中有異步邏輯, 請(qǐng)返回promise, 或直接使用async方法
module.exports = async function(ctx) {
  // 異步邏輯處理
  await asyncFn();

  return {
    data: {}, // 響應(yīng)數(shù)據(jù)
    header: {}, // 如有需要可以配置, 同http.js#header
    delay: 0.1, // 如有需要可以配置, 同http.js#delay
    status: 200 // 如有需要可以配置, 同http.js#status
  };
};
代理線上數(shù)據(jù)

在開發(fā)過程可能出現(xiàn)這樣的場(chǎng)景, 一期項(xiàng)目已經(jīng)開發(fā)完了, 現(xiàn)在進(jìn)行二期迭代的開發(fā)工作, 這個(gè)時(shí)候由于之前的接口后臺(tái)已經(jīng)都實(shí)現(xiàn), 二期開發(fā)中只想對(duì)新增的 api 進(jìn)行 mock

這個(gè)時(shí)候可以修改一下代理工具的配置, 把不同接口的請(qǐng)求轉(zhuǎn)發(fā)到不同的服務(wù)器

# 新增接口轉(zhuǎn)發(fā)至mock server
target.mock.com/api/new1 127.0.0.1:8080

target.mock.com/api/new2 127.0.0.1:8080

# 其余接口直接使用線上/測(cè)試機(jī)數(shù)據(jù)
target.mock.com ww.xx.yy.zz

又或者可以直接使用 mock server 提供的簡單的代理功能, 只需要在 mock 目錄個(gè)目錄下新建proxy.js文件

|- proj
  |- mock
    |- proxy.js

// proj/mock/proxy.js
module.exports = {
  target.mock.com: "https://ww.xx.yy.zz" // 這里可以指定ip也可以指定域名, 但是需要注意協(xié)議類型是必須要帶上的
}

這樣配置之后, 在代理工具中就可以直接把所有的target.mock.com的請(qǐng)求都直接轉(zhuǎn)發(fā)到 mock server

當(dāng)對(duì)應(yīng)請(qǐng)求的 url 并沒有勾選任何一個(gè)返回狀態(tài), 或根本沒有配置對(duì)應(yīng)的 url 時(shí), mock server 都會(huì)幫助我們把請(qǐng)求轉(zhuǎn)發(fā)到目標(biāo) ip

假設(shè)沒有配置proxy.js的話, 對(duì)于沒有命中的 url 請(qǐng)求, 會(huì)根據(jù) host 直接請(qǐng)求線上的資源或接口

模板接口調(diào)試 & 微信登錄支持

在非前后端分離的架構(gòu)中, 很常會(huì)出現(xiàn)這樣的需求, 應(yīng)用的入口即是后端接口, 后端會(huì)進(jìn)行鑒權(quán), 拼接模板內(nèi)容和數(shù)據(jù), 然后直接返回頁面給到前端進(jìn)行展示.

這樣的場(chǎng)景 mock server 可以很簡單通過data.js中導(dǎo)出方法的方式來處理

const fs = require("fs");

module.exports = async ctx => {
    let html = "";

    let template = fs.readFileSync("path/to/html/template/index.ejs"); // 舉例ejs, 實(shí)際可以處理任何模板引擎

    // 這里處理模板的語法
    // 1. 處理類似include的拼接模板的語法
    // 2. 處理類似<%= =>插入變量/數(shù)據(jù)的語法
    // 3. 等等等等....

    html = processedHtml;

    return {
        data: html,
        header: {
          "Set-Cookie": "SESSIONID=123123123123;"
        };
    };
};

這樣子我們就可以進(jìn)行模板接口的調(diào)試了. 再回到我們的上一個(gè)例子

我們希望可以使用線上已有接口和數(shù)據(jù)狀態(tài)(如開戶數(shù)據(jù))

也希望使用后端的登錄態(tài)(這樣后續(xù)的接口調(diào)用也能通過鑒權(quán)), 但也同時(shí)希望可以調(diào)試本地模板呢?

比較直觀的方式是, 本地修改模板然后把模板改動(dòng)上傳到開發(fā)服務(wù)器, 然后直接請(qǐng)求開發(fā)服務(wù)器進(jìn)行調(diào)試

但是改動(dòng)比較多, 需要頻繁調(diào)試的話, 或許使用 mock server 也是一個(gè)不錯(cuò)的選擇. 更進(jìn)一步, 如果是微信 h5 且后端的登錄鑒權(quán)接入了微信登錄呢?

我們來分析一下如何使用 mock server 滿足這樣的調(diào)試述求, h5 微信登錄基本的流程如下

請(qǐng)求線上/開發(fā)測(cè)試服務(wù)器接口

接口返回 http 狀態(tài)碼 302 并帶上 Location 頭, 跳轉(zhuǎn)到微信 url

請(qǐng)求微信 url 會(huì)返回 301 再回跳我們的業(yè)務(wù)域名

回跳我們的業(yè)務(wù)域名時(shí), 即再次請(qǐng)求服務(wù)器接口, 獲取微信登錄 code 進(jìn)行業(yè)務(wù)登錄

返回登錄態(tài)及 html 頁面

上面的流程中, 其實(shí)需要介入只有最后一步而已, 就是獲取到登錄態(tài)并返回需要調(diào)試的 html 模板內(nèi)容即可

而前面的步驟, 完全可以通過在data.js中實(shí)現(xiàn)簡單的代理完成

// 微信登錄/data.js
const httpProxy = require("http-proxy");
const fs = require("fs");
const path = require("path");

proxy = httpProxy.createServer({
  secure: false
});

async function req({ req, res }) {
  proxy.web(req, res, {
    target: {
      protocol: "https:",
      host: "ww.xx.yy.zz", // 目標(biāo)服務(wù)器
      port: 443,
      pfx: fs.readFileSync(path.resolve(process.cwd(), "cert/cert.p12")), // 如果服務(wù)器是https需要生成證書
      passphrase: "password"
    },
    selfHandleResponse: true
  });

  return new Promise((resolve, reject) => {
    proxy.once("proxyRes", function(proxyRes, req, res) {
      let body = [];
      let size = 0;
      function onData(chunk) {
        body.push(chunk);
        size += chunk.length;
      }

      proxyRes.on("data", onData).once("end", () => {
        proxyRes.off("data", onData);
        body = Buffer.concat(body, size);
        resolve({
          header: proxyRes.headers,
          data: body,
          status: proxyRes.statusCode
        });
      });
    });
  });
}

module.exports = async function(ctx) {
  // 登錄態(tài)
  const res = await req(ctx);
  const header = res.header;
  res.header = Object.keys(header).reduce((c, k) => {
    let nk = k
      .split("-")
      .map(v => v.charAt(0).toUpperCase() + v.slice(1))
      .join("-");
    c[nk] = header[k];
    return c;
  }, {});

  if (res.header["Set-Cookie"]) {
    // 如果有Set-Cookie header, 則要處理返回本地模板
    // 這里處理模板的語法
    // 1. 處理類似include的拼接模板的語法
    // 2. 處理類似<%= =>插入變量/數(shù)據(jù)的語法
    // 3. 等等等等....
    res.data = template;

    // 這里需要注意, 目標(biāo)服務(wù)器可能會(huì)返回gzip過后的數(shù)據(jù)
    // 如果不對(duì)Content-Encoding和Content-Length進(jìn)行處理的話
    // 會(huì)導(dǎo)致響應(yīng)中Content-Length和實(shí)際內(nèi)榮長度不一致而出錯(cuò)
    res.header["Content-Encoding"] = "identity";
    delete res.header["Content-Length"];
  }
  return res;
};

這樣我們就可以對(duì)具體的接口模板進(jìn)行調(diào)試了

寫在最后

重復(fù)造輪子不易, 且造且珍惜

如果大家有mock api的需求的話, 不妨也試用一下 mock-server

如果覺得 mock-server 還不錯(cuò), 或者解決了mock的一些痛點(diǎn), 不妨賞個(gè)star

最后, 用得不爽或發(fā)現(xiàn)bug, 懇請(qǐng)?zhí)醝ssue!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/109613.html

相關(guān)文章

  • 前后分離總結(jié)

    摘要:如何去解決這些問題前后端分離大部分的互聯(lián)網(wǎng)公司都分成了前端團(tuán)隊(duì)和后端團(tuán)隊(duì)。方案一采用架構(gòu)業(yè)界很多公司會(huì)采用,單頁應(yīng)用的架構(gòu),這種架構(gòu)是天然的前后端分離的。方案二淘寶的大前端方案中途島上圖是淘寶基于的前后端分離分層,以及的職責(zé)范圍。 我們遇到了什么問題? 1.前端無法調(diào)試后端未完成的 API:如果后端同學(xué)還沒有完成 API 開發(fā),那么前端同學(xué)就不能對(duì)這個(gè) API 進(jìn)行開發(fā)。之前我們都是在...

    enrecul101 評(píng)論0 收藏0
  • 前后分離模式

    摘要:采用前后端分離模式可以減后臺(tái)負(fù)擔(dān),加快研發(fā)效率,當(dāng)然,前提是前端能做好的話。還是基礎(chǔ)不夠?qū)е碌暮蠖耸欠耧L(fēng)格很多公司采用了前后端分離模式后,后端仍然采用以往的傳統(tǒng)風(fēng)格,這是不合理的,風(fēng)格的應(yīng)該是前后端分離的最佳實(shí)踐。 showImg(https://segmentfault.com/img/bVFC8f?w=690&h=360);早期的web開發(fā)是不分前端后端的?;ヂ?lián)網(wǎng)進(jìn)入Web2.0時(shí)...

    fobnn 評(píng)論0 收藏0
  • 前后分離模式

    摘要:采用前后端分離模式可以減后臺(tái)負(fù)擔(dān),加快研發(fā)效率,當(dāng)然,前提是前端能做好的話。還是基礎(chǔ)不夠?qū)е碌暮蠖耸欠耧L(fēng)格很多公司采用了前后端分離模式后,后端仍然采用以往的傳統(tǒng)風(fēng)格,這是不合理的,風(fēng)格的應(yīng)該是前后端分離的最佳實(shí)踐。 showImg(https://segmentfault.com/img/bVFC8f?w=690&h=360);早期的web開發(fā)是不分前端后端的。互聯(lián)網(wǎng)進(jìn)入Web2.0時(shí)...

    DesGemini 評(píng)論0 收藏0
  • 前后分離模式

    摘要:采用前后端分離模式可以減后臺(tái)負(fù)擔(dān),加快研發(fā)效率,當(dāng)然,前提是前端能做好的話。還是基礎(chǔ)不夠?qū)е碌暮蠖耸欠耧L(fēng)格很多公司采用了前后端分離模式后,后端仍然采用以往的傳統(tǒng)風(fēng)格,這是不合理的,風(fēng)格的應(yīng)該是前后端分離的最佳實(shí)踐。 showImg(https://segmentfault.com/img/bVFC8f?w=690&h=360);早期的web開發(fā)是不分前端后端的?;ヂ?lián)網(wǎng)進(jìn)入Web2.0時(shí)...

    whlong 評(píng)論0 收藏0
  • 淺談前后分離與實(shí)踐(一)

    摘要:前后端的界限是按照瀏覽器和服務(wù)器的劃分。前后端彼此互不關(guān)聯(lián)。關(guān)于作者本文部分圖片段落參考文章實(shí)踐中的前后端分離。淘寶前后端分離實(shí)踐本文源碼詳見服務(wù)端代碼。 一、起源 (故事純屬虛構(gòu),如有雷同,純屬巧合)傳說在很久很久以前,我們有志之士有了個(gè)創(chuàng)業(yè)的想法,于是乎開始了自己的創(chuàng)業(yè)之夢(mèng),但是人手不足啊,于是乎所有角色老子一個(gè)人全包了: Roles: PM, DBA, RD, FED, Des...

    dantezhao 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<