-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(core) exposing rewrite_by_lua handler to plugins #2354
Conversation
4b25115
to
37508c2
Compare
I have added a test that demonstrates rewriting a random URI to a URI that will later matched to an API. |
37508c2
to
96dfc2b
Compare
do we need this for some reason? if not urgent, maybe better to postpone until a new plugin api has been designed? |
Business requirements 😄. |
kong/kong.lua
Outdated
core.rewrite.before() | ||
|
||
for _, plugin in ipairs(singletons.loaded_plugins) do | ||
plugin.handler:rewrite() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This currently runs the handler on every plugin loaded in the system. Say we now have some 25 plugins, so on every request we're now invoking 25 plugins. Not just configured ones, but all available ones.
As the rewrite phase does not have a consumer yet, and also doesn't have an api yet, the only plugins that should be selected here are the global ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point - I will update the PR to only chose plugins where api_id == nil and consumer_id == nil
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Tieske done
|
||
core.rewrite.after() | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the above runs on loaded_plugins
which means that it will run all plugins available, no matter what. So the user has no control on whether it runs or not, when it is in the system, it will execute.
It should fetch the plugins from the database, and execute only those that are neither attached to a consumer, nor to an api (eg. the ones that already run on every api).
btw, can't we bring the api detection forward, to run in the core.rewrite.before()
handler? not sure what it takes, but then we can run plugins like in any phase, including "per api" configured plugins
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the above runs on loaded_plugins which means that it will run all plugins available, no matter what.
I understand your point but it would be over-optimization IMHO. Currently every other handler also runs on every plugin regardless if they have an event handler associated or not (ie, the access()
for every plugin is invoked regardless if the plugin implements that method).
btw, can't we bring the api detection forward, to run in the core.rewrite.before() handler? not sure what it takes, but then we can run plugins like in any phase, including "per api" configured plugins
My use-case is to implement URL rewriting before the APIs are matched, and rewrite the URI to be matched later by the router.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ie, the access() for every plugin is invoked regardless if the plugin implements that method
That's not what I mean. Because that access handler is only called if the user explcitly added that plugin through the management api.
In the code you have now, it will run the handler, even if the user did not configure it. Just a plugin "being in the system" will make it being executed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hence if you run only the plugins that have been globally added by the user, neither attached to a consumer nor an api, it would work. And it would be up to the user to whether to add this plugin or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one more thing: does it currently honour the plugin priority
setting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no_api
and no_consumer
make sure that the plugin cannot be applied to a specific consumer or API, because in the rewrite phase we cannot possibly know who the consumer is and what API he is trying to consume.
With the last commit I am only executing the rewrite()
check for those plugins that satisfy the requirement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two ways to approach this problem
- add the
no_api
flag: run only plugins that haveno_consumer
andno_api
set. This causes a plugin to be configurable ONLY as a global plugin - execute the
rewrite
handler only for globally configured plugins, without adding the extra complexity of ano_api
flag. This allows a plugin to be used either as a global, or api/consumer specific plugin. In the latter case therewrite
handler won't be used. But that is then up to the plugin author...
I find option 1 to be A) more complex due to the extra flag, 2) needlessly limiting flexibility
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Option 3: use option 2 above (so select only global plugins when running the rewrite
handler), but still add the no_api
flag. This allows the author to specify the extra limitation only if his plugin needs it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Tieske no_api
is important because it prevents, from the Admin API, to target a specific API when it doesn't make any sense to do so (like no_consumer
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thefosk That's the option 3 above, which is nice. But that is a limitation that kicks in when configuring. But you should not be using that field to select the plugins to run, you should run all plugins that are configured as global, so where consumer_id
and api_id
are nil
.
Running the global plugins is a Kong responsibility
Marking a plugin with no_api
is a plugin developer responsibility.
Those are different things.
The latest commit broke something, see the travis-ci build. |
12fb88a
to
125f97f
Compare
d76ef57
to
efef49e
Compare
@thefosk @p0pr0ck5 @thibaultcha updated this as discussed. Now in the Note: do not merge yet, would prefer to merge #2455 first and update this PR before merging (see |
efef49e
to
3a5f370
Compare
update: fixed the update after 2455 was merged, so |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Starting to look good to me! However, a few things in there are lacking, or unneeded...
end | ||
|
||
function BasePlugin:log() | ||
ngx.log(ngx.DEBUG, " executing plugin \""..self._name.."\": log") | ||
ngx_log(DEBUG, "executing plugin \"", self._name, "\": log") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sadly, these are some an unrelated change to this PR and should have been part of a different one...
end, | ||
after = function () | ||
local ctx = ngx.ctx | ||
ctx.KONG_REWRITE_TIME = get_now() - ctx.KONG_REWRITE_START -- time spent in Kong's rewrite_by_lua |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This variable needs to be added to the basic
log serializer when computing the latencies.kong
property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done!
kong/core/reports.lua
Outdated
@@ -180,6 +180,9 @@ return { | |||
|
|||
create_timer(PING_INTERVAL, ping_handler) | |||
end, | |||
rewrite = function() | |||
-- Do nothing | |||
end, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need this? We manually call reports.init_worker()
and reports.log()
, but I see nowhere where reports.rewrite()
is called. There is no reports.access()
either, for example and for that matters.
|
||
describe("OpenResty handlers", function() | ||
|
||
describe("rewrite on global plugin", function() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would have been slightly better to have the sentences be slightly more specific when tests run with --o=gtest
flag:
describe("OpenResty phases", function()
describe("rewrite_by_lua", function()
describe("enabled on all APIs", function()
it("runs")
end)
describe("enabled on a specific APIs", function()
it("doesn't run")
end)
end)
end)
reverted api-only config option. Rewrite handler will only be executed on the globally configured plugins
3a5f370
to
09659cb
Compare
Signed-off-by: Thibault Charbonnier <thibaultcha@me.com> This handler exposes the Nginx rewrite phase. This handler is called for all loaded plugins (since the rewrite phase is executed prior to API matching). From #2354
Merged to |
Signed-off-by: Thibault Charbonnier <thibaultcha@me.com> This handler exposes the Nginx rewrite phase. This handler is called for all loaded plugins (since the rewrite phase is executed prior to API matching). From #2354
rewrite_by_lua
event can now be implemented by plugins.no_api
in the plugin's schema to determine if a plugin can be applied to a specific API.