-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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: add public api plugin #6145
Conversation
9952d03
to
eab8158
Compare
apisix/plugins/public-api.lua
Outdated
local local_conf = core.config.local_conf() | ||
|
||
-- overwrite the uri in the ctx when the user has set the target uri | ||
ctx.var.uri = conf.uri and conf.uri or ctx.var.uri |
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.
ctx.var.uri = conf.uri and conf.uri or ctx.var.uri | |
ctx.var.uri = conf.uri or ctx.var.uri |
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.
fixed
|
||
-- overwrite the uri in the ctx when the user has set the target uri | ||
ctx.var.uri = conf.uri and conf.uri or ctx.var.uri | ||
local skip = local_conf and local_conf.apisix.global_rule_skip_internal_api |
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.
We don't need to run global rules twice?
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.
Lines 376 to 445 in 64c47df
router.router_http.match(api_ctx) | |
local route = api_ctx.matched_route | |
if not route then | |
-- whether the public API run global rules is | |
-- controlled by the configuration file | |
if router.api.has_route_not_under_apisix() or | |
core.string.has_prefix(uri, "/apisix/") | |
then | |
local skip = local_conf and local_conf.apisix.global_rule_skip_internal_api | |
local matched = router.api.match(api_ctx, skip) | |
if matched then | |
return | |
end | |
end | |
-- run global rule when there is no matching route | |
plugin.run_global_rules(api_ctx, router.global_rules, nil) | |
core.log.info("not find any matched route") | |
return core.response.exit(404, | |
{error_msg = "404 Route Not Found"}) | |
end | |
core.log.info("matched route: ", | |
core.json.delay_encode(api_ctx.matched_route, true)) | |
local enable_websocket = route.value.enable_websocket | |
if route.value.plugin_config_id then | |
local conf = plugin_config.get(route.value.plugin_config_id) | |
if not conf then | |
core.log.error("failed to fetch plugin config by ", | |
"id: ", route.value.plugin_config_id) | |
return core.response.exit(503) | |
end | |
route = plugin_config.merge(route, conf) | |
end | |
if route.value.service_id then | |
local service = service_fetch(route.value.service_id) | |
if not service then | |
core.log.error("failed to fetch service configuration by ", | |
"id: ", route.value.service_id) | |
return core.response.exit(404) | |
end | |
route = plugin.merge_service_route(service, route) | |
api_ctx.matched_route = route | |
api_ctx.conf_type = "route&service" | |
api_ctx.conf_version = route.modifiedIndex .. "&" .. service.modifiedIndex | |
api_ctx.conf_id = route.value.id .. "&" .. service.value.id | |
api_ctx.service_id = service.value.id | |
api_ctx.service_name = service.value.name | |
if enable_websocket == nil then | |
enable_websocket = service.value.enable_websocket | |
end | |
else | |
api_ctx.conf_type = "route" | |
api_ctx.conf_version = route.modifiedIndex | |
api_ctx.conf_id = route.value.id | |
end | |
api_ctx.route_id = route.value.id | |
api_ctx.route_name = route.value.name | |
-- run global rule | |
plugin.run_global_rules(api_ctx, router.global_rules, nil) |
Hi, @spacewander.
Based on this part of the code, we can presume to have such a situation.
- HTTP match, and
public-api
plugin is enabled.
This will be controlled by the configuration file whether to enforce global rules for public API calls. After the match, the subsequent request processing flow will be completely taken over by the public API handler, bypassing the rest of the code execution in the access phase. - HTTP not matched, public API route matched.
This will also be controlled by the configuration file whether to enforce global rules or not. - Both HTTP and public APIs do not match
It will force the global rule to run and return 404 Not Route.
Also, as you said in this issue #6137 (comment), we will adjust the public API to not be exposed by default, which will be done by completely removing the public API route match in the access phase. (Currently HTTP matching is performed followed by public API matching as a backup) In that case, the matching and processing of the public API will be done by the public-api plugin only, and if a match is made the global rules will be enforced according to the configuration.
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.
In that case, the matching and processing of the public API will be done by the public-api plugin only, and if a match is made the global rules will be enforced according to the configuration.
We can adjust it when we retire the router? The current implementation will run global rules twice in some cases.
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 will try to fix 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.
Update
After checking again, I think there may not be a duplicate calls problem.
Details
There are 4 calls to run_global_rules
executed in the current code. One of them is in api_router
, which is controlled by the configuration file (this is the router used by the public API), and the remaining ones are executed in the http_access_phase
of init
.
-
both HTTP and public API do not match, will run and return a 404 status code, stop progress
-
run in
common_phase
forbefore_proxy
In fact I didn't add global_rules
to init.lua, they are still being executed according to the original logic.
If I have missed anything, please help point it out. Thanks.
ping @spacewander
t/plugin/public-api.t
Outdated
|
||
=== TEST 3: hit route (custom-jwt-sign) | ||
--- request | ||
GET /gen_token?key=user-key |
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.
Let's add assertion to make sure the jwt sign is working
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.
added, It will check the first part of the JWT in the response body, however, because json encode cannot guarantee the order of the data in it, it matches both cases.
t/plugin/public-api.t
Outdated
GET /apisix/plugin/wolf-rbac/user_info | ||
--- error_code: 401 | ||
--- error_log | ||
custom-jwt-sign was triggered |
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.
Let's add more cases:
- public api not match
- match without optional uri
- add auth to protect public api
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.
- added
- I didn't understand what you meant, is it a case where there is no uri configuration in the schema? If so it is there now.
- added, protect jwt sign by
key-auth
=== TEST 5: missing route | ||
--- request | ||
GET /apisix/plugin/balalbala | ||
--- error_code: 404 |
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.
Let's add more test that the uri in public API plugin matches nothing.
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.
got it, adding
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.
added
I don't see the problem in the code and test cases, but I don't see the documentation for the plugin. |
According this comment #6145 (comment), there is a next phase of development work after this PR is completed, which will be added when everything is done. |
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.
Approve except #6145 (comment)
What this PR does / why we need it:
Implement: #6137
Pre-submission checklist: