ZBLOG

openresty需要识别出上游响应的JS代码里的window.location对象,并对location对象修改代码,如何借助babel完成这件事

要借助 Babel 修改 OpenResty 上游响应中的 window.location 对象代码,可以按照以下步骤实现:


1. 核心思路

  • 目标:在 OpenResty 中拦截上游返回的 JavaScript 代码,通过 Babel 解析、修改 AST(抽象语法树),最终生成修改后的代码。
  • 关键工具
    • Babel Parser:将 JS 代码解析为 AST。
    • Babel Traverse:遍历并修改 AST。
    • Babel Generator:将修改后的 AST 重新生成 JS 代码。

2. OpenResty + Babel 的实现步骤

(1) OpenResty 配置

在 Nginx/OpenResty 的 location 块中拦截响应,调用 Lua 脚本处理 JS:

location / {
    proxy_pass http://upstream_server;
    header_filter_by_lua_block {
        -- 检查 Content-Type 是否为 JavaScript
        if ngx.header.content_type and string.match(ngx.header.content_type, "javascript") then
            ngx.ctx.process_js = true
        end
    }
    body_filter_by_lua_block {
        if ngx.ctx.process_js then
            local resp = ngx.arg[1]
            -- 调用外部 Node.js/Babel 服务处理 JS(或直接嵌入 LuaJS)
            local modified_js = modify_js_with_babel(resp)
            ngx.arg[1] = modified_js
        end
    }
}

(2) Babel JS处理逻辑

假设通过 Node.js HTTP服务处理(推荐):

const babel = require('@babel/core');
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const generator = require('@babel/generator').default;

function transformJS(code) {
    // Step1: Parse JS to AST
    const ast = parser.parse(code, { sourceType: 'script' });

    // Step2: Modify AST (e.g., change window.location.href)
    traverse(ast, {
        MemberExpression(path) {
            if (path.get('object').matchesPattern('window.location') || 
                path.get('object').matchesPattern('location')) {
                // Example: Replace location.href with a new value
                if (path.node.property.name === 'href') {
                    path.parentPath.replaceWith(
                        t.stringLiteral("https://modified-url.com")
                    );
                }
            }
        }
    });

    // Step3: Generate new JS code from AST
    return generator(ast).code;
}

// HTTP Server for OpenResty to call (e.g., http://localhost:3000/transform)
app.post('/transform', (req, res) => {
    const modifiedJS = transformJS(req.body.code);
    res.send(modifiedJS);
});

(3) Lua调用Node.js服务

在 OpenResty Lua脚本中发送请求到 Babel服务:

local http = require "resty.http"
local function modify_js_with_babel(js_code)
    local httpc = http.new()
    local res, err = httpc:request_uri("http://node-babel-service:3000/transform", {
        method = "POST",
        body = js_code,
        headers = { ["Content-Type"] = "text/javascript" }
    })
    return res and res.body or js_code -- Fallback to original if error
end

3.替代方案(纯Lua)

如果不想依赖 Node.js,可以用轻量级Lua库如 LuaJS(但功能有限):

local luajs = require("luajs")
local function modify_location_in_js(code)
   -- Simple regex replacement (不推荐用于复杂逻辑)
   return code:gsub("window.location.href%s*=%s*['\"][^'\"]+['\"]", "window.location.href='https://new-url.com'")
end

-- Usage in body_filter_by_lua_block:
ngx.arg[1] = modify_location_in_js(ngx.arg[1])

4.注意事项

  • 性能:AST操作较慢,建议对关键JS文件按需处理。
  • 错误处理:确保Babel解析失败时回退原始代码。
  • 安全:验证上游响应内容,避免注入攻击。

如果需要更具体的实现细节(如特定AST修改规则),可以进一步讨论!


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=23976

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?