一、如何通过openresty操作http头
http头分请求头和,响应头
在nginx的access_by_lua阶段操作请求头,操作请求头涉及两个函数。
1、ngx.req.get_headers,第一个参数请求头个数,默认分析100个头,防止恶意攻击,第二个参数默认将头域信息转为小写,如果设置为true会关闭掉。
2、ngx.req.set_headers对头的域信息作一些设置操作,并且可以设置为table
respnse header通常在header filter阶段操作响应头,可以通过ngx.header.*方法读取响应头信息,也可以重写头信息。
二、测试
2.1测试get_headers
1.conf/lua/request_header.json
local function print_table(t)
local function parse_array(key, tab)
local str = ''
for _, v in pairs(tab) do
str = str .. key .. ' ' .. v .. '\r\n'
end
return str
end
local str = ''
for k, v in pairs(t) do
if type(v) == "table" then
str = str .. parse_array(k, v)
else
str = str .. k .. ' ' .. v .. '\r\n'
end
end
return str
end
local headers = ngx.req.get_headers()
ngx.say(print_table(headers))
curl -H "Foo:bar" http://localhost:8080/request_header
2.修改request_header.json
local headers = ngx.req.get_headers(1)
nginx -s reload热加载后,请求request_header响应只有打印了一个header
3.修改request_header.json
local headers = ngx.req.get_headers(0, true)
nginx -s reload热加载后,请求request_header响应header大小写保持不变
2.2测试set_headers
增加conf/lua/sub_request_header.json文件
cp conf/lua/request_header.json conf/lua/sub_request_header.json
修改conf/lua/request_header.json文件
local function print_table(t)
local function parse_array(key, tab)
local str = ''
for _, v in pairs(tab) do
str = str .. key .. ' ' .. v .. '\r\n'
end
return str
end
local str = ''
for k, v in pairs(t) do
if type(v) == "table" then
str = str .. parse_array(k, v)
else
str = str .. k .. ' ' .. v .. '\r\n'
end
end
return str
end
--local headers = ngx.req.get_headers(0, true)
--ngx.say(print_table(headers))
ngx.req.set_header('Foo', 'Bar')
local res = ngx.location.capture('/sub_request_header.json')
if res.status == ngx.HTTP_OK then
ngx.say(res.body)
else
ngx.exit(res.status)
end
子请求set_header
2.3测试response.header.*
2.3.1
ngx.header.Foo = 'Bar'
--lua_transform_underscores_in_response_headers
ngx.header['Foo_Bar'] = 'Bar2'
curl -I http://localhost:8080/response_header
lua_transform_underscores_in_response_headers指令设置在nginx.conf,可以保持response.header中大小写保持不变
2.3.2修改response_header.json
2.3.3修改response_header.json,如果修改ContentType后边为table,只取出最后一个值
--ngx.header['Content_Type'] = {"a=32; path", "text"}
ngx.header['content_type'] = {"a=32; path", "text"}
2.3.4测试response.header的类型为table
修改response_header.json
ngx.say(type(ngx.header))
2.3.5打印response.header内容使用parirs方式,打印内容为空
local function print_table(t)
local function parse_array(key, tab)
local str = ''
for _, v in pairs(tab) do
str = str .. key .. ' ' .. v .. '\r\n'
end
return str
end
local str = ''
for k, v in pairs(t) do
if type(v) == "table" then
str = str .. parse_array(k, v)
else
str = str .. k .. ' ' .. v .. '\r\n'
end
end
return str
end
ngx.say(print_table(ngx.header))
2.3.6打印response.header
local function print_table(t)
local function parse_array(key, tab)
local str = ''
for _, v in pairs(tab) do
str = str .. key .. ' ' .. v .. '\r\n'
end
return str
end
local str = ''
for k, v in pairs(t) do
if type(v) == "table" then
str = str .. parse_array(k, v)
else
str = str .. k .. ' ' .. v .. '\r\n'
end
end
return str
end
ngx.header.Foo = 'Bar'
local resp = ngx.resp.get_headers(0, true)
ngx.say(print_table(resp))
(1)上面演示可以看到,通过ngx.header.*方式设置头信息。需要注意像ngx.set_headers,ngx.print,ngx.c这样函数后面,不能通过ngx.header去设置改变头信息。原因是这些函数调用后,触发一个内容句柄返回,内容句柄返回后,通头信息的设置会失效。如果在这些函数后面,调用ngx.header改变头信息,会得到lua异常。
(2)ngx.header就是一个普通的lua table
(3)通过ngx.header.Foo访问Foo这个域,内部会映射到index,并且跳转一个c函数,再去做这样的访问
(4)ngx.header.Foo='Bar'这样方式改变一个域信息,内部会映射到del index,来完成域信息改变,不要尝试使用pairs和ipairs方式去遍历ngx.header,而是通过ngx.resp.get_header()去获取所头部信息返回,这个函数获取的信息也并非是完全的
三、总结
请求头(ngx.req.get_headers/ngx.req.set_headers)和响应头(ngx.header/ngx.resp.get_headers)的操作和读取