最近接到一个需求,需要返回请求内容的md5,为此专门调研了下实现内容md5值的方法

        1、使用专门的第三方模块

        2、使用支持lua的nginx实现

    第一种方法需要重新编译nginx,因为这么这个第三方模块平时很少用。第二种方法github上找的解决方案使用ngx.location.capture方法但没有写具体的实现过程。第一种方案想都不用想拉,那么只剩下第二种方案,最近正在学习lua正好练练手,那么是不是只用 body_filter_by_lua_file就可以实现了!!!!!结果不行,具体看下面这张图因为返回内容是分块传输的,并且header头内容当时已经发送给客户端。所以看来是需要ngx.location.capture方法,毕竟这个方法在返回给客户端信息的时候可以接收到完整响应体。

    实现思路:新建一个location,将原有请求转发到新的location(新location需要截取掉url,具体为什么见具体实现方法),在原有location中请求返回的时候算出响应体的md5值,并且增加到header中

    Lua Nginx Modules Directives

现在演示下具体实现方法:

    1、部署测试环境

        新起一个http server,并且将其加到配置文件中

        #nohup python -m SimpleHTTPServer 127.0.0.1:8008 &

        在配置文件中新增一个loction,并验证测试

        location /images {

            proxy_pass http://127.0.0.1:8008;    

        }

       测试URL:curl -svo /dev/null "https://www.centosdoc.com/image/20181216/1544934870690012.png" 访问正常

    2、新增location,并在原location中设置转发,增加header头

        新增location

         location /testimage/ {

            proxy_pass http://127.0.0.1:8008/;

        }

        原location中设置转发到新location中

        location /image {

                content_by_lua_block {

                        local res = ngx.location.capture("/testimage")

                        local headers = ngx.header

                        local log = ngx.log

                        local ERR = ngx.ERR

                        if res then

                                local contentmd5 = ngx.md5(res.body)

                                log(ERR, contentmd5)

                                #headers["Content-hash"] = contentmd5

                                ngx.ctx.md5 = contentmd5

                        end

                }

                header_filter_by_lua_block {

                        local headers = ngx.header

                        headers["Content-hash"] = ngx.ctx.md5

                }

                #proxy_pass http://127.0.0.1:8008;

        }

    3、测试并验证结果        

        # curl -svo /dev/null "https://www.centosdoc.com/image/20181216/1544934870690012.png"

        * About to connect() to www.centosdoc.com port 443 (#0)

        *   Trying 47.93.228.41…

        * Connected to www.centosdoc.com (47.93.228.41) port 443 (#0)

        * Initializing NSS with certpath: sql:/etc/pki/nssdb

        *   CAfile: /etc/pki/tls/certs/ca-bundle.crt

          CApath: none

        * SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

        * Server certificate:

        *       subject: CN=www.centosdoc.com

        *       start date: Sep 07 00:00:00 2018 GMT

        *       expire date: Oct 07 12:00:00 2019 GMT

        *       common name: www.centosdoc.com

        *       issuer: CN=TrustAsia TLS RSA CA,OU=Domain Validated SSL,O="TrustAsia Technologies, Inc.",C=CN

        > GET /image/20181216/1544934870690012.png HTTP/1.1

        > User-Agent: curl/7.29.0

        > Host: www.centosdoc.com

        > Accept: */*

        > 

        < HTTP/1.1 200 OK

        < Server: openresty

        < Date: Sun, 22 Sep 2019 09:15:38 GMT

        < Content-Type: image/png

        < Transfer-Encoding: chunked

        < Connection: keep-alive

        < Content-hash: d41d8cd98f00b204e9800998ecf8427e

        < 

        { [data not shown]

        * Connection #0 to host www.centosdoc.com left intact

4、注意事项

  •  新location 要截取URL,直接方向代理到后端根,是为了原location转发到新location后 文件路径保持一致

  • 在content_by_lua_block中设置头不生效,只能将md5值转递到header_filter_by_lua_block

  • 增加md5头肯定对性能有影响,避免全局设置

    

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注