proxy_pass 请求基于通过 lua-nginx 的另一个内部请求的结果

proxy_pass request base on the result of another internal request via lua-nginx

我想proxy_pass一个请求或return一个基于内部服务结果的响应。 为了实现这个目的,我使用 openresty docker image

这是我的 nginx.conf:

# nginx.vh.default.conf  --  docker-openresty
#
# This file is installed to:
#   `/etc/nginx/conf.d/default.conf`
#
# It tracks the `server` section of the upstream OpenResty's `nginx.conf`.
#
# This config (and any other configs in `etc/nginx/conf.d/`) is loaded by
# default by the `include` directive in `/usr/local/openresty/nginx/conf/nginx.conf`.
#
# See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files
#
# load_module /usr/lib/nginx/modules/ndk_http_module.so;
# load_module /usr/lib/nginx/modules/ngx_http_lua_module.so;
lua_package_path '/usr/local/nginx/includes.d/?.lua;/home/user/lua/?.lua;/home/lua/?.lua;;';

error_log  logs/error.log  info;
error_log  logs/error.log  debug;

upstream flask_webservice {
    server challenge:5000;
}

server {
    listen 80;
    server_name  localhost;
    lua_need_request_body on;
    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        # default_type text/plain;
        # proxy_pass http://challenge:5000/;
        content_by_lua_file /home/user/lua/proxy_middleware.lua;
        # content_by_lua_block {}
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/local/openresty/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           /usr/local/openresty/nginx/html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

这里是proxy_middleware.lua:

local http = require "resty.http"
local cjson = require "cjson"

local httpc = http.new()

local challenge_url = "http://" .. ngx.var.flask_webservice .. ngx.var.uri
local request_header = ngx.req.get_headers()
local request_method = ngx.req.get_method()
local request_body = ngx.req.get_body_data()

if request_body == nil then
    request_body = {}
end

if request_header == nil then
    request_header = {}
end

ngx.log(ngx.DEBUG, challenge_url)
ngx.log(ngx.DEBUG, "request_header: " .. cjson.encode(request_header))
ngx.log(ngx.DEBUG, "request_method: " .. request_method)
ngx.log(ngx.DEBUG, "request_body: " .. cjson.encode(request_body))

local res, err = httpc:request_uri(challenge_url, {
    method = request_method,
    headers = request_header,
    body = request_body
})

ngx.log(ngx.DEBUG, "response is:" .. cjson.encode(res))
ngx.log(ngx.DEBUG, "error is:" .. cjson.encode(err))

这是我遇到的错误:

2020/12/24 19:17:52 [error] 7#7: *3 lua entry thread aborted: runtime error: /home/user/lua/proxy_middleware.lua:6: attempt to concatenate field 'flask_webservice' (a nil value)

这是 the Github repo

上的项目

我有两个问题:

  1. 还有其他方法可以达到这个目的吗?
  2. 如何在Lua代码中访问上游服务器?

我通过 resty-http 管理了第一个请求,然后根据第一个请求的响应

使用 ngx.location.capture 到 proxy_pass 请求

这里是lua_middleware.lua:

local http = require "resty.http"
local cjson = require "cjson"

local httpc = http.new()

local challenge_url = "http://challenge:5000" .. ngx.var.uri
local request_header = ngx.req.get_headers()
local request_method = ngx.req.get_method()
local request_body = ngx.req.get_body_data()

if request_body == nil then
    request_body = {}
end

if request_header == nil then
    request_header = {}
end

ngx.log(ngx.DEBUG, challenge_url)
ngx.log(ngx.DEBUG, "request_header: " .. cjson.encode(request_header))
ngx.log(ngx.DEBUG, "request_method: " .. request_method)
ngx.log(ngx.DEBUG, "request_body: " .. cjson.encode(request_body))

local res, err = httpc:request_uri(challenge_url, {
    method = request_method,
    headers = request_header,
    body = request_body
})

local response_body = res.body
local response_headers = res.headers
local response_status = res.status

ngx.log(ngx.DEBUG, "response_body: " .. cjson.encode(response_body))
ngx.log(ngx.DEBUG, "response_headers: " .. cjson.encode(response_headers))
ngx.log(ngx.DEBUG, "response_status: " .. cjson.encode(response_status))
ngx.log(ngx.DEBUG, "error: " .. cjson.encode(err))

ngx.log(ngx.DEBUG, "logger: " .. response_status == 200)
ngx.log(ngx.DEBUG, "status type: " .. type(response_status))

if response_status == 200 then
    ngx.log(ngx.DEBUG, "Redirecting ...")
    local redirected_res = ngx.location.capture("/redirect_to", {
        method = ngx.HTTP_POST,
        always_forward_body = true
    })
    ngx.log(ngx.DEBUG, "redirect res body: " .. cjson.encode(redirected_res.body))
    ngx.log(ngx.DEBUG, "redirect res status: " .. cjson.encode(redirected_res.status))

    ngx.status = redirected_res.status
    ngx.say(redirected_res.body)
    ngx.exit(ngx.HTTP_OK)

else
    ngx.status = response_status
    ngx.say(response_body)
    ngx.exit(ngx.HTTP_OK)
end

这是我的 nginx.conf:

# nginx.vh.default.conf  --  docker-openresty
#
# This file is installed to:
#   `/etc/nginx/conf.d/default.conf`
#
# It tracks the `server` section of the upstream OpenResty's `nginx.conf`.
#
# This config (and any other configs in `etc/nginx/conf.d/`) is loaded by
# default by the `include` directive in `/usr/local/openresty/nginx/conf/nginx.conf`.
#
# See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files
#
# load_module /usr/lib/nginx/modules/ndk_http_module.so;
# load_module /usr/lib/nginx/modules/ngx_http_lua_module.so;
lua_package_path '/usr/local/nginx/includes.d/?.lua;/home/user/lua/?.lua;/home/lua/?.lua;;';

error_log  logs/error.log  info;
error_log  logs/error.log  debug;

upstream flask_webservice {
    server challenge:5000;
}

server {
    listen 80;
    server_name  localhost;
    resolver 127.0.0.11;
    lua_need_request_body on;
    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        client_max_body_size 50k;
        client_body_buffer_size 50k;

        # default_type text/plain;
        # proxy_pass http://challenge:5000/;
        content_by_lua_file /home/user/lua/proxy_middleware.lua;
    }

    location /redirect_to {
        proxy_pass http://challenge:5000/arvan;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/local/openresty/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           /usr/local/openresty/nginx/html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

这里是 project link