MD5 $request_body

mat*_*129 2 nginx cache

我正在使用 nginx(和 OpenResty)并尝试$request_body对缓存进行哈希处理(使用srcache)。

当试图做到echo$request_body,它完美的作品:

# actually echoes the request body
location /works {
    # force loading the body
    echo_read_request_body;

    echo $request_body;
}
Run Code Online (Sandbox Code Playgroud)

但是当试图计算 md5 时,我得到了一个空字符串的 MD5,尽管我确保它$request_body是通过echo_read_request_body;.

# echoes d41d8cd98f00b204e9800998ecf8427e, which is the MD5 for empty input.
location /doesnt-work-md5 {
    # force loading the body
    echo_read_request_body;

    set_md5 $digest $request_body;
    echo $digest;
}
Run Code Online (Sandbox Code Playgroud)

最奇怪的现象是,在尝试复制变量时它甚至不起作用:

# echoes nothing - empty data
location /doesnt-work {
    # force loading the body
    echo_read_request_body;

    set $temp $request_body;
    echo $temp;
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,这些最新的片段在使用$echo_request_body代替时不起作用$request_body

提前致谢!

mat*_*129 5

在OpenResty 开发人员的帮助下,我意识到set_XYZ(ie set, set_md5) 在 nginxrewrite阶段进行评估,而$request_body/$echo_request_body仅通过该content阶段可用。

因此,在评估 时set_md5 $digest $request_body;$request_body变量为空,这解释了常量 MD5 结果。

最终,我在自己的 API 应用程序中实现了实际的缓存密钥生成(参见下面的示例),并使用access_by_lua块访问它。

块在运行access阶段,前srcache_fetchsrcache_store被评估(它们在评估post-accessoutput-filter分别)。

在我自己的 API 中实现它可以更好地控制缓存键生成逻辑,这在单独使用 nginx 时很难做到(因为我不想成为一个全职的 lua 程序员)。

例如,我希望能够使用 Json 主体确定性地缓存POST请求。Json 序列化不是确定性的,因为键可以按任何顺序排列。在我的 API 中,我对键进行排序,以便生成的缓存键对于相同的数据是不变的。

此外,它简化了 的处理$request_body,因为 lua 发出的子请求只是将它转发到 API,而不管阶段或磁盘缓冲状态如何。

最终的配置看起来像

location /api {
    # proxy_pass ...
    # Force normal responses (no deflate, etc.) See https://github.com/openresty/srcache-nginx-module#srcache_ignore_content_encoding
    proxy_set_header  Accept-Encoding  "";

    set $cache_key "";
    access_by_lua_block {
        local res = ngx.location.capture('/generate-key' .. ngx.var.request_uri, {
                method=ngx.HTTP_POST,
                -- forwards the entire request body,
                -- regardless of disk buffering!
                always_forward_body=true,
                args=ngx.var.args
            })

        if res then
            ngx.var.cache_key = res.body
        end
    }

    # ... srcache options ...
}

location /generate-key {
    # proxy_pass ...
}
Run Code Online (Sandbox Code Playgroud)

示例密钥生成 API 如下:

location /api {
    # proxy_pass ...
    # Force normal responses (no deflate, etc.) See https://github.com/openresty/srcache-nginx-module#srcache_ignore_content_encoding
    proxy_set_header  Accept-Encoding  "";

    set $cache_key "";
    access_by_lua_block {
        local res = ngx.location.capture('/generate-key' .. ngx.var.request_uri, {
                method=ngx.HTTP_POST,
                -- forwards the entire request body,
                -- regardless of disk buffering!
                always_forward_body=true,
                args=ngx.var.args
            })

        if res then
            ngx.var.cache_key = res.body
        end
    }

    # ... srcache options ...
}

location /generate-key {
    # proxy_pass ...
}
Run Code Online (Sandbox Code Playgroud)