Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >openresty是如何通过lua代码获取nginx内请求数据的

openresty是如何通过lua代码获取nginx内请求数据的

原创
作者头像
stan1ey
发布于 2022-06-04 16:17:54
发布于 2022-06-04 16:17:54
2.6K00
代码可运行
举报
文章被收录于专栏:安全开发记录安全开发记录
运行总次数:0
代码可运行

nginx中处理请求是围绕ngx_http_request_t结构体进行的。

ngx_http_request_t结构体包含了当前http请求的所有数据。

ngx_http_lua_module与nginx进行交互,主要围绕这个结构体实现的,lua代码获取nginx内部http请求数据,然后进行处理。

lua_module为此在建立新的协程,将ngx_http_request_t的指针保存在了lua_State的全局变量中。

经过 ngx_http_lua_set_req 将请求与协程关联。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static ngx_inline void
ngx_http_lua_set_req(lua_State *L, ngx_http_request_t *r)
{
#ifdef OPENRESTY_LUAJIT
    lua_setexdata(L, (void *) r);
#else
    lua_pushlightuserdata(L, r);
    lua_setglobal(L, ngx_http_lua_req_key);
#endif
}

经过ngx_http_lua_get_req获取请求的ngx_http_request_t结构体,从结构体中把想要获取的http数据返回。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// ngx_http_lua_util.h文件
// 经过 ngx_http_lua_get_req 从lua_State中获取协程关联的请求
 
static ngx_inline ngx_http_request_t *
ngx_http_lua_get_req(lua_State *L)
{
    ngx_http_request_t    *r;
 
    lua_getglobal(L, ngx_http_lua_req_key);
    r = lua_touserdata(L, -1);
    lua_pop(L, 1);
 
    return r;
}

lua获取nginx请求方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function ngx.req.get_method()
    local r = get_request()
    if not r then
        error("no request found")
    end
 
    do
        local id = C.ngx_http_lua_ffi_req_get_method(r)
        if id == FFI_BAD_CONTEXT then
            error("API disabled in the current context", 2)
        end
 
        local method = methods[id]
        if method then
            return method
        end
    end
 
    local sizep = get_size_ptr()
    local rc = C.ngx_http_lua_ffi_req_get_method_name(r, namep, sizep)
    if rc ~= 0 then
        return nil
    end
 
    return ffi_str(namep[0], sizep[0])
end
ngx_http_lua_req_method.c

int
ngx_http_lua_ffi_req_get_method(ngx_http_request_t *r)
{
    if (r->connection->fd == (ngx_socket_t) -1) {
        return NGX_HTTP_LUA_FFI_BAD_CONTEXT;
    }
 
    return r->method;
}
 
int
ngx_http_lua_ffi_req_get_method_name(ngx_http_request_t *r, u_char **name,
    size_t *len)
{
    if (r->connection->fd == (ngx_socket_t) -1) {
        return NGX_HTTP_LUA_FFI_BAD_CONTEXT;
    }
 
    *name = r->method_name.data;
    *len = r->method_name.len;
 
    return NGX_OK;
}

lua获取nginx请求参数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function ngx.req.get_uri_args(max_args)
    -- ...
    -- 获取请求参数个数
    local n = C.ngx_http_lua_ffi_req_get_uri_args_count(r, max_args, truncated)
 
    -- 获取请求参数长度
    local args_len = C.ngx_http_lua_ffi_req_get_querystring_len(r)
 
    -- 用于存放请求参数的数据结构
    local strbuf = get_string_buf(args_len + n * table_elt_size)
    local kvbuf = ffi_cast(table_elt_type, strbuf + args_len)
 
    -- nargs为请求参数的个数
    -- kvbuf为table类型kv结构 用于保存请求参数/index.html?aa=11&bb=22&cc=33
    local nargs = C.ngx_http_lua_ffi_req_get_uri_args(r, strbuf, kvbuf, n)
 
    -- 最终请求参数保存到 args 表中返回
    local args = new_tab(0, nargs)
    for i = 0, nargs - 1 do
        local arg = kvbuf[i]
 
        local key = arg.key
        key = ffi_str(key.data, key.len)
 
        local value = arg.value
 
        -- value 为arg.value.data
        -- 最终保存到args table中
        args[key] = value
        -- 如果 参数keys值有重复
        args[key] = {existvalue, value}
    end
 
    if truncated[0] ~= 0 then
        return args, "truncated"
    end
 
    return args
end

ngx_http_lua_args.c

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int
ngx_http_lua_ffi_req_get_uri_args_count(ngx_http_request_t *r, int max,
    int *truncated)
{
    int                      count;
    u_char                  *p, *last;
 
    if (r->connection->fd == (ngx_socket_t) -1) {
        return NGX_HTTP_LUA_FFI_BAD_CONTEXT;
    }
 
    *truncated = 0;
 
    if (max < 0) {
        max = NGX_HTTP_LUA_MAX_ARGS;
    }
 
    last = r->args.data + r->args.len;
    count = 0;
 
    for (p = r->args.data; p != last; p++) {
        if (*p == '&') {
            if (count == 0) {
                count += 2;
 
            } else {
                count++;
            }
        }
    }
 
    if (count) {
        if (max > 0 && count > max) {
            count = max;
            *truncated = 1;
            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                           "lua hit query args limit %d", max);
        }
 
        return count;
    }
 
    if (r->args.len) {
        return 1;
    }
 
    return 0;
}

ngx_http_lua_ffi_req_get_querystring_len函数

ngx_http_lua_ffi_req_get_uri_args函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
size_t
ngx_http_lua_ffi_req_get_querystring_len(ngx_http_request_t *r)
{
    return r->args.len;
}
 
int
ngx_http_lua_ffi_req_get_uri_args(ngx_http_request_t *r, u_char *buf,
    ngx_http_lua_ffi_table_elt_t *out, int count)
{
    int                          i, parsing_value = 0;
    u_char                      *last, *p, *q;
    u_char                      *src, *dst;
 
    if (count <= 0) {
        return NGX_OK;
    }
 
    ngx_memcpy(buf, r->args.data, r->args.len);
 
    i = 0;
    last = buf + r->args.len;
    p = buf;
    q = p;
 
    while (p != last) {
        if (*p == '=' && !parsing_value) {
            /* key data is between p and q */
 
            src = q; dst = q;
 
            ngx_http_lua_unescape_uri(&dst, &src, p - q,
                                      NGX_UNESCAPE_URI_COMPONENT);
 
            dd("saving key %.*s", (int) (dst - q), q);
 
            out[i].key.data = q;
            out[i].key.len = (int) (dst - q);
 
            /* skip the current '=' char */
            p++;
 
            q = p;
            parsing_value = 1;
 
        } else if (*p == '&') {
            /* reached the end of a key or a value, just save it */
            src = q; dst = q;
 
            ngx_http_lua_unescape_uri(&dst, &src, p - q,
                                      NGX_UNESCAPE_URI_COMPONENT);
 
            dd("pushing key or value %.*s", (int) (dst - q), q);
 
            if (parsing_value) {
                /* end of the current pair's value */
                parsing_value = 0;
 
                if (out[i].key.len) {
                    out[i].value.data = q;
                    out[i].value.len = (int) (dst - q);
                    i++;
                }
 
            } else {
                /* the current parsing pair takes no value,
                 * just push the value "true" */
                dd("pushing boolean true");
 
                if (dst - q) {
                    out[i].key.data = q;
                    out[i].key.len = (int) (dst - q);
                    out[i].value.len = -1;
                    i++;
                }
            }
 
            if (i == count) {
                return i;
            }
 
            /* skip the current '&' char */
            p++;
 
            q = p;
 
        } else {
            p++;
        }
    }
 
    if (p != q || parsing_value) {
        src = q; dst = q;
 
        ngx_http_lua_unescape_uri(&dst, &src, p - q,
                                  NGX_UNESCAPE_URI_COMPONENT);
 
        dd("pushing key or value %.*s", (int) (dst - q), q);
 
        if (parsing_value) {
            if (out[i].key.len) {
                out[i].value.data = q;
                out[i].value.len = (int) (dst - q);
                i++;
            }
 
        } else {
            if (dst - q) {
                out[i].key.data = q;
                out[i].key.len = (int) (dst - q);
                out[i].value.len = (int) -1;
                i++;
            }
        }
    }
 
    return i;
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Nginx(三):http模块的处理流程解析之正向代理
无疑,在nginx的核心服务中,http服务占据了相当大的份量。那么,要想多了解nginx多一点,则必须要了解其http模块的工作机制。
烂猪皮
2021/01/28
2K0
Nginx(三):http模块的处理流程解析之正向代理
openresty源码剖析——lua代码的加载
##Openresty是什么 OpenResty是一个基于 Nginx 与 Lua 的高性能 Web 平台,通过把lua嵌入到Nginx中,使得我们可以用轻巧的lua语言进行nginx的相关开发,处理高并发,扩展性极高的动态 Web 应用。 大家知道lua_code_cache 开关用于控制是否缓存*_by_lua_file对应的文件里的lua代码 lua_code_cache off的情况下,跟请求有关的阶段,在每次有请求来的时候,都会重新加载最新的lua文件,这样我们修改完代码之后就不用通过reload
magicsoar
2018/02/06
3K0
openresty源码剖析——lua代码的执行
上一篇文章中(https://cloud.tencent.com/developer/article/1037840)我们讨论了openresty是如何加载lua代码的 那么加载完成之后的lua代码又是如何执行的呢 ##代码的执行  在init_by_lua等阶段  openresty是在主协程中通过lua_pcall直接执行lua代码 而在access_by_lua  content_by_lua等阶段中,openresty创建一个新的协程,通过lua_resume执行lua代码 二者的区别在于能否执行n
magicsoar
2018/02/06
2.5K0
Nginx(四):http服务器静态文件查找的实现
上一篇nginx的文章中,我们理解了整个http正向代理的运行流程原理,主要就是事件机制接入,header解析,body解析,然后遍历各种checker,直到处理成功为止。
烂猪皮
2021/01/28
1.9K2
Nginx(四):http服务器静态文件查找的实现
ngin0.1.0之range_filter模块源码解析
/* * Copyright (C) Igor Sysoev */ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> /* * the single part format: * * "HTTP/1.0 206 Partial Content" CRLF * ... header ... * "Content-Type: image/jpeg" CRLF * "Content-Length: SIZ
theanarkh
2019/03/29
9640
ngin0.1.0之range_filter模块源码解析
Nginx内存内容泄漏-问题复现与修复方案解析
最近HackerOne公布了Nginx内存内容泄漏的问题,如果说内存内容泄漏的问题是个Bug的话,那这个Bug是个比较典型的程序没有对输入异常数据做适当的过滤处理而形成的。
糖果
2020/03/25
6610
深入理解nginx的请求限流模块
  当构建高流量的Web应用程序时,保护服务器免受过多请求的影响是至关重要的。过多的请求可能会导致服务器过载,降低性能甚至导致系统崩溃。为了解决这个问题,nginx提供了一个强大的请求限速模块。该模块允许您根据自定义规则限制客户端请求的速率,并且还可以使用延迟机制来平滑处理超出限制的请求。在本文中,我们将深入探讨nginx的请求限速模块,了解它的工作原理、配置选项以及如何在实际应用中使用它来保护您的服务器免受恶意或异常请求的影响。
码农心语
2024/04/09
1K0
深入理解nginx的请求限流模块
openresty下lua的function定义及调用
/usr/local/openresty/lualib/resty/string.lua
code4it
2018/09/17
2.2K0
ngx_http_auth_basic_module源码解析(基于nginx1.17.9)
auth_basic模块是nginx中比较简单的模块。地址在http://nginx.org/en/docs/http/ngx_http_auth_basic_module.html。我们通过分析这个模块的代码,不仅知道如何使用,还可以了解到http认证的实现。该模块支持http认证和验证的功能。支持两个配置。
theanarkh
2020/06/19
8550
编写 Nginx 模块进行 RSA 加解密
在《Nginx 模块系统:前篇》一文中,曾提过要展开聊聊如何编写和编译一个 Nginx 模块。
soulteary
2021/08/16
2K0
编写 Nginx 模块进行 RSA 加解密
handler模块(100%)
相信大家在看了前一章的模块概述以后,都对nginx的模块有了一个基本的认识。基本上作为第三方开发者最可能开发的就是三种类型的模块,即handler,filter和load-balancer。Handler模块就是接受来自客户端的请求并产生输出的模块。有些地方说upstream模块实际上也是一种handler模块,只不过它产生的内容来自于从后端服务器获取的,而非在本机产生的。
用户5640963
2019/07/26
1K0
OpenResty实战系列 | Nginx Lua API 接口开发
OpenResty 为开发者提供了一系列强大的API,这些API使得Lua脚本能够与Nginx紧密交互,从而高效地执行多种Web服务器任务。在处理Web服务器的核心工作流程中,主要包括三个环节:接收请求、处理请求以及输出响应。在接收请求时,我们能够获取到请求参数、请求头部以及请求体等关键信息。处理请求则涉及执行特定的Lua代码逻辑。至于输出响应,则需要设定响应状态码、自定义响应头部以及构造响应内容体。
Tinywan
2024/07/16
3840
OpenResty实战系列 | Nginx Lua API 接口开发
nginx lua api解读
标识response结束,ngx.eof()只是结束响应流的输出,中断HTTP连接,后面的代码逻辑还会继续在服务端执行
code4it
2018/09/17
3.2K0
nginx lua api解读
4 OpenResty & Lua 处理各类Http请求
测试有不同的结果,form-data数据是混乱的,x-www-form-urlencoded才是正常的!
收心
2022/08/24
1.9K0
4 OpenResty & Lua 处理各类Http请求
nginx日志模块源码分析
请求在处理结束时,会按请求路径的配置上下文记访问日志。 如果在请求处理期间产生了内部跳转(参考另一篇nginx跳转讲述), 请求结束时的路径可能不同于原始的请求路径。
stan1ey
2021/06/07
1.6K0
nginx日志模块源码分析
nginx嵌入lua 解析get和post请求
nginx.conf文件 worker_processes 1; error_log logs/error.log; events { worker_connections 1024; }
友儿
2022/09/11
2K0
Nginx高级应用:lua + OpenResty
而对于首页这种,高访问,且 页面数据并不是,经常的变化! 为了减轻服务器的压力,直接将其制作成一个 静态的页面进行展示!
Java_慈祥
2024/08/06
3410
Nginx高级应用:lua + OpenResty
聊聊nginx的keepalive相关参数
nginx/src/http/ngx_http_header_filter_module.c
code4it
2023/12/04
9780
通过openresty+lua+nginx实现nginx缓存机制
OpenResty是一个基于Nginx的高性能Web应用服务器,它集成了Lua脚本语言,可以使用Lua编写Nginx模块,从而实现更多的高级功能。在本篇博客中,我们将介绍如何使用OpenResty和Lua来实现缓存机制。
司夜
2023/03/31
1.2K0
分布式--OpenResty+lua+Redis
前面我们已经使用了nginx,它拥有丰富的模块供我们使用,由于nginx是由c语言编写而成的,所以以前编写模块就必须使用c/c++,后来,有人将lua解释器继承到了nginx中,内建了ngx_lua模块,至此,nginx支持了lua
aruba
2022/06/30
7870
分布式--OpenResty+lua+Redis
相关推荐
Nginx(三):http模块的处理流程解析之正向代理
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验