Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >4 OpenResty & Lua 处理各类Http请求

4 OpenResty & Lua 处理各类Http请求

作者头像
收心
发布于 2022-08-24 08:17:39
发布于 2022-08-24 08:17:39
1.9K00
代码可运行
举报
文章被收录于专栏:Java实战博客Java实战博客
运行总次数:0
代码可运行

快速导航

初始的配置文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
-- 读取所有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"])

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

Post请求 读取参数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
-- 解析 body 参数之前一定要先读取 body
ngx.req.read_body() 

-- 获取数据,目标数据也是一个table
local arg = ngx.req.get_post_args()
for k,v in pairs(arg) do
    ngx.say("[POST] key:", k, " v:", v)
end

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

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

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

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

方案一:ngx.location.capture(有bug)

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

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

修改nginx.conf文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
        server 192.168.31.204:8080;        # ①  zi ji xie yi ge controller fanhuiyixia
        keepalive 20;               # ② 一定要添加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文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
-- 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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @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!

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
local args, err = ngx.req.get_uri_args()
-- 组装uri
local res = ngx.location.capture('/useForOtherUrlRequest',
    {
        method = ngx.HTTP_POST,
        body = args.data
    }
)
ngx.say(res.status)
ngx.say(res.body)

方案二:

特殊说明: 以上文章,均是我实际操作,写出来的笔记资料,不会盗用别人文章!烦请各位,请勿直接盗用!转载记得标注来源!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验