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》的核心内…