-
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: xml-json-conversion plugin convert xml data from request body to json response, and vice versa #5016
Conversation
@tzssangglass @tokers Can you help me review this PR? Thanks |
rockspec/apisix-master-0.rockspec
Outdated
@@ -70,6 +70,8 @@ dependencies = { | |||
"ext-plugin-proto = 0.3.0", | |||
"casbin = 1.26.0", | |||
"api7-snowflake = 2.0-1", | |||
"xml2lua = 1.5-2", | |||
"lua-cjson = 2.1.0.6" |
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.
lua-cjson
has installed? refer to:
Line 17 in baf8434
local json_encode = require("cjson.safe").encode |
cc @spacewander
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. lua-cjson is unneccessary
|
||
local _M = { | ||
version = 0.1, | ||
priority = 90, |
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 config-defalt.yaml
, priority
is 9, pls keep same.
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.
local req_body, err = core.request.get_body() | ||
if err or req_body == nil or req_body == '' then | ||
core.log.error("failed to read request body: ", err) | ||
core.response.exit(400, {error_msg = "invalid request body: " .. err}) | ||
end | ||
|
||
local from = conf.from | ||
local to = conf.to | ||
if from == to then | ||
return req_body | ||
end | ||
|
||
local content_type = core.request.headers()["Content-Type"] | ||
local _f_anon = _switch_anonymous[from] | ||
if _f_anon then | ||
return _f_anon(content_type, req_body, to) | ||
else | ||
return 400, {message = "Operation not supported"} | ||
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.
This code is almost the same as the following get_json()
, can we extract it into a 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.
done. Thanks
t/plugin/xml-json-conversion.t
Outdated
return | ||
end | ||
|
||
ngx.say(body) |
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.
should check the request body is converted to json format?
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.
|
||
local function json2xml(table_data) | ||
local xmlStr = xml2lua.toXml(cjson.decode(table_data)) | ||
xmlStr = string.gsub(xmlStr, "%s+", "") |
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 think Camel-Case naming is not good here
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. Thanks
end | ||
|
||
local function xml2json(xml_data) | ||
local convertHandler = handler:new() |
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 think Camel-Case naming is not good here
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.
|
||
local _switch_anonymous = { | ||
["json"] = function(content_type, req_body, to) | ||
if "application/json" ~= content_type then |
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.
Maybe you should use the flowing code to check header is json ,not the equal compare
if string.find(content_type, "application/json", 1, true)
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.
Co-authored-by: tzssangglass <tzssangglass@gmail.com>
Co-authored-by: tzssangglass <tzssangglass@gmail.com>
@mangoGoForward hi, pls resolve the conflicting files |
What are scenes can this plugin be used? |
done. Already resolved. |
Could you help me to review this PR? Or give me some suggestions @tokers @arthur-zhang |
return { | ||
{ | ||
methods = {"GET"}, | ||
uri = "/apisix/plugin/xml-json-conversion", |
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.
Could we remove the API? We don't want to expose more APIs to the public network.
|
||
local _switch_anonymous = { | ||
["json"] = function(content_type, req_body, to) | ||
if string.find(content_type, "application/json", 1, true) == nil then |
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.
Better to use core.string.find
default = "json" | ||
} | ||
}, | ||
additionalProperties = false, |
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 have already removed additionalProperties
from other plugins.
local string = require("string") | ||
local parser = require("xml2lua").parser | ||
local table_to_xml = require("xml2lua").toXml | ||
local json_decode = require('cjson.safe').decode |
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.
Better to use core.json
|
||
local function json2xml(table_data) | ||
local xmlStr = table_to_xml(json_decode(table_data)) | ||
xmlStr = string.gsub(xmlStr, "%s+", "") |
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.
Could we use re.gsub
?
local function xml2json(xml_data) | ||
local convert_handler = handler:new() | ||
local parser_handler = parser(convert_handler) | ||
parser_handler:parse(xml_data) |
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 should check if the parse fails.
end | ||
|
||
local function json2xml(table_data) | ||
local xmlStr = table_to_xml(json_decode(table_data)) |
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.
Ditto
@@ -347,6 +347,7 @@ plugins: # plugin list (sorted by priority) | |||
#- log-rotate # priority: 100 | |||
# <- recommend to use priority (0, 100) for your custom plugins | |||
- example-plugin # priority: 0 | |||
- xml-json-conversion # priority: 9 |
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.
Why "priority: 9" is after "priority: 0"? And we should avoid '(0, 100)' for builtin plugins
t/plugin/xml-json-conversion.t
Outdated
GET /t | ||
--- response_body | ||
done | ||
--- no_error_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.
We can check no_error_log by default like:
Line 40 in b5d72cb
if ((!defined $block->error_log) && (!defined $block->no_error_log)) { |
I am curious about the use case of this plugin. If it is just converting XML to JSON online, and echoing it back, why should we add it as a feature of API gateway? Maybe we should pass the converted body to the upstream, which could be useful. |
agree |
I think so right now, thanks for your suggestion. @spacewander @arthur-zhang |
We can introduce an "echo_back" option (default to false), so the current behavior can be persisted when echo_back is true. |
I‘m a little bit incomprehensible, could you please provide more detailed description. And It seems that the plugin is unsuitable as a apisix plugin. |
will give us the current behavior.
will pass the rewritten body to the upstream. |
I think |
What this PR does / why we need it:
Summary
name
xml-json-conversion plugin convert xml data from request body to json response, and vice versa
Attributes
how-to-enable
Here's an example, enable this plugin on the specified route:
test-plugin
Via curl to access
disable-plugin
When you want to disable the
xml-json-conversion
plugin, it is very simple,you can delete the corresponding json configuration in the plugin configuration,
no need to restart the service, it will take effect immediately:
Pre-submission checklist: