【精选】Nginx模块Lua-Nginx-Module学习笔记(一)Nginx Lua API 接口详解

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 源码地址:https://github.com/Tinywan/Lua-Nginx-Redis一、介绍  各种* _by_lua,* _by_lua_block和* _by_lua_file配置指令用作nginx.conf文件中Lua API的网关。

源码地址:https://github.com/Tinywan/Lua-Nginx-Redis

一、介绍

  各种* _by_lua,* _by_lua_block和* _by_lua_file配置指令用作nginx.conf文件中Lua API的网关。 下面描述的Nginx Lua API只能在这些配置指令的上下文中运行的用户Lua代码中调用。API以两个标准软件包ngx和ndk的形式暴露给Lua。 这些软件包位于ngx_lua中的默认全局范围内,并且始终可在ngx_lua指令中使用。

这些包可以像这样引入外部Lua模块:

 local say = ngx.say
 local _M = {}
 function _M.foo(a)
     say(a)
 end
 return _M

强烈建议使用package.seeall标志,因为其各种不良的副作用。也可以直接要求外部Lua模块中的包:

  local ngx = require“ngx”
  local ndk = require“ndk”

  v0.2.1rc19版本中引入了需要这些软件包的能力。

  用户代码中的网络I / O操作应该只通过Nginx Lua API调用来完成,因为Nginx事件循环可能被阻塞,否则性能会明显下降。 磁盘操作与相对少量的数据可以使用标准的Lua io库,但巨大的文件读写应尽可能避免,因为他们可能会显着阻止Nginx进程。 强烈建议将所有网络和磁盘I / O操作委派给Nginx的子请求(通过ngx.location.capture方法等),以获得最佳性能。

二、命令介绍

ngx.arg

语法:val = ngx.arg [index]

上下文:set_by_lua *,body_filter_by_lua *

描述:当在set_by_lua *指令的上下文中使用时,此表是只读的,并保存config指令的输入参数:

value = ngx.arg[n]

这里是一个例子

   location /foo_sum {
                 set $a 32;
                 set $b 56;
                 set_by_lua $sum
                        'return tonumber(ngx.arg[1]) + tonumber(ngx.arg[2])'
                 $a $b;
                 echo "sum = ${sum}";
        }

CURL 运行输出

root@iZ236j3sofdZ:/usr/local/nginx/conf/lua# curl "http://localhost/foo_sum"
sum = 88

写出88,32和56的和。

  当在body_filter_by_lua *的上下文中使用此表时,第一个元素将输入数据块保存到输出过滤器代码,第二个元素保存指示整个输出数据流结束的“eof”标志的布尔标志。

  传递给下游Nginx输出过滤器的数据块和“eof”标志也可以通过将值直接分配给相应的表元素来覆盖。 当将nil或空Lua字符串值设置为ngx.arg [1]时,根本不会将数据块传递到下游Nginx输出过滤器。

ngx.null

  ngx.null常量是一个NULL light用户数据,通常用于在Lua表等中表示nil值,类似于lua-cjson库的cjson.null常量。 这个常数首先在v0.5.0rc5版本中引入。

ngx.var.VARIABLE 

语法:ngx.var.VAR_NAME

上下文:set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*

读取和写入Nginx变量值

 value = ngx.var.some_nginx_variable_name
 ngx.var.some_nginx_variable_name = value

注意,只有已经定义的nginx变量可以写入。 例如:

location /foo {
     set $my_var ''; # this line is required to create $my_var at config time
     content_by_lua_block {
         ngx.var.my_var = 123;
         ...
     }
 }

  也就是说,nginx变量不能在运行中创建。一些特殊的nginx变量,如$ args和$ limit_rate可以分配一个值,许多其他变量不是,如$ query_string,$ arg_PARAMETER和$ http_NAME。通过写入ngx.var [1],ngx.var [2],ngx.var [3]等,也可以通过此接口读取Nginx正则表达式组捕获变量$ 1,$ 2,$ 3等。将ngx.var.Foo设置为nil值将取消设置$ Foo Nginx变量。

ngx.var.args = nil

  小心当从Nginx变量读取时,Nginx将在每个请求的内存池中分配内存,只有在请求终止时才释放内存。 因此,当您需要在Lua代码中重复读取Nginx变量时,将Nginx变量值缓存到您自己的Lua变量中,例如:

local val = ngx.var.some_var
 --- use the val repeatedly later

  以防止(临时)内存在当前请求的生存期内泄漏。 缓存结果的另一种方法是使用ngx.ctx表。未定义的NGINX变量评估为nil,而未初始化(但已定义)的NGINX变量将被评估为空的Lua字符串。此API需要相对昂贵的元方法调用,建议避免在热代码路径上使用它。

Core constants

上下文: init_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*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*

   ngx.OK (0)
   ngx.ERROR (-1)
   ngx.AGAIN (-2)
   ngx.DONE (-4)
   ngx.DECLINED (-5)

请注意,只有三个这些常数是由所利用的Nginx API为lua(即ngx.exit接受NGX_OKNGX_ERRORNGX_DECLINED作为输入)。

ngx.null

ngx.null常数是一个NULL通常用来表示在Lua表等零值光用户数据和类似于LUA-cjson库的cjson.null常数。此常数最早在引入的v0.5.0rc5释放。

待续.........

HTTP方法常量

上下文: init_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,ssl_certificate_by_lua *,* ssl_session_fetch_by_lua,ssl_session_store_by_lua *。

  ngx.HTTP_GET
  ngx.HTTP_HEAD
  ngx.HTTP_PUT
  ngx.HTTP_POST
  ngx.HTTP_DELETE
  ngx.HTTP_OPTIONS   (added in the v0.5.0rc24 release)
  ngx.HTTP_MKCOL     (added in the v0.8.2 release)
  ngx.HTTP_COPY      (added in the v0.8.2 release)
  ngx.HTTP_MOVE      (added in the v0.8.2 release)
  ngx.HTTP_PROPFIND  (added in the v0.8.2 release)
  ngx.HTTP_PROPPATCH (added in the v0.8.2 release)
  ngx.HTTP_LOCK      (added in the v0.8.2 release)
  ngx.HTTP_UNLOCK    (added in the v0.8.2 release)
  ngx.HTTP_PATCH     (added in the v0.8.2 release)
  ngx.HTTP_TRACE     (added in the v0.8.2 release)

这些常数通常在使用ngx.location.capturengx.location.capture_multi方法调用。

 

HTTP状态常数

上下文: init_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,ssl_certificate_by_lua *,* ssl_session_fetch_by_lua,ssl_session_store_by_lua *。

   value = ngx.HTTP_CONTINUE (100) (first added in the v0.9.20 release)
   value = ngx.HTTP_SWITCHING_PROTOCOLS (101) (first added in the v0.9.20 release)
   value = ngx.HTTP_OK (200)
   value = ngx.HTTP_CREATED (201)
   value = ngx.HTTP_ACCEPTED (202) (first added in the v0.9.20 release)
   value = ngx.HTTP_NO_CONTENT (204) (first added in the v0.9.20 release)
   value = ngx.HTTP_PARTIAL_CONTENT (206) (first added in the v0.9.20 release)
   value = ngx.HTTP_SPECIAL_RESPONSE (300)
   value = ngx.HTTP_MOVED_PERMANENTLY (301)
   value = ngx.HTTP_MOVED_TEMPORARILY (302)
   value = ngx.HTTP_SEE_OTHER (303)
   value = ngx.HTTP_NOT_MODIFIED (304)
   value = ngx.HTTP_TEMPORARY_REDIRECT (307) (first added in the v0.9.20 release)
   value = ngx.HTTP_BAD_REQUEST (400)
   value = ngx.HTTP_UNAUTHORIZED (401)
   value = ngx.HTTP_PAYMENT_REQUIRED (402) (first added in the v0.9.20 release)
   value = ngx.HTTP_FORBIDDEN (403)
   value = ngx.HTTP_NOT_FOUND (404)
   value = ngx.HTTP_NOT_ALLOWED (405)
   value = ngx.HTTP_NOT_ACCEPTABLE (406) (first added in the v0.9.20 release)
   value = ngx.HTTP_REQUEST_TIMEOUT (408) (first added in the v0.9.20 release)
   value = ngx.HTTP_CONFLICT (409) (first added in the v0.9.20 release)
   value = ngx.HTTP_GONE (410)
   value = ngx.HTTP_UPGRADE_REQUIRED (426) (first added in the v0.9.20 release)
   value = ngx.HTTP_TOO_MANY_REQUESTS (429) (first added in the v0.9.20 release)
   value = ngx.HTTP_CLOSE (444) (first added in the v0.9.20 release)
   value = ngx.HTTP_ILLEGAL (451) (first added in the v0.9.20 release)
   value = ngx.HTTP_INTERNAL_SERVER_ERROR (500)
   value = ngx.HTTP_METHOD_NOT_IMPLEMENTED (501)
   value = ngx.HTTP_BAD_GATEWAY (502) (first added in the v0.9.20 release)
   value = ngx.HTTP_SERVICE_UNAVAILABLE (503)
   value = ngx.HTTP_GATEWAY_TIMEOUT (504) (first added in the v0.3.1rc38 release)
   value = ngx.HTTP_VERSION_NOT_SUPPORTED (505) (first added in the v0.9.20 release)
   value = ngx.HTTP_INSUFFICIENT_STORAGE (507) (first added in the v0.9.20 release)

Nginx的日志级别常数

上下文: init_by_lua *,* 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 *,* ssl_certificate_by_lua,ssl_session_fetch_by_lua *,* ssl_session_store_by_lua。

   ngx.STDERR
   ngx.EMERG
   ngx.ALERT
   ngx.CRIT
   ngx.ERR
   ngx.WARN
   ngx.NOTICE
   ngx.INFO
   ngx.DEBUG

print

语法: print(...)

上下文: init_by_lua*, 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*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*

写参数值到nginx的error.log与文件ngx.NOTICE日志级别。它相当于

ngx.log(ngx.NOTICE, ...)

Lua的nil参数被接受,并导致文字"nil"字符串,而Lua的布尔导致文字"true""false"字符串。和ngx.null常数将产生"null"串输出。

  有一个硬编码2048在Nginx的核心错误信息的长度字节的限制。此限制包括尾随换行符和领先的时间戳。如果邮件的大小超出此限制,Nginx的将相应截断消息文本。这个限制可以通过编辑手动修改NGX_MAX_ERROR_STR的宏定义src/core/ngx_log.h在Nginx的源代码树文件。

ngx.ctx

上下文: 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*

这个表可以被用来存储每个请求的Lua上下文数据,并具有使用寿命相同当前请求(与Nginx的变量)。考虑下面的例子,

 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)
     }
 }

然后GET /test将产生的输出:79

即,ngx.ctx.foo条目横跨重写,访问和请求的内容相存在。每一项要求,其中包括子请求,有它自己的表的副本。例如:

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)
     }
 }

然后GET /main会给输出:

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

在此,改性ngx.ctx.blah的子请求条目不会影响所述一个在父请求。这是因为他们有两个独立的版本ngx.ctx.blah。内部重定向会破坏原来的请求ngx.ctx数据(如果有的话)和新要求将有一个空ngx.ctx表。例如:

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

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

然后GET /orig会给:nil

而不是原来的"hello"值。任意的数据值,包括Lua的关闭和嵌套表,可以插入到这个“神奇”的表。它还允许自定义元方法的注册。覆盖ngx.ctx用一个新的Lua表也支持,例如:

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

当在上下文中使用init_worker_by_lua *,此表只是有当前的Lua处理程序的寿命相同。

  在ngx.ctx查找需要相对昂贵元方法的调用,这是不是明确传递每个请求的数据沿着自己的函数参数慢得多。所以,不要滥用这个API保存你自己的函数的参数,因为它通常具有颇有些性能的影响。因为魔元方法的,从来没有“本地”的ngx.ctx上由于Lua的模块级的Lua的功能范围之外的表工作者级的数据共享例如,以下是坏:

-- 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

也就是说,让调用者通过ctx表明确地通过一个函数的参数。

 

ngx.location.capture

语法: res = ngx.location.capture(uri, options?)

上下文: rewrite_by_lua *,* access_by_lua,content_by_lua *

是一个同步非阻塞的NGINX子请求uri

NGINX的子请求提供了一个非常强大的方式去实现非阻塞的内部请求,或者其他的C模块,比如 ngx_proxy, ngx_fastcgi, ngx_memc, ngx_postgres, ngx_drizzle, 甚至ngx_lua自己等等。

当然,这些子请求仅仅是模拟HTTP请求,但是并没有额外的 HTTP/TCP,所有的进程都是C级别的

子请求完全不同与HTTP 301/302。

这里有个基本的例子:

res = ngx.location.capture(uri)

返回与4插槽,一个Lua表:res.statusres.headerres.body,和res.truncated

res.status 用于保存子请求响应的响应状态代码。

res.header持有子请求的响应头,这是一个正常的Lua表。对于多值响应头,该值是保存所有的顺序它们出现的值的Lua(阵列)表。例如,如果子请求响应报头包含以下几行:

返回一个LUA的TABLE,三个值(res.status, res.header, and res.body)。

res.header包含了所有的子请求的头的信息,它是一个普通的LUA TABLE。比如多个值的相应头,他们以数组的形式按照顺序返回出现。例如:子请求包含了如下信息:

 Set-Cookie: a=3
 Set-Cookie: foo=bar
 Set-Cookie: baz=blah

然后res.header["Set-Cookie"]将被评估,以表中的值 {"a=3", "foo=bar", "baz=blah"}

  res.body持有子请求的响应体数据,这些数据可能会被截断。你总是需要检查res.truncated布尔标志,看是否res.body包含截断数据。这里的数据截断只能由那些不可恢复的错误在你的子请求一样,远端中止在响应体数据流的中间,或当你的子请求接收从响应体数据的读取超时发生过早的连接的情况下造成的遥控器。URI查询串可以串联到的URI本身,例如:

res = ngx.location.capture('/foo/bar?a=3&b=4')

像名为位置@foo不允许由于nginx的核心的限制。使用与组合正常位置internal指令准备仅供内部使用的位置。

可选选项表可以喂的第二个参数,它支持的选项:

  • method 指定子请求的请求方法,只接受常量一样ngx.HTTP_POST
  • body 指定子请求的请求体(仅字符串值)。
  • args 指定子请求的URI查询参数(这两个字符串值和Lua表被接受)
  • ctx 指定一个Lua表是ngx.ctx为子请求表。它可以是当前请求的ngx.ctx表,这有效地使母体和其子请求共享完全相同的上下文表。此选项最初是在引进v0.3.1rc25发行。
  • vars 采取持有的值设置指定的Nginx变量在子请求作为此选项的值一个Lua表。此选项最初是在引进v0.3.1rc31发行。
  • copy_all_vars 指定是否在当前请求所讨论的子请求的所有的Nginx变量值复制。在子请求nginx的变量的修改将不会影响当前(父)的请求。此选项最初是在引进v0.3.1rc31发行。
  • share_all_vars 指定是否共享的子请求与当前(父)要求所有的Nginx变量。在子请求Nginx的变量的修改将影响当前(父)的请求。启用此选项可能会导致因不良副作用难以调试问题,被认为是不好的,有害的。只有启用该选项,当你完全知道自己在做什么。
  • always_forward_body 当设置为true,当前(父)的请求的请求体总是会被转发到,如果创建的子请求body未指定选项。无论是通过读取请求体()ngx.req.read_bodylua_need_request_body上会被直接转发到子请求不创建子请求(无论请求体数据在内存中缓存或临时文件缓存)时复制整个请求体数据。默认情况下,这个选项是false和时body没有指定选项时,当前的(父)请求的请求体,当子请求取只转发PUTPOST请求方法。

发出一个POST子请求,例如,可以做如下:

 res = ngx.location.capture(
     '/foo/bar',
     { method = ngx.HTTP_POST, body = 'hello, world' }
 )

看到比其他POST HTTP方法的常量方法。该method选项是ngx.HTTP_GET默认。

args选项可以指定额外的URI参数,例如:

 ngx.location.capture('/foo?a=1',
     { args = { b = 3, c = ':' } }
 )

相当于

ngx.location.capture('/foo?a=1&b=3&c=%3a')

也就是说,该方法将根据规则URI参数逃脱键和值一起将它们连接起来成为一个完整的查询字符串。对于作为通过的Lua表的格式args参数是相同于使用的格式ngx.encode_args方法。该args选项也可以采取简单的查询字符串:

 ngx.location.capture('/foo?a=1',
     { args = 'b=3&c=%3a' } }
 )

这在功能上等同于前面的例子。

share_all_vars选项控制是否将当前请求和子请求之间共享nginx的变量。如果此选项设置为true,那么当前请求和相关的子请求将共享相同的Nginx变量的作用域。因此,通过一个子请求更改了Nginx的变量将影响到当前的请求。

应小心使用此选项,变量的作用域共享可以有意想不到的副作用。argsvarscopy_all_vars选项通常优于代替。这个选项被设置为false默认

location /other {
     set $dog "$dog world";
     echo "$uri dog: $dog";
 }

 location /lua {
     set $dog 'hello';
     content_by_lua_block {
         res = ngx.location.capture("/other",
             { share_all_vars = true });

         ngx.print(res.body)
         ngx.say(ngx.var.uri, ": ", ngx.var.dog)
     }
 }

访问位置/lua给:

/other dog: hello world
/lua: hello world

copy_all_vars选项提供父请求的Nginx的变量的副本子请求时这样子请求发出。由这样子请求对这些变量所做的更改不会影响父请求或任何其他子请求共享父请求的变量。

 location /other {
     set $dog "$dog world";
     echo "$uri dog: $dog";
 }

 location /lua {
     set $dog 'hello';
     content_by_lua_block {
         res = ngx.location.capture("/other",
             { copy_all_vars = true });

         ngx.print(res.body)
         ngx.say(ngx.var.uri, ": ", ngx.var.dog)
     }
 }

请求GET /lua将给输出

/other dog: hello world
/lua: hello

请注意,如果两者share_all_varscopy_all_vars都设置为true,则share_all_vars优先。

除了上述两个设置,有可能使用在子请求变量的值vars选项。这些变量的变量共享或复制已评估后设置,并且提供了对编码它们以URL参数,并在Nginx的配置文件反向转义它们传递特定值应用于一个子请求的更有效的方法:

 location /other {
     content_by_lua_block {
         ngx.say("dog = ", ngx.var.dog)
         ngx.say("cat = ", ngx.var.cat)
     }
 }

 location /lua {
     set $dog '';
     set $cat '';
     content_by_lua_block {
         res = ngx.location.capture("/other",
             { vars = { dog = "hello", cat = 32 }});

         ngx.print(res.body)
     }
 }

访问/lua将产生的输出:

dog = hello
cat = 32

ctx选项可用于指定自定义的Lua表作为ngx.ctx为子请求表。

 location /sub {
     content_by_lua_block {
         ngx.ctx.foo = "bar";
     }
 }
 location /lua {
     content_by_lua_block {
         local ctx = {}
         res = ngx.location.capture("/sub", { ctx = ctx })

         ngx.say(ctx.foo);
         ngx.say(ngx.ctx.foo);
     }
 }

然后请求GET /lua 输出:

bar
nil

另外,也可以使用这个ctx选项共享同一ngx.ctx电流(父)请求和子请求之间的表:

 location /sub {
     content_by_lua_block {
         ngx.ctx.foo = "bar";
     }
 }
 location /lua {
     content_by_lua_block {
         res = ngx.location.capture("/sub", { ctx = ngx.ctx })
         ngx.say(ngx.ctx.foo);
     }
 }

请求GET /lua产生的输出:bar

  注意,通过发出子请求ngx.location.capture默认继承当前请求的所有请求头,而这可能对子请求响应意想不到的副作用。例如,使用标准时,ngx_proxy模块服务子请求,“接受编码:gzip”中的主要请求头,可能会导致不能在Lua代码正确处理gzip压缩的响应。原始请求头,应通过设置被忽略 proxy_pass_request_headersoff的子请求的位置。

如果body没有指定选项,且always_forward_body选项为false(默认值),POST以及PUT子请求将继承父请求(如果有的话)的请求主体。

  上有可能为每一个主要请求并发子请求的数目的硬编码上限。在旧版本Nginx的,下限为50并行子请求,并在最近的版本中,Nginx的1.1.x开始,这是提高到200并发子请求。当超过此限制时,以下错误消息被添加到error.log文件中:

[error] 13983#0: *1 subrequests cycle while processing "/uri"

  极限可以根据需要通过编辑的定义手动修改NGX_HTTP_MAX_SUBREQUESTS宏中nginx/src/http/ngx_http_request.h在Nginx的源树文件。请同时参阅限制捕获由配置位置的其他模块的子请求指示

 

ngx.location.capture_multi

ngx.status

ngx.header.HEADER

ngx.resp.get_headers

 

ngx.req.is_internal

 

ngx.req.start_time

语法: secs = ngx.req.start_time()

上下文: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*

返回表示时间戳(包括毫秒作为小数部分)已创建当前请求时一个浮点数。下面的例子模拟了$request_time变量值(由提供ngx_http_log_module纯LUA):

 local request_time = ngx.now() - ngx.req.start_time()

ngx.req.http_version

语法:  num = ngx.req.http_version()

背景: set_by_lua *,* rewrite_by_lua,access_by_lua *,* content_by_lua,header_filter_by_lua *

返回当前请求作为Lua的数字的HTTP版本号。

当前可能的值是2.0,1.0,1.1和0.9。返回nil了无法识别的值。

ngx.req.raw_header

语法:  str = ngx.req.raw_header(no_request_line?)

背景: set_by_lua *,* rewrite_by_lua,access_by_lua *,* content_by_lua,header_filter_by_lua *

返回由Nginx的服务器接收到的原始原始的HTTP协议头。

默认情况下,请求行和尾随CR LF终止也将包括在内。例如,

 ngx.print(ngx.req.raw_header())

给出这样的事情:

GET /t HTTP/1.1
Host: localhost
Connection: close
Foo: bar

你可以指定可选的 no_request_line参数作为true排除从结果的请求行的值。例如

ngx.print(ngx.req.raw_header(true))

输出是这样的:

Host: localhost
Connection: close
Foo: bar

此方法不会在HTTP / 2请求工作尚未

 



CDN 反向代理LiveNode节点,通过Lua脚本操作Redis数据库实现转发



URL访问地址:http://127.0.0.1/hls/4953.m3u8

nginx.conf 配置

     location ~ \/.+\/.+\.(m3u8|ts) {
                #设置nginx变量
                if ($uri ~ \/([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)(|-).*\.(m3u8|ts)) {
                        set $app_name $1;
                        set $a $2;
                }
                set $stream_id "";
                default_type 'text/html';
                lua_code_cache on;
                rewrite_by_lua_file  /home/www/lua-tinywan/set_by_file.lua;
                #echo "stream_id :" $stream_id;
                proxy_buffering             off;
                proxy_redirect              off;
                proxy_connect_timeout       10;
                proxy_send_timeout          30;
                proxy_read_timeout          30;
                proxy_pass                  $stream_id;
        }
set_by_file.lua 添加一下内容:
-- 接受Nginx传递进来的参数$1 也就是SteamName
local stream_a = ngx.var.a

local redis = require("resty.redis");
-- 创建一个redis对象实例。在失败,返回nil和描述错误的字符串的情况下
local redis_instance = redis:new();
--设置后续操作的超时(以毫秒为单位)保护,包括connect方法
redis_instance:set_timeout(1000)
--建立连接
local ip = '127.0.0.1'
local port = 6379
--尝试连接到redis服务器正在侦听的远程主机和端口
local ok,err = redis_instance:connect(ip,port)
if not ok then
        ngx.say("connect redis error : ",err)
        return err
end

-- 权限验证
local res,err = redis_instance:auth('tinywanredis')
if not res then
    ngx.say("failed to authenticate: ", err)
    return
end

--数据库选择 
redis_instance:select(2)

--调用API获取数据  
local resp, err = redis_instance:hget("StreamLiveNodeInnerIp:"..stream_a,'livenode')
if not resp then
    ngx.say("get msg error : ", err)
    return err
end

--得到的数据为空处理  
if resp == ngx.null then
    ngx.say("this is not redis_data")
    return nil
end
ngx.var.stream_id = resp
-- ngx.say("reds get result : ", resp)

 思路图片:

 

 

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
7天前
|
人工智能 自然语言处理 API
Multimodal Live API:谷歌推出新的 AI 接口,支持多模态交互和低延迟实时互动
谷歌推出的Multimodal Live API是一个支持多模态交互、低延迟实时互动的AI接口,能够处理文本、音频和视频输入,提供自然流畅的对话体验,适用于多种应用场景。
47 3
Multimodal Live API:谷歌推出新的 AI 接口,支持多模态交互和低延迟实时互动
|
2天前
|
前端开发 API 数据库
Next 编写接口api
Next 编写接口api
|
9天前
|
XML JSON 缓存
阿里巴巴商品详情数据接口(alibaba.item_get) 丨阿里巴巴 API 实时接口指南
阿里巴巴商品详情数据接口(alibaba.item_get)允许商家通过API获取商品的详细信息,包括标题、描述、价格、销量、评价等。主要参数为商品ID(num_iid),支持多种返回数据格式,如json、xml等,便于开发者根据需求选择。使用前需注册并获得App Key与App Secret,注意遵守使用规范。
|
8天前
|
JSON API 开发者
淘宝买家秀数据接口(taobao.item_review_show)丨淘宝 API 实时接口指南
淘宝买家秀数据接口(taobao.item_review_show)可获取买家上传的图片、视频、评论等“买家秀”内容,为潜在买家提供真实参考,帮助商家优化产品和营销策略。使用前需注册开发者账号,构建请求URL并发送GET请求,解析响应数据。调用时需遵守平台规定,保护用户隐私,确保内容真实性。
|
8天前
|
搜索推荐 数据挖掘 API
淘宝天猫商品评论数据接口丨淘宝 API 实时接口指南
淘宝天猫商品评论数据接口(Taobao.item_review)提供全面的评论信息,包括文字、图片、视频评论、评分、追评等,支持实时更新和高效筛选。用户可基于此接口进行数据分析,支持情感分析、用户画像构建等,同时确保数据使用的合规性和安全性。使用步骤包括注册开发者账号、创建应用获取 API 密钥、发送 API 请求并解析返回数据。适用于电商商家、市场分析人员和消费者。
|
18天前
|
JSON API 开发工具
淘宝实时 API 接口丨淘宝商品详情接口(Taobao.item_get)
淘宝商品详情接口(Taobao.item_get)允许开发者获取商品的详细信息,包括基本信息、描述、卖家资料、图片、属性及销售情况等。开发者需注册账号、创建应用并获取API密钥,通过构建请求获取JSON格式数据,注意遵守平台规则,合理使用接口,确保数据准确性和时效性。
|
19天前
|
JSON 安全 API
Python调用API接口的方法
Python调用API接口的方法
84 5
|
19天前
|
JSON 缓存 监控
淘宝商品详情接口(Taobao.item_get)丨淘宝API接口指南
淘宝商品详情接口(Taobao.item_get)允许开发者通过HTTP GET方法获取淘宝商品的详细信息,包括商品ID、价格、库存等。请求需包含key、secret、num_iid等必选参数,支持缓存及多种返回格式。此接口广泛应用于电商数据分析、商品选品、价格监控等领域,提升商家运营效率。
|
23天前
|
JSON 搜索推荐 API
LAZADA关键词搜索API接口的获取与应用
Lazada作为东南亚领先的电商平台,为满足开发者和商户需求,开放了关键词搜索API接口。本文详细介绍该接口的获取与应用,助力提升电商业务效率。接口支持关键词搜索、指定搜索范围和排序方式,提供精准、灵活且全面的数据支持,促进电商应用和服务的优化与创新。
24 3
|
1月前
|
JSON API 数据格式
淘宝 / 天猫官方商品 / 订单订单 API 接口丨商品上传接口对接步骤
要对接淘宝/天猫官方商品或订单API,需先注册淘宝开放平台账号,创建应用获取App Key和App Secret。之后,详细阅读API文档,了解接口功能及权限要求,编写认证、构建请求、发送请求和处理响应的代码。最后,在沙箱环境中测试与调试,确保API调用的正确性和稳定性。
下一篇
DataWorks