• 源码来源:negroni-gzip

  • gzip能对数据进行压缩,从而使服务端向客户端传输数据的速度加快。以下对源码的分析是基于源码注释加上自己在谷歌上搜索入header和Sec-WebSocket-Key等知识后的理解,由于时间原因没有深入使用过gzip,很可能存在错误请指正~

// 以下的压缩常量来自于compress/gzip 包
const (encodingGzip = "gzip" // 编码方式为gzip// request或response的headerheaderAcceptEncoding  = "Accept-Encoding" // 指定浏览器可以支持的web服务器返回内容压缩编码类型headerContentEncoding = "Content-Encoding" //web服务器支持的返回内容压缩编码类型headerContentLength   = "Content-Length" // 响应体的长度headerContentType     = "Content-Type" // 返回内容的MIME类型headerVary            = "Vary"headerSecWebSocketKey = "Sec-WebSocket-Key"// 压缩级别BestCompression    = gzip.BestCompressionBestSpeed          = gzip.BestSpeedDefaultCompression = gzip.DefaultCompressionNoCompression      = gzip.NoCompression
)// gzipResponseWriter 包含 negroni.ResponseWriter
type gzipResponseWriter struct {w *gzip.Writernegroni.ResponseWriterwroteHeader bool
}// 检查并设置response的header,并把wroteHeader 设为true,
func (grw *gzipResponseWriter) WriteHeader(code int) {headers := grw.ResponseWriter.Header()if headers.Get(headerContentEncoding) == "" {headers.Set(headerContentEncoding, encodingGzip)headers.Add(headerVary, headerAcceptEncoding)} else {grw.w.Reset(ioutil.Discard)grw.w = nil}grw.ResponseWriter.WriteHeader(code)// 设置状态码grw.wroteHeader = true
}// 把byte数据写入 gzip.Writer并设置Content-Type
func (grw *gzipResponseWriter) Write(b []byte) (int, error) {if !grw.wroteHeader {// 判断是否已经设置过了response的headergrw.WriteHeader(http.StatusOK) // 默认返回码200}if grw.w == nil {return grw.ResponseWriter.Write(b)}// 设置Content-Typeif len(grw.Header().Get(headerContentType)) == 0 {grw.Header().Set(headerContentType, http.DetectContentType(b))}return grw.w.Write(b)
}// handler结构体包含ServeHTTP方法,sync.Pool用来缓存对象
type handler struct {pool sync.Pool
}// 根据压缩level来进行,返回一个handler去处理ServeHTTP中的gzip压缩
func Gzip(level int) *handler {h := &handler{}h.pool.New = func() interface{} {gz, err := gzip.NewWriterLevel(ioutil.Discard, level)if err != nil {panic(err)}return gz}return h
}// ServeHTTP以包括http.ResponseWriter
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {// 判断客户端的AcceptEncoding,如果不接受gzip的编码格式则跳过压缩if !strings.Contains(r.Header.Get(headerAcceptEncoding), encodingGzip) {next(w, r)return}// 如果客户端是发送Sec-WebSocket-Key过来也无需压缩 if len(r.Header.Get(headerSecWebSocketKey)) > 0 {next(w, r)return}gz := h.pool.Get().(*gzip.Writer)// 从pool中获取Writerdefer h.pool.Put(gz)// 使用完后放回pool池等待重新被利用gz.Reset(w)// 用ResponseWriter完成Reset// 新建一个包含negroni.ResponseWriter和Write的gzipResponseWriter对象,并把wroteHeader初始化为falsenrw := negroni.NewResponseWriter(w)grw := gzipResponseWriter{gz, nrw, false}// gzipResponseWriter取代原来的中间件去应用下一个handlerFuncnext(&grw, r)// 删除header的ContentLengthgrw.Header().Del(headerContentLength)gz.Close()
}

浅析negroni-gzip 过滤器的源码相关推荐

  1. 【java】浅析JDK中ServiceLoader的源码

    1.概述 转载:浅析JDK中ServiceLoader的源码 上一篇文章:深入探讨 Java 类加载器 2.ServiceLoader的使用 这里先列举一个经典的例子,MySQL的Java驱动就是通过 ...

  2. 关于flask过滤器truncate源码分析

    1.函数下面的注释: 逐句对照: 1.Return a truncated copy of the string.返回一个截断字符串的副本 2.The length is specified with ...

  3. negroni-gzip源码分析

    gibhub地址:针对negroni的gzip 作业内容:支持了gzip的服务器小程序 这是一个为Negroni设计的gzip压缩处理中间件,需要用到已有的compress中的gzip.源码共有一百多 ...

  4. react相关代码库以及框架的源码解析

    持续更新中react相关库源码浅析, react ts3 项目 ???对react相关代码库以及框架的源码进行了一定的分析 ?react16.6 View contents 源码实例分析:可见runl ...

  5. Sa-Token源码简单阅读

    一.权限登录模块包括几个基本子模块: 1.登录. 实现方式大致为:先检验用户名密码是否正确,如正确则在缓存中存入用户信息(一般必须要有用户标识和访问token,或再加一些附加信息如用户的角色权限),再 ...

  6. golang学习之negroni/gizp源码分析

    在 Go 语言里,Negroni 是一个很地道的 Web 中间件,它是一个具备微型.非嵌入式.鼓励使用原生 net/http 库特征的中间件.利用它地Use功能,我们可以很简单地自定义中间件并使用.其 ...

  7. Spring-Web(一) RestTemplate使用与源码浅析

    Spring RestTemplate使用与源码浅析 一.RestTemplate 概述 ​ RestTemplate 是 Spring Web 模块封装的一个基于Rest规范提供HTTP请求服务的工 ...

  8. 【FFmpeg】ffmpeg工具源码分析(三):分配过滤器内存(宏GROW_ARRAY)详解

    0.引言 在ffmpeg.c源码的核心函数transcode() 中,先执行初始化操作transcode_init() : 首先初始化过滤器filtergraphs,在寻找过滤器在哪分配时,发现它使用 ...

  9. ASP.NET页面进行GZIP压缩优化的几款压缩模块的使用简介及应用测试!(附源码)

    在介绍之前,先简单说一说ASP.NET服务端GZIP压缩模块的作用及工作原理,很多人编写网页的时候页面因为使用了大量的JS特效又或者放置很多大型动态广告导致了页面或脚本体积庞大,通常都会使用一些压缩工 ...

最新文章

  1. Linux下php连接sql server 2008
  2. 【控制】《自动控制原理》胡寿松老师-目录
  3. php和mysql一起_PHP和MYSQL数据库合理且有效的结合在一起_MySQL
  4. 加快FineReport报表设计的几个心得体会
  5. java成员修饰词 友好的_Java的类成员访问权限修饰词(以及类访问权限)
  6. PPP协议的配置(以H3C模拟器为例)
  7. 在VMware下创建新的CentOS虚拟机
  8. 14.bash(2) 与 环境变量
  9. 视频直播源代码,视频文件当中的存储方法
  10. 《系统集成项目管理》第四章 项目管理一般知识
  11. CTF-实验吧-安全杂项-社交网络
  12. android怎么监听多点触摸_android 多点触控
  13. 基于Proxy代理服务器的长连接方法
  14. 上门洗车APP --- Android客户端开发 之 网络框架封装介绍(二)
  15. 智慧养老之智慧养老解决方案-新导智能
  16. RS-485 工作逻辑
  17. 云原生与业务可观测性
  18. 女神节快乐 | 用编程语言解密京东云程序媛!
  19. Android R- CarAudioService之registerAudioPolicy动态注册(一)
  20. 如何判断一个多边形的环是逆时针还是顺时针

热门文章

  1. C++ Combo Box控件用法
  2. 方方格子excel工具箱 Excel表格处理必备
  3. python 图片处理模块_(python)图片处理Pillow模块的使用
  4. python pygame 游戏实践: 俄罗斯方块(Tetris Game)第一步
  5. 码流 | 码率 | 比特率 | 帧速率 | 分辨率 | 高清的区别
  6. Google GMS 送测的三种方式
  7. 目标跟踪(1)基于OpenCV实现单目标跟踪
  8. 【小程序】微信小程序重复循环平移动画
  9. 24. bootstrap组件#折叠菜单
  10. Win7系统下插入新的usb设备都提示安装驱动失败的解决方法