一 概述
output api
主要用于向客户端发送应答数据,或者对应答进行控制。输出函数:ngx.send_headers
、ngx.print
、ngx.say
;响应控制函数:ngx.flush
、ngx.eof
。
二 输出函数
1. ngx.send_headers
函数原型:
1 | ok, err = ngx.send_headers() |
允许介入的阶段:rewrite_by_lua_*
、access_by_lua_*
、content_by_lua_*
。
向客户端发送应答头。在发送响应时需要对 content type
、content length
进行特别关注,如果这两者错误会直接导致客户端解析异常。lua_nginx_module
会调用 ngx_http_lua_set_content_type
函数对 content type
进行特殊处理。在对 conten_type
进行特殊处理时最终会调用 ngx_http_set_content_type
函数,首先根据请求文件扩展名获得对于的 content type
,如果失败则使用默认 content type
设置。其实现如下:
1 | ngx_int_t |
对于 content_length
头,如果未设置过应答 header
(调用 ngx.resp.header['new_header'] = 'value'
函数),需要将 content_length
头清除,使用 chrunked
编码方式传输。
**调用 ngx.send_headers
后会进入 header filter
阶段,此函数的实际输出是调用 ngx_http_top_header_filter
**。
2. ngx.print
函数原型:
1 | ok, err = ngx.print(...) |
允许介入阶段:rewrite_by_lua_*
、access_by_lua_*
、content_by_lua_*
。
ngx.print
会调用 ngx_http_lua_ngx_echo
函数进行应答 ngx_http_top_body_filter
1 | static int |
3. ngx.say
函数原型:
1 | ok, err = ngx.say(...) |
与 ngx.print
功能相同,最终会调用 ngx_http_lua_ngx_echo
函数,只不过 ngx.say
调用时 newline
参数为 1
。
4. ngx.flush
函数原型:
1 | ok, err = ngx.flush(wait?) |
允许介入阶段:rewrite_by_lua_*
、access_by_lua_*
、content_by_lua_*
。
如果存在可选 wait
参数,并且值为 true
函数调用会等待发送结束或超时才返回(HTTP/1.0 buffing 未在此情况),否则立即返回。ngx.flush
实现函数 ngx_http_lua_ngx_flush
主要实现两个功能:body filter
链对应答数据进行处理、将应答数据发送出去,函数实现如下:
1 | static int |
在 ngx.print
、ngx.say
、ngx.flush
函数实现中都会调用 ngx_http_lua_send_chain_link
函数,用于将应答数据经过 header filter
、body filter
处理。
1 | // 将应答数据经过 body filter 处理 |
5. ngx.eof
函数原型:
1 | ok, err = ngx.eof() |
允许介入阶段:rewrite_by_lua_*
、access_by_lua_*
、content_by_lua_*
。
指示响应流结束,如果是 HTTP/1.1
版本 chunked
编码格式,将触发发送最后一个 chunk
。如果未启用 HTTP/1.1
的 keep-alive
特性,调用 ngx.eof
后客户端应该关闭连接。**ngx.eof
不会关闭连接,只会调用 header filter
、body filter
进行应答处理**。
在 ngx.eof
实现中同样会调用 ngx_http_lua_send_chain_link
。
三 HTTP/1.0 buffing
HTTP/1.0
不支持 chunked
编码,当响应 body
不为空时需要 content-length
头以便支持 HTTP/1.0
的 keep-alive
特性。因此当发起 HTTP/1.0
协议请求并且打开了 lua_http10_buffing
配置时,lua-nginx
模块会将 ngx.say
、ngx.print
的输出内容缓存(同时会将应答 header
延时发送),直到收到所有的应答 body
。此时,lua-nginx
模块就能计算出 content-length
并发送给客户端。如果在应答头中有 content-length
头,即使打开了 lua_http10_buffing
也不会缓存应答信息。
对于大的响应流,要注意关闭 lua_http10_buffing
指令,避免内存占用过高。
1. lua_http10_buffering
指令
1 | syntax: lua_http10_buffering on|off |
为 HTTP/1.0
(或更老的)请求启用或禁用自动响应缓存,这种缓冲机制主要用于低于 HTTP/1.0
版本的 keep-alive
特性,它依赖于正确的 content-length
响应头。
如果 lua
代码在发送响应头(通过调用 ngx.send_headers
、ngx.say
、ngx.print
触发发送响应头)之前已经显示的设置 content-length
头,http10_buffering
特性将被关闭。