一 概述
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 特性将被关闭。