4 OpenResty & Lua 处理各类Http请求

快速导航

初始的配置文件

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

测试

完成!

特殊说明: 以上文章,均是我实际操作,写出来的笔记资料,不会盗用别人文章!烦请各位,请勿直接盗用!转载记得标注来源!
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: openresty lua 可以通过 ngx.req.get_body_data() 函数来获取请求报文数据。如果请求报文是以 application/x-www-form-urlencoded 或 multipart/form-data 格式提交的,也可以通过 ngx.req.get_post_args() 函数来获取请求参数。如果请求报文是以 application/json 格式提交的,可以通过 ngx.req.get_body_data() 函数获取请求体数据,然后使用 json.decode() 函数将其解析为 Lua table。 ### 回答2: 要在OpenResty中接受请求报文数据,可以使用ngx.req模块。这个模块提供了处理请求内容的功能。 首先,我们可以使用ngx.req.get_method函数获取请求的方法,例如GET或POST。接下来,可以使用ngx.req.get_headers函数获取请求头的信息,例如User-Agent、Content-Type等。 要获取请求体的内容,可以使用ngx.req.read_body函数来读取请求体。然后,可以使用ngx.req.get_post_args函数来获取请求体的参数。如果请求体的类型是application/x-www-form-urlencoded,那么可以使用ngx.req.get_post_args函数直接获取参数。如果请求体是JSON格式,可以使用ngx.req.get_body_data函数获取请求体的原始数据,然后使用Lua中的json库进行解析。 另外,还可以使用ngx.req.get_uri_args函数来获取URL中的参数。这个函数返回一个Lua表,其中包含了URL中的所有参数。 除了获取请求报文数据,OpenResty还提供了ngx.req.set_header函数来设置请求头的信息。可以使用ngx.req.set_header函数来添加、修改或删除请求头的参数。 在处理请求报文数据后,可以使用ngx.say函数来像客户端返回响应内容。可以将任何数据作为ngx.say函数的参数进行返回,包括字符串、数值、表等。 总结起来,通过ngx.req模块的函数,我们可以获取请求的方法、请求头、请求体、URL参数等请求报文数据,并且还可以设置请求头和返回响应内容。 ### 回答3: 在OpenResty中,可以通过使用ngx.req.get_body_data()方法接收请求报文数据。 ngx.req.get_body_data()方法用于获取请求报文主体的数据,并且可以在ngx_lua中方便地进行处理。 使用方法如下: local body_data = ngx.req.get_body_data() if body_data then -- 处理请求报文数据 -- ... else -- 请求报文没有主体数据 -- ... end 需要注意的是,ngx.req.get_body_data()方法只能获取请求报文中的主体数据,并不能获取请求报文的其他信息。如果需要获取其他请求信息,可以使用ngx.req.get_uri_args()获取查询参数,ngx.req.get_headers()获取请求头部信息,以及ngx.req.get_method()获取请求方法等。 在使用ngx.req.get_body_data()方法前,需要保证在nginx配置文件中已启用了请求体内容的接收。可以在http或server配置块中添加以下指令: http { # ... client_body_buffer_size 8k; client_max_body_size 8m; # ... } 以上是OpenResty Lua如何接收请求报文数据的方法。通过使用ngx.req.get_body_data()方法,我们可以方便地获取到请求报文的主体数据,并进行相应的处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值