2.2.2goweb內置的 HTTP 處理程序2

http.StripPrefix

http.StripPrefix?是 Go 語言?net/http?包中的一個函數,它的主要作用是創建一個新的 HTTP 處理程序。這個新處理程序會在處理請求之前,從請求的 URL 路徑中移除指定的前綴,然后將處理工作委托給另一個提供的處理程序。

使用示例

package mainimport ("fmt""net/http"
)// 定義一個簡單的處理函數
func simpleHandler(w http.ResponseWriter, r *http.Request) {fmt.Fprintf(w, "Path after stripping prefix: %s", r.URL.Path)
}func main() {// 創建一個處理程序,移除 "/static/" 前綴后將請求交給 simpleHandler 處理http.Handle("/static/", http.StripPrefix("/static/", http.HandlerFunc(simpleHandler)))// 啟動 HTTP 服務器,監聽 8080 端口fmt.Println("Starting server on :8080")http.ListenAndServe(":8080", nil)
}

在這個例子中,如果客戶端請求?/static/css/style.csshttp.StripPrefix?會移除?/static/?前綴,將?/css/style.css?作為路徑傳遞給?simpleHandler?處理。

源碼分析

http.StripPrefix?函數的定義如下:

// StripPrefix returns a handler that serves HTTP requests
// by removing the given prefix from the request URL's Path
// and invoking the handler h. StripPrefix handles a
// request for a path that doesn't begin with prefix by
// replying with an HTTP 404 not found error.
func StripPrefix(prefix string, h Handler) Handler {if prefix == "" {return h}return HandlerFunc(func(w ResponseWriter, r *Request) {if p := strings.TrimPrefix(r.URL.Path, prefix); len(p) < len(r.URL.Path) {r2 := new(Request)*r2 = *rr2.URL = new(url.URL)*r2.URL = *r.URLr2.URL.Path = ph.ServeHTTP(w, r2)} else {http.NotFound(w, r)}})
}
源碼詳細解釋
  1. 參數檢查

    if prefix == "" {return h
    }
    
    ?

    如果傳入的前綴?prefix?為空字符串,那么直接返回原處理程序?h,因為不需要移除任何前綴。

  2. 創建新的處理程序

    return HandlerFunc(func(w ResponseWriter, r *Request) {// ...
    })
    
    ?

    使用?HandlerFunc?類型創建一個新的處理程序。HandlerFunc?是一個函數類型,它實現了?http.Handler?接口的?ServeHTTP?方法。

  3. 移除前綴并處理請求

    if p := strings.TrimPrefix(r.URL.Path, prefix); len(p) < len(r.URL.Path) {r2 := new(Request)*r2 = *rr2.URL = new(url.URL)*r2.URL = *r.URLr2.URL.Path = ph.ServeHTTP(w, r2)
    }
    
    ?
    • 使用?strings.TrimPrefix?函數嘗試從請求的 URL 路徑中移除指定的前綴。
    • 如果移除成功(即移除后的路徑長度小于原路徑長度),則創建一個新的?http.Request?對象?r2,并復制原請求的所有信息。
    • 修改新請求對象?r2?的 URL 路徑為移除前綴后的路徑。
    • 調用原處理程序?h?的?ServeHTTP?方法,將新請求對象?r2?傳遞給它進行處理。
  4. 處理未匹配的請求

    } else {http.NotFound(w, r)
    }
    
    ?

    如果請求的 URL 路徑不包含指定的前綴,那么調用?http.NotFound?函數返回一個 404 錯誤響應。

http.StripPrefix?是一個非常實用的工具,它允許你在處理請求之前對 URL 路徑進行預處理,移除不必要的前綴。這在處理靜態文件服務、API 路由等場景中非常有用。通過分析源碼,我們可以看到它是如何創建新的請求對象、修改路徑并將處理工作委托給原處理程序的,同時也處理了未匹配前綴的情況。

http.TimeoutHandler?

http.TimeoutHandler?是 Go 語言?net/http?包中的一個函數,它用于為 HTTP 請求處理設置超時時間。當一個請求的處理時間超過預設的超時時間時,會返回一個超時響應給客戶端,避免客戶端長時間等待無響應的請求。

使用示例

package mainimport ("fmt""net/http""time"
)// 模擬一個耗時的處理函數
func slowHandler(w http.ResponseWriter, r *http.Request) {time.Sleep(5 * time.Second)fmt.Fprint(w, "Slow handler completed")
}func main() {// 設置超時時間為 2 秒timeoutHandler := http.TimeoutHandler(http.HandlerFunc(slowHandler), 2*time.Second, "Request timed out")// 注冊處理程序http.Handle("/slow", timeoutHandler)// 啟動 HTTP 服務器fmt.Println("Starting server on :8080")if err := http.ListenAndServe(":8080", nil); err != nil {fmt.Println("Error starting server:", err)}
}

在這個示例中,slowHandler?函數模擬了一個耗時 5 秒的處理過程,而?http.TimeoutHandler?設置的超時時間為 2 秒。當客戶端請求?/slow?路徑時,如果處理時間超過 2 秒,客戶端將收到 "Request timed out" 的響應。

源碼分析

// TimeoutHandler returns a Handler that runs h with the given time limit.
//
// The new Handler calls h.ServeHTTP to handle each request, but if a
// call runs for longer than its time limit, the handler responds with
// a 503 Service Unavailable error and the given message in its body.
// (If msg is empty, a suitable default message will be sent.)
// After such a timeout, writes by h to its ResponseWriter will return
// ErrHandlerTimeout.
//
// TimeoutHandler buffers all Handler writes to memory and does not
// support the Hijacker or Flusher interfaces.
func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler {return &timeoutHandler{handler: h,timeout: dt,msg:     msg,}
}

TimeoutHandler?函數接收三個參數:

  • h:一個?http.Handler?類型的處理程序,代表實際要執行的請求處理邏輯。
  • dt:一個?time.Duration?類型的超時時間,指定了處理請求的最大允許時間。
  • msg:一個字符串類型的超時消息,當請求處理超時時,會將該消息作為響應體返回給客戶端。
timeoutHandler?結構體
type timeoutHandler struct {handler Handlertimeout time.Durationmsg     string
}

timeoutHandler?結構體包含三個字段,分別存儲傳入的處理程序、超時時間和超時消息。

ServeHTTP?方法實現
func (th *timeoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {done := make(chan struct{})tw := &timeoutWriter{w:   w,h:   make(http.Header),msg: th.msg,}go func() {th.handler.ServeHTTP(tw, r)close(done)}()select {case <-done:tw.mu.Lock()defer tw.mu.Unlock()copyHeader(w.Header(), tw.h)w.WriteHeader(tw.code)w.Write(tw.wbuf.Bytes())case <-time.After(th.timeout):tw.mu.Lock()defer tw.mu.Unlock()if !tw.wroteHeader {http.Error(w, tw.errorMessage(), http.StatusServiceUnavailable)tw.timedOut = true}}
}

ServeHTTP?方法是?timeoutHandler?結構體實現?http.Handler?接口的方法,其執行流程如下:

  1. 創建通道和包裝響應寫入器

    • 創建一個?done?通道,用于通知請求處理是否完成。
    • 創建一個?timeoutWriter?結構體實例?tw,用于包裝原始的?http.ResponseWriter,并記錄響應信息。
  2. 啟動 goroutine 處理請求

    • 啟動一個新的 goroutine 來執行實際的請求處理邏輯?th.handler.ServeHTTP(tw, r)
    • 當處理完成后,關閉?done?通道。
  3. 使用?select?語句等待結果

    • 如果?done?通道接收到信號,說明請求處理在超時時間內完成。此時,將?tw?中記錄的響應頭、狀態碼和響應體復制到原始的?http.ResponseWriter?中并發送給客戶端。
    • 如果?time.After(th.timeout)?通道接收到信號,說明請求處理超時。此時,檢查是否已經寫入響應頭,如果沒有,則使用?http.Error?函數返回一個 503 狀態碼和超時消息給客戶端,并標記?tw.timedOut?為?true
timeoutWriter?結構體
type timeoutWriter struct {w    http.ResponseWriterh    http.Headerwbuf bytes.Buffercode intwroteHeader booltimedOut    boolmu          sync.Mutexmsg         string
}

timeoutWriter?結構體用于包裝原始的?http.ResponseWriter,并記錄響應頭、狀態碼、響應體等信息。同時,它使用互斥鎖?mu?來保證并發安全。

http.TimeoutHandler?是一個非常實用的工具,它可以幫助我們避免長時間無響應的請求阻塞服務器資源。通過使用 goroutine 和通道,結合?select?語句進行超時控制,實現了對請求處理時間的有效管理。需要注意的是,TimeoutHandler?會將處理程序的所有寫入操作緩沖到內存中,并且不支持?Hijacker?和?Flusher?接口。

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

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

相關文章

【Fifty Project - D20】

今日完成記錄 TimePlan完成情況7&#xff1a;30 - 11&#xff1a;30收拾行李閃現廣州 & 《挪威的森林》√10&#xff1a;00 - 11&#xff1a;00Leetcode√16&#xff1a;00 - 17&#xff1a;00健身√ Leetcode 每日一題 每日一題來到了滑動窗口系列&#xff0c;今天是越…

【圖片識別改名】批量讀取圖片區域文字識別后批量改名,基于Python和騰訊云的實現方案

項目場景 ??辦公文檔管理??&#xff1a;將掃描的發票、合同等文檔按編號、日期自動重命名。例如&#xff0c;識別“編號:2023001 日期:20230403”生成“2023001_20230403.jpg”。??產品圖片整理??&#xff1a;電商產品圖片按產品編號、名稱自動命名。例如&#xff0c;…

生物化學筆記:神經生物學概論04 視覺通路簡介視網膜視網膜神經細胞大小神經節細胞(視錯覺)

視覺通路簡介 神經節細胞的胞體構成一明確的解剖層次&#xff0c;其外鄰神經纖維層&#xff0c;內接內叢狀層&#xff0c;該層在鼻側厚約10&#xff5e;20μm&#xff0c;最厚在黃斑區約60&#xff5e;80μm。 全部細胞數約為120萬個(1000000左右)。 每個細胞有一軸突&#xff…

「Mac暢玩AIGC與多模態08」開發篇04 - 基于 OpenAPI Schema 開發專用 Agent 插件

一、概述 本篇介紹如何在 macOS 環境下,通過編寫 OpenAPI Schema,開發自定義的專用插件,讓智能體可以調用外部 API,擴展功能至任意在線服務。實踐內容基于 Dify 平臺,適配 macOS 開發環境。 二、環境準備 1. 確認本地開發環境 macOS 系統Dify 平臺已完成部署并可訪問本…

【計算機視覺】深度解析MediaPipe:谷歌跨平臺多媒體機器學習框架實戰指南

深度解析MediaPipe&#xff1a;谷歌跨平臺多媒體機器學習框架實戰指南 技術架構與設計哲學核心設計理念系統架構概覽 核心功能與預構建解決方案1. 人臉檢測2. 手勢識別3. 姿勢估計4. 物體檢測與跟蹤 實戰部署指南環境配置基礎環境準備獲取源碼 構建第一個示例&#xff08;手部追…

NVIDIA高級輔助駕駛領域的創新實踐與云計算教育啟示

AI與高級輔助駕駛的時代浪潮 人工智能正在重塑現代交通的面貌&#xff0c;而高級輔助駕駛技術無疑是這場變革中最具顛覆性的力量之一。作為全球AI計算的領軍企業&#xff0c;NVIDIA憑借其全棧式技術生態和創新實踐&#xff0c;為高級輔助駕駛的產業化落地樹立了標桿。從芯片到…

頭歌實訓之存儲過程、函數與觸發器

&#x1f31f; 各位看官好&#xff0c;我是maomi_9526&#xff01; &#x1f30d; 種一棵樹最好是十年前&#xff0c;其次是現在&#xff01; &#x1f680; 今天來學習C語言的相關知識。 &#x1f44d; 如果覺得這篇文章有幫助&#xff0c;歡迎您一鍵三連&#xff0c;分享給更…

醫學圖像處理軟件中幾種MPR

1&#xff1a;設備廠商的MPR 2&#xff1a;后處理的MPR 3&#xff1a;閱片PACS的MPR 4&#xff1a;手術導航 手術規劃的MPR 設備廠商的MPR需求更多是掃描線、需要3DMPR &#xff0c;三條定位線的任意角度旋轉。 后處理的MPR&#xff0c;需求更多的是算法以及UI工具的研發&a…

java 類的實例化過程,其中的相關順序 包括有繼承的子類等復雜情況,靜態成員變量的初始化順序,這其中jvm在干什么

Java類的實例化過程及初始化順序 Java類的實例化過程涉及多個步驟&#xff0c;特別是在存在繼承關系和靜態成員的情況下。下面我將詳細解釋整個過程&#xff0c;包括JVM在其中的角色。 1. 類加載階段&#xff08;JVM的工作&#xff09; 在實例化一個類之前&#xff0c;JVM首…

Sce2DriveX: 用于場景-到-駕駛學習的通用 MLLM 框架——論文閱讀

《Sce2DriveX: A Generalized MLLM Framework for Scene-to-Drive Learning》2025年2月發表&#xff0c;來自中科院軟件所和中科院大學的論文。 端到端自動駕駛直接將原始傳感器輸入映射到低級車輛控制&#xff0c;是Embodied AI的重要組成部分。盡管在將多模態大語言模型&…

【題解-Acwing】870. 約數個數

題目:870. 約數個數 題目描述 給定 n 個正整數 ai,請你輸出這些數的乘積的約數個數,答案對 109+7 取模。 輸入 第一行包含整數 n。 接下來 n 行,每行包含一個整數 ai。 輸出 輸出一個整數,表示所給正整數的乘積的約數個數,答案需對 109+7 取模。 數據范圍 1 ≤ …

創龍全志T536全國產(4核A55 ARM+RISC-V+NPU 17路UART)工業開發板硬件說明書

前 言 本文檔主要介紹TLT536-EVM評估板硬件接口資源以及設計注意事項等內容。 T536MX-CXX/T536MX-CEN2處理器的IO電平標準一般為1.8V、3.3V,上拉電源一般不超過3.3V或1.8V,當外接信號電平與IO電平不匹配時,中間需增加電平轉換芯片或信號隔離芯片。按鍵或接口需考慮ESD設計…

Redis 持久化雙雄:RDB 與 AOF 深度解析

Redis 是一種內存數據庫&#xff0c;為了保證數據在服務器重啟或故障時不丟失&#xff0c;提供了兩種持久化方式&#xff1a;RDB&#xff08;Redis Database&#xff09;和 AOF&#xff08;Append Only File&#xff09;。以下是它們的詳細介紹&#xff1a; 一、RDB 持久化 工…

數據結構|并查集

Hello &#xff01;朋友們&#xff0c;這是我在學習過程中梳理的筆記&#xff0c;以作以后復習回顧&#xff0c;有時略有潦草&#xff0c;一些話是我用自己的話描述的&#xff0c;可能不夠準確&#xff0c;還是感謝大家的閱讀&#xff01; 目錄 一、并查集Quickfind 二、兩種算…

【GPU 微架構技術】Pending Request Table(PRT)技術詳解

PRT&#xff08;Pending Request Table&#xff09;是 GPU 中用于管理 未完成內存請求&#xff08;outstanding memory requests&#xff09;的一種硬件結構&#xff0c;旨在高效處理大規模并行線程的內存訪問需求。與傳統的 MSHR&#xff08;Miss Status Handling Registers&a…

遠程訪問你的家庭NAS服務器:OpenMediaVault內網穿透配置教程

文章目錄 前言1. OMV安裝Cpolar工具2. 配置OMV遠程訪問地址3. 遠程訪問OMV管理界面4. 固定遠程訪問地址 前言 在這個數據爆炸的時代&#xff0c;無論是管理家人的照片和視頻&#xff0c;還是企業老板處理財務報表和技術文檔&#xff0c;高效的數據管理和便捷的文件共享已經變得…

微服務架構下的熔斷與降級:原理、實踐與主流框架深度解析

微服務架構下的熔斷與降級&#xff1a;原理、實踐與主流框架深度解析 在現代分布式系統中&#xff0c;熔斷 (Circuit Breaker) 和 降級 (Degrade) 是保障系統彈性與高可用性的核心機制。本文將系統解析兩者的原理、區別與協同方式&#xff0c;并結合主流框架 (Resilience4j、S…

docker-vllm運行大模型

vllm鏡像下載&#xff0c;國內代理源 vllm/vllm-openai - Docker Image - 毫秒鏡像https://1ms.run/r/vllm/vllm-openai 執行下載docker pull docker.1ms.run/vllm/vllm-openai 查看本地鏡像 查看鏡像 查看鏡像 docker images導出鏡像 docker save -o E:\docker\ollama.tar …

基于tabula對pdf中多個excel進行識別并轉換成word中的優化(四)

對上一節進行優化&#xff1a; 1、識別多個excel 2、將表格中的nan替換成空字符串 一、示例中的pdf內容 二、完整代碼參考&#xff1a; import tabula import numpy as np from docx import Document from docx.oxml.ns import qn from docx.oxml import OxmlElementdef get_t…

【10分鐘讀論文】Power Transmission Line Inspections電力視覺水文

標題Power Transmission Line Inspections: Methods, Challenges, Current Status and Usage of Unmanned Aerial Systems 2024 評分一顆星 論文《Power Transmission Line Inspections: Methods, Challenges, Current Status and Usage of Unmanned Aerial Systems》的核心內…