openresty ngx.ctx请求上下文


openresty ngx.ctx请求上下文

         

官网:https://github.com/openresty/lua-nginx-module#ngxctx

        

             

                                     

请求上下文

          

ngx.ctx:请求上下文

# 语法格式
ngx.ctx.name = value
ngx.ctx = { foo = 32, bar = 54 }

环境:init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, 
     content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, 
     ngx.timer.*, balancer_by_lua*, exit_worker_by_lua*

This table can be used to store per-request Lua context data and has a 
life time identical to the current request (as with the Nginx variables)
* ngx.ctx是个表结构,用来存储每个请求的上下文
* 请求结束后,table存储的数据清空

            

ngx_lua 执行顺序

               

       

正常请求

ngx.ctx.foo entry persists across the rewrite, access, and content 
phases of a request
* ngx.ctx在rewrite、access、content等阶段都会存储请求的上下文

 location /test {
     rewrite_by_lua_block {
         ngx.ctx.foo = 76
     }
     access_by_lua_block {
         ngx.ctx.foo = ngx.ctx.foo + 3
     }
     content_by_lua_block {
         ngx.say(ngx.ctx.foo)
     }
 }

==> 输出:79

                

子请求

Every request, including subrequests, has its own copy of the table
* 每个请求,包括子请求,都会有自己的请求上下文,互不影响

modification of the ngx.ctx.blah entry in the subrequest does not 
affect the one in the parent request. This is because they have 
two separate versions of ngx.ctx.blah
* 修改子请求的值,不会影响主请求的上下文


 location /sub {
     content_by_lua_block {
         ngx.say("sub pre: ", ngx.ctx.blah)
         ngx.ctx.blah = 32
         ngx.say("sub post: ", ngx.ctx.blah)
     }
 }

 location /main {
     content_by_lua_block {
         ngx.ctx.blah = 73
         ngx.say("main pre: ", ngx.ctx.blah)
         local res = ngx.location.capture("/sub")
         ngx.print(res.body)
         ngx.say("main post: ", ngx.ctx.blah)
     }
 }


==> 

 main pre: 73
 sub pre: nil
 sub post: 32
 main post: 73

        

重定向

Internal redirects (triggered by nginx configuration directives 
like error_page, try_files, index and etc) will destroy the 
original request ngx.ctx data (if any) and the new request will 
have an empty ngx.ctx table
* 内部重定向会破坏请求的上下文,
* 重定向后,生成新的请求,上下文为空


 location /new {
     content_by_lua_block {
         ngx.say(ngx.ctx.foo)
     }
 }

 location /orig {
     content_by_lua_block {
         ngx.ctx.foo = "hello"
         ngx.exec("/new")
     }
 }

==> 输出:nil

       

ssl 安全连接

Because HTTP request is created after SSL handshake, the ngx.ctx created 
in ssl_certificate_by_lua*, ssl_session_store_by_lua*, 
ssl_session_fetch_by_lua* and ssl_client_hello_by_lua* is not available 
in the following phases like rewrite_by_lua*
* http请求是在ssl连接之后创建,在ssl_certificate_by_lua*、ssl_session_store_by_lua*、
* ssl_session_fetch_by_lua* 、ssl_client_hello_by_lua*中
* 设置的ngx.ctx不会被后续的执行阶段读取

        

生成新的请求上下文

Overriding ngx.ctx with a new Lua table is also supported
* 可是使用心得lua table覆盖原来的请求上下文

 ngx.ctx = { foo = 32, bar = 54 }

使用注意

When being used in the context of init_worker_by_lua*, this table just 
has the same lifetime of the current Lua handler.
* ngx.ctx在init_worker_by_lua*创建时,生命周期和当前的lua handler相同

The ngx.ctx lookup requires relatively expensive metamethod calls and 
it is much slower than explicitly passing per-request data along by your 
own function arguments. So do not abuse this API for saving your own 
function arguments because it usually has quite some performance impact
* 和函数传递数据相比,ngx.ctx数据传递很耗性能

           

不要用local修饰ngx.ctx

Because of the metamethod magic, never "local" the ngx.ctx table 
outside your Lua function scope on the Lua module level due to 
worker-level data sharing
* 由于worker级别的数据共享,不要用local修饰ngx.ctx


 -- mymodule.lua
 local _M = {}

 -- the following line is bad since ngx.ctx is a per-request
 -- data while this <code>ctx</code> variable is on the Lua module level
 -- and thus is per-nginx-worker.
 local ctx = ngx.ctx

 function _M.main()
     ctx.foo = "bar"
 end

 return _M

==>

 -- mymodule.lua
 local _M = {}

 function _M.main(ctx)
     ctx.foo = "bar"
 end

 return _M

        

                   

                                     

使用示例

          

default.conf

server {
    listen       80;
    server_name  localhost;

    location / {
        root   /usr/local/openresty/nginx/html;
        index  index.html index.htm;
    }

    location /test {
        rewrite_by_lua_block {
            ngx.ctx.name = '瓜田李下';
            ngx.ctx.age = 20;
        }

        access_by_lua_block {
            ngx.ctx.age = ngx.ctx.age + 1;
        }

        content_by_lua_block {
            ngx.say("content name ==> ", ngx.ctx.name);
            ngx.say("content age ==> ", ngx.ctx.age);

            ngx.ctx.age = ngx.ctx.age + 1;
            ngx.say("content age ==> ", ngx.ctx.age);
        }

        header_filter_by_lua_block {
            ngx.header.age = ngx.ctx.age
        }
    }

    location /main {
        rewrite_by_lua_block {
            ngx.ctx.name = '瓜田李下';
            ngx.ctx.age = 20;
        }

        content_by_lua_block {
            ngx.say("主请求 name ==> ", ngx.ctx.name);

            local res = ngx.location.capture("/sub");
            ngx.print(res.body);
        }

        header_filter_by_lua_block {
            ngx.header.age ="主请求 " .. ngx.ctx.age
        }
    }

    location /sub {
        rewrite_by_lua_block {
            ngx.ctx.name = '海贼王';
            ngx.ctx.age = 21;
        }

        content_by_lua_block {
            ngx.say("子请求 name ==> ", ngx.ctx.name);
        }

        header_filter_by_lua_block {
            ngx.header.age = ngx.ctx.age
        }
    }

    location /redirect {
        rewrite_by_lua_block {
            ngx.ctx.name = '瓜田李下';
            ngx.ctx.age = 20;
        }

        content_by_lua_block {
            ngx.exec("/new");
        }

        header_filter_by_lua_block {
            ngx.header.redirect_age ="redirect " .. ngx.ctx.age
        }
    }

    location /new {
        rewrite_by_lua_block {
            ngx.ctx.name = '海贼王';
            ngx.ctx.age = 21;
        }

        content_by_lua_block {
            ngx.say("new name ==> ", ngx.ctx.name);
        }

        header_filter_by_lua_block {
            ngx.header.new_age = "new " .. ngx.ctx.age
        }
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/local/openresty/nginx/html;
    }

}

       

创建容器

docker run -it -d --net fixed --ip 172.18.0.100 -p 4000:80 \
-v /Users/huli/lua/openresty/cache/default.conf:/etc/nginx/conf.d/default.conf \
--name open5 lihu12344/openresty

       

使用测试

# 正常请求执行流程
huli@hudeMacBook-Pro cache % curl -i localhost:4000/test    
HTTP/1.1 200 OK
Server: openresty/1.21.4.1
Date: Thu, 21 Jul 2022 05:03:01 GMT
Content-Type: application/octet-stream
Transfer-Encoding: chunked
Connection: keep-alive
age: 21     --content修改的age不会对header_filter_by_lua_block产生影响

content name ==> 瓜田李下
content age ==> 21
content age ==> 22


# 子请求执行:子请求创建新的请求上下文
huli@hudeMacBook-Pro cache % curl -i localhost:4000/main
HTTP/1.1 200 OK
Server: openresty/1.21.4.1
Date: Thu, 21 Jul 2022 05:03:05 GMT
Content-Type: application/octet-stream
Transfer-Encoding: chunked
Connection: keep-alive
age: 主请求 20

主请求 name ==> 瓜田李下
子请求 name ==> 海贼王


# 重定向请求:子请求创建新的请求上下文
huli@hudeMacBook-Pro cache % curl -i localhost:4000/redirect
HTTP/1.1 200 OK
Server: openresty/1.21.4.1
Date: Thu, 21 Jul 2022 05:03:09 GMT
Content-Type: application/octet-stream
Transfer-Encoding: chunked
Connection: keep-alive
age: new 21

new name ==> 海贼王

         

                 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值