概述
kong的serverless插件可以在请求的生命周期内,动态执行lua代码。
例子一
下面来看一个删除请求url中的jsessionid
的例子。
现在请求中有如下url导致后端服务报错:pc/courses/jcqzf9dc;jsessionid=94DB14C127698FCAFEA6599AEE93C252/last-chapter
。 url中出现jsessionid是因为在浏览器不支持cookie的情况下,tomcat的url重写。其实就算url中带有;jsessionid=xxxxx
,在tomcat,spring boot的架构下是没有什么问题的,但是后端框架中使用了spring security,spring security有一些安全的要求,默认情况下是不允许url中带sessionid来维持会话的,错误消息为:The request was rejected because the URL contained a potentially malicious String ";"
。由于后端服务是无状态,使用jwt来鉴权,根本不需要cookie与session,此sessionid可能是老的认证服务导致。
暂时无法找到原因,出错的服务由网关代理,作为一个网关,改写请求是再平常不过之功能。通常现有的插件只提供增删改query 参数,header,body等简单功能,对于上述情况则无能为力。通过serverless插件动态执行自己的代码,在access阶段使用如下代码:
local url = ngx.var.upstream_uri;
local sessionLength = 32;
local start, last = string.find(url, ";jsessionid=");
if start ~= nil then
local newUrl = string.sub(url, 0, start - 1) .. string.sub(url, last + 1 + sessionLength);
kong.log.err("删除url jsessionid,原始url:", url, "修改后:", newUrl);
ngx.var.upstream_uri = newUrl;
end
无论jsessionid出现在url中的什么位置,把它删除掉,然后修改upstream_uri。access阶段是在匹配到路由之后,在转发给上游服务之前,此时匹配路由的前缀已经删除掉,要修改转发给上游服务的url就是修改ngx.var.upstream_uri
这个变量的值。虽然lua代码不需要分号结尾,但是要当做一段代码在serverless中执行,必须加分号。在pre-function插件中的access阶段粘贴上述代码,即可快速,有效,无更新的暂时解决上述问题。
例子二
无后端的授时服务。
假设需要网关提供一个接口来获取当前的时间戳。access阶段是匹配到路由后,转发给上游服务处理前。使用serverless插件,在access阶段填写如下代码:
return kong.response.exit(200,{timestamp=os.time()})
配置一个service,此service地址可以随便写,因为请求根本不会转发给这个地址,在access阶段就返回响应了。再配置路由地址为/time
,即可实现返回当前时间戳。