【窍门】测试环境前端静态资源注入

背景

测试环境已有静态资源服务器,但是需要设置hosts172.19.80.14 s.thsi.cn进行访问,这必须连接抓包才能完成,一些支付相关的业务由于第三方支付服务的限制,在设置抓包的情况下将无法走完流程。为了满足这样的场景,需要提供一种公网访问测试环境静态资源的方法。

测试环境nginx设置了CD静态资源的转发,链路为https://testm.10jqka.com.cn/cd/https://s.thsi.cn/cd/,这类资源只需替换域名即可。

但是采用这样的方式,必须让前端在编译测试环境页面时就将CD静态资源目录设置为 testm 域名,构建产物和线上将会不一致,十分不优雅。

所以,有什么样的方法可以即可以维持测试环境构建产物和线上一致,又能使得CD静态资源请求转到测试环境呢?

同样地,前端注入 eruda 工具,是否也能有不改变构建产物而实现的优雅方式呢?

解决方案

在 testm 的 nginx 层面处理,前端只管按照正式环境的方式进行构建,nginx层将页面所有的//s.thsi.cn/cd/替换为//testm.10jqka.com.cn/cd/,然后在 html 的 header 结束之前注入 eruda 的 script 标签即可;

使用方法

直接在 nginx.conf 中新增如下语句进行配置引用即可

include thsi_inject.conf;

按照上述配置之后,前端页面将看到 eruda 工具,并且CD资源请求全部替换为testm域名,html请求的响应头也会有Thsi-Inject-Status: true ;

如果某个前端页面不希望有 eruda 工具注入,则在转发规则中新增如下语句即可关闭

set $eruda "false";

副作用

使用注入之后,nginx返回给浏览器的相应中响应头中将不会有Content-Length,而是走Transfer-Encoding: chunked的模式,目前还没有发现由此导致的问题;

HTTP请求经由 lua 做了一层过滤,性能会有所影响;

原理

使用 openresty 的header_filterbody_filter功能即可实现,源码如下

header_filter

-- 文件位置:/data/waf/lua/inject/thsi_header.lua

local pos = string.find(ngx.var.request_uri, ".html")

if pos ~= nil then

    -- 清空响应头中的内容长度,因为body的内容替换会导致实际发送内容长度变化

    -- 标称长度和实际长度若不一致会导致前端下载html页面资源时间过长

    ngx.header.content_length = nil

    -- 响应头中添加注入的标记

    ngx.header["Thsi-Inject-Status"] = "true"

end

body_filter

-- 文件位置:/data/waf/lua/inject/thsi_body.lua

-- body_filter_by_lua, body filter模块,ngx.arg[1]代表输入的chunk,ngx.arg[2]代表当前chunk是否为last

local pos = string.find(ngx.var.request_uri, ".html")

if pos ~= nil then

    local chunk, eof = ngx.arg[1], ngx.arg[2]

    local buffered = ngx.ctx.buffered

    if not buffered then

      buffered = {}  -- XXX we can use table.new here

      ngx.ctx.buffered = buffered

    end

    if chunk ~= "" then

      buffered[#buffered + 1] = chunk

      ngx.arg[1] = nil

    end

    if eof then

      local whole = table.concat(buffered)

      ngx.ctx.buffered = nil

      -- try to unzip

      -- local status, debody = pcall(com.decode, whole)

      -- if status then whole = debody end

      -- try to add or replace response body

      -- local js_code = ...

      -- whole = whole .. js_code

      -- cd路径的静态资源请求域名替换

      whole = string.gsub(whole, "//s.thsi.cn/cd/",  "//testm.10jqka.com.cn/cd/")

      -- 注入前端调试工具

      if ngx.var.eruda ~= 'false' then

          whole = string.gsub(whole, "</head>",  '<script type="text/javascript" src="//s.thsi.cn/js/m/eruda.js"></script></head>')

      end

      ngx.arg[1] = whole

    end

end

nginx conf

# 文件位置:/usr/local/nginx/conf/thsi_inject.conf

header_filter_by_lua_file /data/waf/lua/inject/thsi_header.lua;

body_filter_by_lua_file /data/waf/lua/inject/thsi_body.lua;

参考资料

Lua + OpenResty修改response body (https://jkzhao.github.io/2018/05/03/Lua-OpenResty%E4%BF%AE%E6%94%B9response-body/)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容