基於 HTTP 請求攔截,快速解決跨域和代理 Mock

来源:https://www.cnblogs.com/mfwtech/archive/2019/03/01/10456261.html
-Advertisement-
Play Games

近幾年,隨著 Web 開發逐漸成熟,前後端分離的架構設計越來越被眾多開發者認可,使得前端和後端可以專註各自的職能,降低溝通成本,提高開發效率。 在前後端分離的開發模式下,前端和後端工程師得以並行工作。當遇到前端界面展示需要的數據,而後端對應的介面還沒有完成開發的情況時,需要一個數據源來保證前端工作的 ...


近幾年,隨著 Web 開發逐漸成熟,前後端分離的架構設計越來越被眾多開發者認可,使得前端和後端可以專註各自的職能,降低溝通成本,提高開發效率。

在前後端分離的開發模式下,前端和後端工程師得以並行工作。當遇到前端界面展示需要的數據,而後端對應的介面還沒有完成開發的情況時,需要一個數據源來保證前端工作的順利進行。

今天這篇文章,我們會介紹幾種常見的方法和其中存在的問題,並提出如何基於HTTP 請求攔截,快速解決跨域和代理 mock 問題的方案。

常見方法及問題

請求 mock 伺服器

最常規的做法是維護一個提供靜態數據的 mock 伺服器(它提供的數據稱為 mock 數據),前端請求 mock 伺服器獲取數據即可,但這種靜態數據維護不便。

請求 AMP 

更好的做法是有一個根據介面定義來自動生成數據的 mock 伺服器,我們稱為AMP(介面管理平臺,API Manage Platform),前端請求該伺服器獲取數據。

在這種場景下,如果有些介面已經完成開發,前端需要手動修改代碼去設置不同介面的請求地址。當介面數量較多時,這種方法會變得非常低效。因此, AMP 一般也會同時提供代理功能,也就是指前端仍請求 AMP,AMP 會根據介面完成情況來決定返回 mock 數據,還是將請求再次代理到真實的業務伺服器獲取數據後返回。

但是這種方案的問題在於當涉及到需要角色許可權驗證的介面時,登錄輸入用戶信息後在瀏覽器中會緩存 cookie,當訪問與登錄時同功能變數名稱的介面時,瀏覽器會自動攜帶 cookie,由伺服器解析 cookie 並鑒權後獲取對應許可權的介面數據。前端一般是在本地啟動伺服器進行開發,當業務伺服器的介面完成開發,這時再採用請求 AMP 的方法切換介面數據,就會出現跨域的情況。

由於瀏覽器的安全機制決定跨域訪問時無法攜帶 cookie,並且無法通過代碼讀取 cookie,因此通過代碼傳遞 cookie 跨域不可行,而現有的解決方案也不完美:

  • 如果在 AMP 額外增加模擬登陸的功能,會因為所有介面的許可權固定不變,無法適配一個介面對不同角色有不同許可權而返回相應的數據;而且一旦鑒權的介面功能變更、失效等情況發生,都需要重寫修改 AMP 的代理功能,代價較大。

  • 如果利用瀏覽器插件保存登陸信息、提供代理,則需要相容不同瀏覽器,成本太高。

針對上述技術問題,本文提出了一種可跨瀏覽器,併在前端實現的不侵入業務代碼的代理方法。

基於 HTTP 請求攔截

實現前端介面代理

基於 HTTP 請求攔截實現前端介面的方式,從更底層的角度實現了介面開發完成前後的 mock 數據,及業務伺服器真實數據之間的切換,並且解決了現有技術中由 HTTP 請求通過 AMP 代理到業務伺服器產生跨域無法攜帶許可權信息,導致無法按照角色許可權返回請求數據的技術問題。

主要創新點

  1. 在更底層基於 XMLHttpRequest 和 Fetch API 實現攔截代理,不需要考慮主流瀏覽器類型,和 JavaScript 依賴的工具庫;

  2. 在前端實現代理,保留了登陸信息,無需額外處理鑒權問題;

  3. 提供一種可以快速實現且可插拔的使用方式。

總的來說,這個方案提供了一種可快速實現,運行在前端瀏覽器中,且不依賴瀏覽器類型的請求代理方法。

設計思路

Web 前端開發一般使用 JavaScript 語言,瀏覽器環境的 HTTP 請求都是基於 Fetch  API 或 XMLHttpRequest API 來實現的(基於前者的請求記做 xhr,後者記做 fetch),主流的 Javascript 開源工具庫如 Axios、Request 也是這樣。所以,我們的方案就是要通過底層攔截 xhr 或 fetch,根據一定的判斷邏輯來實現前端代理功能。

實現方式

首先,重新封裝瀏覽器環境中原生的 XMLHttpRequest API 和 Fetch API。基本思路是將這兩個原生的 API 保存起來,添加到各自重新封裝的同名 API 中(記作新 API),為新 API 寫入與原生 API 中同名的方法和屬性,在攜帶請求參數的同名方法(比如下文中的 open 和 send)裡加入攔截請求和代理的邏輯 ApiProxy,對外開放一個可配置該攔截邏輯的介面,用於配置針對不同的 HTTP 請求格式所請求數據的攔截和代理邏輯。

圖1:代理與AMP和終端業務的交互流程

ApiProxy 在這個過程中的主要作用和工作流程可以歸納為

  1. 註冊攔截器。接收並攔截 HTTP 請求,解析該請求中的參數,這裡的參數是指能在 AMP 中唯一標識該介面的參數,比如功能變數名稱+請求方法(如 GET、POST 等)+路徑(如 https://service.com/user 中的/user)。

  2. 根據該參數生成發送 AMP 的請求。AMP 實時維護了 mock 伺服器上存儲的介面以及業務伺服器上存儲的真實介面的相關信息,包括介面的定義、功能變數名稱、屬性、開髮狀態等。

  3. AMP 根據請求查詢介面定義數據,如果介面存在且狀態是開發中,則返回根據介面定義生成的 mock 數據,否則返回特定響應標誌,如圖 1 中的「{code:』200302』}」。

  4. Apiproxy 收到 AMP 的響應後判斷是否有特殊標誌,沒有直接返回 mock 數據到原請求,有則表示後端介面開發完成,繼續發送原 HTTP 請求到後端伺服器請求後端伺服器存儲的真實數據,相當於沒有對原請求做任何處理。

和傳統的將 HTTP 請求發送給 AMP 不同的是 ,AMP 根據介面狀態判斷是根據請求直接返回 mock 數據,還是開啟代理將 HTTP 請求再發送給業務伺服器(此時跨域訪問會丟失原始 HTTP 請求中瀏覽器攜帶的 cookie),不直接將 HTTP 請求發送給 AMP,而是對請求正式發出之前進行攔截,並解析其中的參數發送給 AMP,由 AMP 反饋介面狀態,若開發完成則將 HTTP 請求正式發送給業務伺服器。因為沒有修改該請求,只是延遲發送,這樣就保持了原請求與業務伺服器之間的所有鑒權等相關信息,由此解決了跨域訪問無法攜帶 cookie 的問題。

不同請求方式下 ApiProxy 的實現

由於不同請求方式的底層設計不同,我們相應的具體封裝手段也不同。

圖2:代理核心工作原理

XMLHttpRequest

對於 XMLHttpRequest 請求,在其 open 方法中解析請求,訪問 AMP 根據響應結果判斷是否需要繼續發送原請求到後臺伺服器,一個 xhr 只有在其 send 方法被調用時才會真正的發起 HTTP 請求,而在 open 方法中無法獲取到 send 方法傳遞的數據,所以攔截發生在 send 方法中。首先單獨存儲 send 方法中發送請求時的參數,然後直接返回,確保先不調用真正的 XMLHttpRequest 的 send 方法,將單獨存儲的參數生成對 AMP 的請求,執行上述 AMP 中的判斷。

實例

1、定義與原生 XMLHttpRequest API 同名的介面,稱為新的 XHR 介面;

2、重命名原生 XMLHttpRequest API 並添加到新的 XHR 介面;

3、在新的 XHR 介面中定義與原生 XMLHttpRequest API 同名的屬性和方法;

4、在同名的 open 方法中解析 HTTP 請求,得到用來在 AMP 查詢介面狀態的參數(比如功能變數名稱+請求方法+路徑);

5、攔截將要發送的原請求,在同名的 send 方法中暫存原請求要發送的數據,暫停原請求的發送;

6、用 4 中的參數請求 AMP,查詢介面狀態,如果介面不存在或是已完成狀態,則返回特殊標誌,ApiProxy 取出 5 中暫存的數據,傳遞給原請求,並繼續原請求的發送;否則,AMP 返回 mock 數據,ApiProxy 直接將該數據返回給原請求。

Fetch API 

對於 Fetch API 而言,因為它是基於 Promise 實現的,攔截比較容易,只需要在 Fetch API 外層封裝一個 Promise 入口,在其發起 fetch 請求前,先暫停原請求,解析數據請求 AMP,並等待響應,判斷響應是否有特殊響應碼,如果有則繼續原請求,否則跳過原請求,直接返回 mock 數據。

啟動前端代理功能

在前端實際開發中,可以藉助打包工具,比如 webpack,自定義一個可配置的插件,開啟後在開發環境中自動將代理攔截代碼插入到主頁面里,從而啟動前端代理功能。

小結

本文提出的前端代理方法通過將代理職責下沉到前端,減少了 mock 伺服器(或者介面管理平臺)請求真實業務伺服器步驟,同時將角色許可權保持在前端請求中,進一步減少了代理所需要承擔的工作量,從底層攔截 HTTP 請求的方法,繞過了利用瀏覽器插件做代理帶來的瀏覽器相容的問題。最後提供的利用打包工具(如 webpack)封裝這種代理方法,實現快速插拔的前端代理。

本文作者:鄧仲哲,馬蜂窩社區研發團隊前端開發工程師,主要負責社區管理後臺,介面管理平臺開發等工作。

 

關註馬蜂窩技術,找到更多你需要的內容

 

附:參考資料

關於跨域: 

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

關於XMLHTTPRequest: 

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest

關於Fetch:

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 微信小程式的出現極大地降低了個人開發者微創業的門檻,不需要後端技術,不需要伺服器和功能變數名稱這些亂七八糟的前置操作,只需要懂得前端技術,就能發佈一款屬於自己的輕量級應用,簡直是前端開發者的福音吶
  • 一、前言 CSS字體屬性可以定義文本的字體系列、大小、加粗、顏色、風格(如斜體)和變形(如小型大寫字母)。 CSS的字體屬性: 下麵我們開始逐步學習CSS中的字體樣式。 二、字體系列:font-family 在CSS中有兩種不同類型的字體系列名稱:通用字體系列,特定字體系列。其中通用字體系列是多個擁 ...
  • 效果如圖: 代碼如下 曾遇到的問題:element表格單元格合併時,合併列數據不顯示,數據錯位。 原因是,表格的數據還沒渲染完,合併的方法就執行了。解決辦法:this.rowspan() 一定要放到介面調用成功,表格數據賦值完畢之後在執行。 ...
  • 轉眼已是四年,想想自己大學即將結束,不由得讓人感慨啊。這才剛開學幾天,我就聽到有同學在因為補考,選課的事情發愁。學校官方的教務處也可以登錄,但是只限於登錄而已,想要進行其他操作只能呵呵了。即使你的瀏覽器開了相容模式也不一定可以操作。多半隻能讓其他同學幫你選課了。於是我分析了下學校的網站內容,下出了這 ...
  • javascript變數 javascript數據類型 javascript運算符 javascript流程語句 javascript數組 javascript字元串函數 javascript函數基礎 javascript基礎DOM操作 javascript windows對象 javascript ...
  • flex對齊 flex對齊方式與主軸和交叉軸所在的方向有關,而flex-direction是控制方向的。 主軸 justify-content justify-content對齊方式共有5種對齊方式: flex-start :主軸起點邊緣開始,從左向右。 flex-end :主軸終點邊緣開始,從右向 ...
  • $broadcast: $broadcast事件是由父組件發起,所有子組件都會收到此廣播事件,除非事件被手動取消。事件廣播的順序為廣度優先搜索順序,如上圖,如果頁面Page_Index發起一個$broadcast事件,那麼按先後順序依次接收到該事件的組件為:ComA、ComB、ComC、ComD、C ...
  • 主要部分: 花括弧,方括弧,冒號和逗號 花括弧保存對象 方括弧裝載數組 名稱和值用冒號隔開 對象通過逗號隔開 一個好用的json格式校驗網址:https://www.json.cn/ ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...