Go語言實戰 : API服務器 (8) 中間件

為什么需要中間件

我們可能需要對每個請求/返回做一些特定的操作,比如

  • 記錄請求的 log 信息
  • 在返回中插入一個 Header
  • 部分接口進行鑒權
    這些都需要一個統一的入口。這個功能可以通過引入 middleware 中間件來解決。Go 的 net/http 設計的一大特點是特別容易構建中間件。apiserver 所使用的 gin 框架也提供了類似的中間件。

gin里面的中間件

在 gin 中可以設置 3 種類型的 middleware:

  • 全局中間件
router := gin.New()
// 添加自定義的 logger 中間件
router.Use(middleware.Logger(), gin.Recovery())
  • 單個路由中間件
userRouter.GET("/profile/", middleware.Auth(), handler.UserProfile)
userRouter.POST("/update", middleware.Auth(), handler.UpdateUserProfile)
  • 群組中間件
authorized := router.Group("/", MyMiddelware())
// 或者這樣用:
authorized := router.Group("/")
authorized.Use(MyMiddelware())
{authorized.POST("/login", loginEndpoint)
}

在請求和返回的 Header 中插入 X-Request-Id

X-Request-Id 值為 32 位的 UUID,用于唯一標識一次 HTTP 請求

func RequestId() gin.HandlerFunc{return func(c *gin.Context) {requestId := c.Request.Header.Get("X-Request-Id")if requestId==""{v4:= uuid.NewV4()requestId=v4.String()}c.Set("X-Request-Id", requestId)c.Writer.Header().Set("X-Request-Id", requestId)c.Next()}

日志中間件

  1. 獲取請求路徑,并且進行匹配(只對業務邏輯進行日志記錄)
		path := c.Request.URL.Pathreg:= regexp.MustCompile("(/v1/user|/login)")if !reg.MatchString(path) {return}// Skip for the health check requests.if path == "/sd/health" || path == "/sd/ram" || path == "/sd/cpu" || path == "/sd/disk" {return}
  1. 獲取請求中的IP等信息,并且給請求重新賦值(請求讀取完會被置空)
		var  bodys []byteif c.Request.Body!=nil{bodys, _ = ioutil.ReadAll(c.Request.Body)}c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(bodys))method := c.Request.Methodip := c.ClientIP()
  1. 將響應重定向到指定IO流,并且提取里面的信息
		blw := &bodyLogWriter{body:           bytes.NewBufferString(""),ResponseWriter: c.Writer,}c.Writer=blwc.Next()var response handler.Responseif err := json.Unmarshal(blw.body.Bytes(), &response); err != nil {log.Println(err, "response body can not unmarshal to model.Response struct, body: %s", string(blw.body.Bytes()))code = errno.InternalServerError.Codemessage = err.Error()} else {code = response.Codemessage = response.Message}}
       func (w bodyLogWriter) Write(b []byte) (int, error) {w.body.Write(b)return w.ResponseWriter.Write(b)
  1. 將從請求與響應中提取的信息進行輸出
	log.Printf("%-13s | %-12s | %s %s | {code: %d, message: %s}", sub, ip, pad.Right(method, 5, ""), path, code, message)

測試

X-Request-id

可以看到,HTTP 返回的 Header 有 32 位的 UUID:
image.png

日志

每個請求的日志信息分為4個部分

  • 耗時
  • 請求 IP
  • HTTP 方法 HTTP 路徑
  • 返回的 Code 和 Message
    image.png

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/390828.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/390828.shtml
英文地址,請注明出處:http://en.pswp.cn/news/390828.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

缺失值和異常值的識別與處理_識別異常值-第一部分

缺失值和異常值的識別與處理📈Python金融系列 (📈Python for finance series) Warning: There is no magical formula or Holy Grail here, though a new world might open the door for you.警告 : 這里沒有神奇的配方或圣杯,盡管…

SQL Server 常用分頁SQL

今天無聊和朋友討論分頁,發現網上好多都是錯的。網上經常查到的那個Top Not in 或者Max 大部分都不實用,很多都忽略了Order和性能問題。為此上網查了查,順帶把2000和2012版本的也補上了。 先說說網上常見SQL的錯誤或者說局限問題 12345select…

Word中摘要和正文同時分欄后,正文跑到下一頁,怎么辦?或Word分欄后第一頁明明有空位后面的文字卻自動跳到第二頁了,怎么辦?...

問題1:Word中摘要和正文同時分欄后,正文跑到下一頁,怎么辦?或Word分欄后第一頁明明有空位后面的文字卻自動跳到第二頁了,怎么辦? 答:在word2010中,菜單欄中最左側選“文件”->“選…

leetcode 664. 奇怪的打印機(dp)

題目 有臺奇怪的打印機有以下兩個特殊要求: 打印機每次只能打印由 同一個字符 組成的序列。 每次可以在任意起始和結束位置打印新字符,并且會覆蓋掉原來已有的字符。 給你一個字符串 s ,你的任務是計算這個打印機打印它需要的最少打印次數。…

SQL數據類型說明和MySQL語法示例

SQL數據類型 (SQL Data Types) Each column in a database table is required to have a name and a data type. 數據庫表中的每一列都必須具有名稱和數據類型。 An SQL developer must decide what type of data that will be stored inside each column when creating a tab…

PHP7.2 redis

為什么80%的碼農都做不了架構師?>>> PHP7.2 的redis安裝方法: 順便說一下PHP7.2的安裝: wget http://cn2.php.net/distributions/php-7.2.4.tar.gz tar -zxvf php-7.2.4.tar.gz cd php-7.2.4./configure --prefix/usr/local/php…

leetcode 1787. 使所有區間的異或結果為零

題目 給你一個整數數組 nums??? 和一個整數 k????? 。區間 [left, right]&#xff08;left < right&#xff09;的 異或結果 是對下標位于 left 和 right&#xff08;包括 left 和 right &#xff09;之間所有元素進行 XOR 運算的結果&#xff1a;nums[left] XOR n…

【JavaScript】網站源碼防止被人另存為

1、禁示查看源代碼 從"查看"菜單下的"源文件"中同樣可以看到源代碼&#xff0c;下面我們就來解決這個問題&#xff1a; 其實這只要使用一個含有<frame></frame>標記的網頁便可以達到目的。 <frameset> <frame src"你要保密的文件…

梯度 cv2.sobel_TensorFlow 2.0中連續策略梯度的最小工作示例

梯度 cv2.sobelAt the root of all the sophisticated actor-critic algorithms that are designed and applied these days is the vanilla policy gradient algorithm, which essentially is an actor-only algorithm. Nowadays, the actor that learns the decision-making …

共享語義 unix語義_語義UI按鈕

共享語義 unix語義什么是語義UI按鈕&#xff1f; (What are Semantic UI Buttons?) A button indicates a possible user action. Semantic UI provides an easy-to-use syntax that simplifies not only the styling of a button, but also the natural language semantics.按…

垃圾回收算法優缺點對比

image.pngGC之前 說明&#xff1a;該文中的GC算法講解不僅僅局限于某種具體開發語言。 mutator mutator 是 Edsger Dijkstra 、 琢磨出來的詞&#xff0c;有“改變某物”的意思。說到要改變什么&#xff0c;那就是 GC 對象間的引用關系。不過光這么說可能大家還是不能理解&…

標準C程序設計七---77

Linux應用 編程深入 語言編程標準C程序設計七---經典C11程序設計 以下內容為閱讀&#xff1a; 《標準C程序設計》&#xff08;第7版&#xff09; 作者&#xff1a;E. Balagurusamy&#xff08;印&#xff09;&#xff0c; 李周芳譯 清華大學出版社…

leetcode 1190. 反轉每對括號間的子串

題目 給出一個字符串 s&#xff08;僅含有小寫英文字母和括號&#xff09;。 請你按照從括號內到外的順序&#xff0c;逐層反轉每對匹配括號中的字符串&#xff0c;并返回最終的結果。 注意&#xff0c;您的結果中 不應 包含任何括號。 示例 1&#xff1a; 輸入&#xff1a…

yolo人臉檢測數據集_自定義數據集上的Yolo-V5對象檢測

yolo人臉檢測數據集計算機視覺 (Computer Vision) Step by step instructions to train Yolo-v5 & do Inference(from ultralytics) to count the blood cells and localize them.循序漸進的說明來訓練Yolo-v5和進行推理(來自Ultralytics )以對血細胞進行計數并將其定位。 …

oauth2-server-php-docs 授權類型

授權碼 概觀 在Authorization Code交付式時使用的客戶端想要請求訪問受保護資源代表其他用戶&#xff08;即第三方&#xff09;。這是最常與OAuth關聯的授予類型。 詳細了解授權碼 用例 代表第三方來電履行 創建一個實例OAuth2\GrantType\AuthorizationCode并將其添加到您的服務…

flask框架視圖和路由_角度視圖,路由和NgModule的解釋

flask框架視圖和路由Angular vs AngularJS (Angular vs AngularJS) AngularJS (versions 1.x) is a JavaScript-based open source framework. It is cross platform and is used to develop Single Page Web Application (SPWA). AngularJS(版本1.x)是一個基于JavaScript的開源…

NGUI EventDelagate事件委托

using System.Collections; using System.Collections.Generic; using UnityEngine;public class BUttonClick : MonoBehaviour {public UIButton button_01;void Start(){if (button_01 null){Debug.Log("button組件丟失了");}else{//首先將腳本中的ClicktheButton…

leetcode 461. 漢明距離(位運算)

兩個整數之間的漢明距離指的是這兩個數字對應二進制位不同的位置的數目。 給出兩個整數 x 和 y&#xff0c;計算它們之間的漢明距離。 注意&#xff1a; 0 ≤ x, y < 231. 示例:輸入: x 1, y 4輸出: 2解釋: 1 (0 0 0 1) 4 (0 1 0 0)↑ ↑上面的箭頭指出了對應二進…

圖深度學習-第2部分

有關深層學習的FAU講義 (FAU LECTURE NOTES ON DEEP LEARNING) These are the lecture notes for FAU’s YouTube Lecture “Deep Learning”. This is a full transcript of the lecture video & matching slides. We hope, you enjoy this as much as the videos. Of cou…

Linux下 安裝Redis并配置服務

一、簡介 1、 Redis為單進程單線程模式&#xff0c;采用隊列模式將并發訪問變成串行訪問。 2、 Redis不僅僅支持簡單的k/v類型的數據&#xff0c;同時還提供list&#xff0c;set&#xff0c;zset&#xff0c;hash等數據結構的存儲。 3、 Redis支持數據的備份&#xff0c;即mas…