快速导航

初始的配置文件

worker_processes  1;
error_log logs/error.log;
events {
    worker_connections 1024;
}
http {

    # 加载lua模块
    lua_package_path "/usr/local/openresty/lualib/?.lua;;";
    # 加载c模块
    lua_package_cpath "/usr/local/openresty/lualib/?.so;;";

    # 在这里配置,这样当前http块内需要用到cjson模块时,都不需要独自加载了
    init_by_lua_block{
        -- 注意,这里面是lua语法,注释是两个杠 不是井号
        cjson=require 'cjson';
        -- mysql=require("resty.mysql");
        -- redis=require 'resty.redis';
    }


    server {
        listen 9000;
        location / {
            default_type text/html;
            content_by_lua '
                ngx.say("<p>Hello, World! second test!</p>")
            ';
        }
        location /abc {
            lua_code_cache off;
            # default_type text/html;
            default_type application/json;
            content_by_lua_file lua/a.lua;
        }
    }
}

从url获取参数,如果其他rest请求参数在url也可以使用此获取

修改a.lua文件

-- 读取所有url参数
local arg = ngx.req.get_uri_args()
ngx.say("读取的参数类型是:"..type(arg)) -- table

-- 遍历table并打印参数
for k,v in pairs(arg) do
    ngx.say("[GET ] key:", k, " v:", v)
end

-- 只取name,取不到就是nil
ngx.say(arg["name"])


-- 取单个参数: ngx.var.arg_XXX 
ngx.say(ngx.var.arg_name)

请求:ip:9000/abc?name=zhangsan

Post请求 读取参数

-- 解析 body 参数之前一定要先读取 body
ngx.req.read_body()

-- 获取数据,目标数据也是一个table
local arg = ngx.req.get_post_args()
local data = ngx.req.get_body_data()
for k,v in pairs(arg) do
    ngx.say("[POST] key:", k, " v:", v)
end
ngx.say('')
ngx.say("**********下面是我后期更新的*********")
ngx.say('')
if data ~= nil then
        ngx.say(type(data)) -- type is string
        ngx.say(data)
end                                                                             

测试有不同的结果,form-data数据是混乱的,x-www-form-urlencoded才是正常的!

post完成!我想了一下post有各种content-type形式,form-data可以是键值对、文件等。x-www-form-urlencode只能是键值对。这也解释了为什么接口muiltfile无法生成上传文件等swagger接口文档!

@RequestParam --- from 表单形式取值
app软件里面常用下面⬇️
@RequestBody ---- json 形式取值

使用post常用nginx的api

-- 解析 body 参数之前一定要先读取 body
ngx.req.read_body()

-- 获取数据,目标数据也是一个table
local arg = ngx.req.get_post_args()

-- 获取数据,返回string类型的数据,不方便我们获取
local data = ngx.req.get_body_data()

获取请求类型

ngx.var.request_method,返回大写的请求类型:GET

-- 只能使用一次,使用过后,第二次执行就是nil
local method = ngx.var.request_method;
-- local nilMethod = ngx.var.request_method;

if method == "GET" then
    ngx.say("is GET")
else
    ngx.say(method)
end

利用openresty发起请求 建议用方案二

方案一:子请求ngx.location.capture

官网说:子请求只是模仿 HTTP 接口,但涉及额外的 HTTP/TCP 流量IPC。一切都在内部高效地在 C 级别上运行。应该就是性能不错!

ngx内部有函数,可以支持发起ngx.location.capture 的内部子查询方式发起(不支持ip与端口),但是我们proxy_pass 来实现发起对外部请求!如果你仅仅需要本机内部,则不需要proxy_pass实现对上游访问!

修改nginx.conf文件

worker_processes  1;
error_log logs/error.log;
events {
    worker_connections 1024;
}
http {

    # 加载lua模块
    lua_package_path "/usr/local/openresty/lualib/?.lua;;";
    # 加载c模块
    lua_package_cpath "/usr/local/openresty/lualib/?.so;;";

    # 在这里配置,这样当前http块内需要用到cjson模块时,都不需要独自加载了
    init_by_lua_block{
        -- 注意,这里面是lua语法,注释是两个杠 不是井号
        cjson=require 'cjson';
        -- mysql=require("resty.mysql");
        -- redis=require 'resty.redis';
    }

    upstream diyServer{   # ban _ tomcat not spuuort
        hash $request_uri; # 让每个请求/item/id=001 访问到固定server,这样可以实现固定url去找固定server。(这样我Aserver的缓存,就不会请求Bserver了)
        server 192.168.31.204:8080;        # ①  自己springboot写一个请求返回(证明openresty发送了http请求)
        keepalive 50;               # ② 一定要添加keepalive保持长链接,减少连接导致的性能损失
        # 一个长连接处理最大请求数(定期释放内存,防止内存溢出)
        keepalive_requests 8192;
    }

    server {
        listen 9000;
        location / {
            default_type text/html;
            content_by_lua '
                ngx.say("<p>Hello, World! second test!</p>")
            ';
        }
        location /abc {
            lua_code_cache off;
            # default_type text/html;
            default_type application/json;
            content_by_lua_file lua/a.lua;
        }
        location /useForOtherUrlRequest{
            internal; # 只允许被内部访问,外部访问就是404
            proxy_pass http://diyServer/user/api/v1/hello/;
        }
    }
}

保存后记得重载nginx配置文件

修改a.lua文件

-- res是个table 有header,body,status, https://github.com/openresty/lua-nginx-module#ngxlocationcapture 所有配置都在github说明了
local res = ngx.location.capture('/useForOtherUrlRequest',
                    {
                        method = ngx.HTTP_POST, -- defult is GET
			body = "names=wangwu", -- 指定子请求的请求正文(仅限字符串值)x-www-urlencoding 
                        args = {names=lisi,age=aa}, -- 指定子请求的 URI 查询参数(字符串值和 Lua 表都被接受)
		        -- always_forward_bodybody = true,
			-- copy_all_vars = true
                    }
                )

ngx.say(res.status)
ngx.say(res.body)

后端接口,实际就要一个names字段,不要担心我上文使用的是RestController,返回的是json

    @RequestMapping("/hello")
    public HashMap sayhello(String names){
        HashMap<String,Object> hashMap = new HashMap<>();
        hashMap.put("name",names);
        hashMap.put("age",20);
        return hashMap;
    }

测试吧!这里有个bug,只要body不选x-www-urlencoded,并且随便添加任何一个值,java就取不到names,实际取到的是lua中body的wangwu!与url连接的内容无关!openresty1.21.4.1

好在这种方式贼他妈拉跨,bug我问了也没人回答,如果有人知道联系我q:740969606

我们采用第二种方法 当前只适合从url中拼接好才能有效请求 如ip:9000/user/api/v1/hello?names=zhangsan

-- 千万不要少,我们是post请求这个lua,如果要读取数据就有这个,不然你回发现你的请求59秒都没响应
ngx.req.read_body()
local args, err = ngx.req.get_uri_args()
local res = ngx.location.capture('/useForOtherUrlRequest',
    {
        method = ngx.HTTP_POST,
        body = args.data
    }
)
ngx.say(res.status)
ngx.say(res.body)

方案二:cosocket 这个不是openresty的本库内容

官网地址:https://github.com/ledgetech/lua-resty-http

安装cosocket

opm get ledgetech/lua-resty-http

重启openresty,使我们配置文件生效

# 重启配置文件(前提得启动过)
sudo /usr/local/openresty/nginx/sbin/nginx -p /www -c conf/nginx.conf -s reload

重新编写a.lua文件

ngx.req.read_body()
local args, err = ngx.req.get_post_args()

-- 遍历table并打印参数
for k,v in pairs(args) do
    ngx.say("key:", k, " v:", v)
end

ngx.say('单独读取到的names是:',args.names)
local body = 'names='..args.names..'&age='..args.age -- 封装请求参数
local http = require "resty.http"   -- ① 引入模块 执行opm get ledgetech/lua-resty-http后,重启openresty才能生效
local httpc = http.new()
local res, err = httpc:request_uri( -- ② 发起请求
                   "http://192.168.31.204:8080/user/api/v1/hello",
                    {
                        method = "POST",
                        body = body,
                        headers = {
                            ["Content-Type"] = "application/x-www-form-urlencoded",
                            
                        },
                    }
                )

if res ~= nil and 200 == res.status then
    ngx.say('请求成功!',res.body)
else
    ngx.say('请求失败!',err)
end

测试

完成!

特殊说明:
上述文章均是作者实际操作后产出。烦请各位,请勿直接盗用!转载记得标注原文链接:www.zanglikun.com
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取全部资料 ❤