一 获取、修改请求与响应的SDK
① 请求和响应梳理
回顾: 信息流的'脉络'
1) nginx接收'origin client'请求
备注: nginx' get 获取'请求信息
2) nginx作为'反向代理'角色对'origin client'请求进行加工,发送给'upstream上游'
备注: nginx' modify修改'发送给上游请求信息
3) nginx '接收'上游的响应
备注: 获取'响应'信息
4) nginx 通过'filter module'对上游的响应信息进行'加工',然后发送给'client'
备注: 修改'响应'信息
本篇讲解: 'ngx_lua_module' 提供的一些API --> 在'lua代码中'获取一些'请求'信息
思考: 哪些模块'默认'就require加载了,不需要在lua代码中'显示'加载?
强调: 每一个'API'能够出现的'context'和'阶段'是不一样的,重点关注一些'常用'的SDK
只是粗略讲解,后续会'深入'细节讲解 --> 案例专门的博客,然后'难点、易错'点详细罗列出来
② 读取、修改变量的SDK
关注点: 变量的'来源'
注意: 这些lua api '适用'的 context
区别: 这里'API'是在'lua代码'中,区别在nginx.conf 通过'配置指令' 设置和获取变量形式
'context'上下文特点:出现在'请求处理'的流程中,因为只有在请求处理的流程中才有请求信息
强调: ngx.var.VAR_NAME '不能'创建新变量,'VAR_NAME'是变量名
++++++++++++++ "分割线" ++++++++++++++
遗留: ngx.ctx和ngx.var '对比' --> '性能'、'优点'
ngx.var 是获取 nginx 的变量,类型是'字符串'或'nil',需要经历字符串 hash、hash 表查找等过程
ngx.ctx 仅仅是一个 'Lua table' 而已,它的'引用'存放在 ngx_lua 的模块上下文 'ctx_ref'
使用 ngx.ctx 比 ngx.var 往往是'更好'的选择
重点:
1、变量'未定义' --> openresty是'nil'
2、变量'未初始化' --> openresty是"空串"
③ lua_check_client_abort 客户端提前关闭连接
关注点: '偶现'还是'必显'
499错误的原因和处理策略 流量链路太长导致499 nginx 49x报错 识别499报错
前置条件: 是否'检查'客户端'提前'关闭连接,取决于lua_check_client_abort 指令
ngx_http_special_response.c 源码中'49x'定义的状态码
nginx '原生': error_page 499 '补获'
openresty '提供': 发生'499' ,callback 'lua 回调'函数
遗留: '模拟'客户端'提前'关闭连接
④ ngx.req.* 获取请求相关的信息
思考:'请求'相关的信息'有那些'呢? --> '拆解'看对应的'lua api'
- ngx.req.is_internal
- ngx.req.start_time
- ngx.req.http_version
- ngx.req.raw_header
- ngx.req.get_method
- ngx.req.set_method
- ngx.req.set_uri
- ngx.req.set_uri_args
- ngx.req.get_uri_args
- ngx.req.get_post_args
- ngx.req.get_headers
- ngx.req.set_header
- ngx.req.clear_header
- ngx.req.read_body
- ngx.req.discard_body
- ngx.req.get_body_data
- ngx.req.get_body_file
- ngx.req.set_body_data
- ngx.req.set_body_file
- ngx.req.init_body
- ngx.req.append_body
- ngx.req.finish_body
- ngx.req.socket
⑤ 获取请求头的SDK
ngx.req.raw_header ngx.req.get_headers
遗留: 多个'相同'的请求头呢?
⑥ 获取请求url的SDK
对比: 类比 '$request_uri' 中的信息,是否'解码'?
ngx.req.get_method ngx.req.http_version ngx.req.get_uri_args ngx.arg[index]
1、ngx.req.get_method
注意: 是'字符串'的形式,而'不是'枚举
2、ngx.req.http_version --> 1.1 还是 2.0
3、ngx.req.get_uri_args --> lua 'table'的方式
细节点:原始URI参数'只有key',没有value,则赋予其值为'true'
形如:https://www.wzj.com/?a
4、ngx.arg[index] --> 按照'索引号码'读取到请求中的'查询参数'
强调: 每一个'API'能够出现的'context'上下文是'不一样'的
⑦ 获取请求包体的SDK
需求: 如何获取'请求的body'?
说明: 一般'不需要',也'不能够',出于'安全和隐私'的角度
前置条件: lua_need_request_body '开启' --> '强制读取' request body
ngx.req.get_post_args ngx.req.read_body ngx.req.get_body_data ngx.req.get_body_file
⑧ HTTP请求方法名常量
⑨ 修改请求信息的SDK
注意: 当修改'转发给上游'的'请求方法时候',要使用上面的'枚举'方法
ngx.req.set_method ngx.req.set_header ngx.req.clear_header ngx.req.set_uri_args
1、set_header --> 修改'某个'请求头
思考:修改'所有'相同的请求头还是'其中一个' --> value 为'nil',则'删除所有'
clear_header --> 专门'删除请求'头部
⑩ 修改请求包体的SDK 了解
ngx.req.discard_body ngx.req.set_body_data ngx.req.init_body ngx.req.append_body
⑪ 修改URL并跳转的SDK
ngx.req.is_internal ngx.req.set_uri ngx.exec ngx.redirect
1、is_internal是否是'内部跳转'过来的请求
2、set(uri,jump)
1) jump默认是'flase'只是'修改'$uri
2) 如果是'true'则是修改并'跳转'
3、 exec --> 明确'修改uri',并进行'内部跳转'
⑫ 响应状态码常量
openresty搞了一个'枚举',叫作HTTP的'响应状态码' --> '不是'直接的200、301这种形式
⑭ 读取、修改响应状态码
ngx.status --> '读取'和'修改'响应状态码
⑮ 修改发送响应的头部
1、ngx.header.HEADER 和ngx.header['HEADER'] --> '两种'方式
备注: 增、删、改、查
默认是'自动'的 --> 我们写的是Content-Length,openresty会将其'修改成'content_length的
⑯ 发送响应的SDK
⑰ 请求响应类指令
遗留:nginx.conf中'自定义'default_type,然后lua代码中看'是否'使用默认的default_type
⑱ 发送响应的SDK
1、print --> ngx.flush(true)'不会卡住'nginx的事件驱动的框架,而是卡住这段lua代码
2、say --> 常用,会'换行'
3、exit
4、eof --> 主要是针对'chunk'编码
LBM --> 'LB 管理平台'
遗留: 相同的功能'nginx'和'openresty'都能满足,该如何'取舍'?
观点:nginx原生'不支持'的或者支持'很复杂'的,但openresty实现很'简单'的能力