membphis commented on code in PR #12718:
URL: https://github.com/apache/apisix/pull/12718#discussion_r2541005501


##########
apisix/admin/standalone.lua:
##########
@@ -158,6 +157,128 @@ local function check_conf(checker, schema, item, typ)
 end
 
 
+local function validate_configuration(req_body, collect_all_errors)
+    local validation_results = {
+        valid = true,
+        errors = {}
+    }
+
+    for key, conf_version_key in pairs(ALL_RESOURCE_KEYS) do
+        local items = req_body[key]
+        local resource = resources[key] or {}
+
+        -- Validate conf_version_key if present
+        local new_conf_version = req_body[conf_version_key]
+        if new_conf_version and type(new_conf_version) ~= "number" then
+            local error_msg
+            if collect_all_errors then
+                error_msg = conf_version_key .. " must be a number, got " .. 
type(new_conf_version)
+            else
+                error_msg = conf_version_key .. " must be a number"
+            end
+
+            if not collect_all_errors then
+                return false, error_msg
+            end
+            validation_results.valid = false
+            table_insert(validation_results.errors, {
+                resource_type = key,
+                error = error_msg
+            })
+        end
+
+        if items and #items > 0 then
+            local item_schema = resource.schema
+            local item_checker = resource.checker
+            local id_set = {}
+
+            for index, item in ipairs(items) do
+                local item_temp = tbl_deepcopy(item)
+                local valid, err = check_conf(item_checker, item_schema, 
item_temp, key)
+                if not valid then
+                    local err_prefix = "invalid " .. key .. " at index " .. 
(index - 1) .. ", err: "
+                    local err_msg = type(err) == "table" and err.error_msg or 
err
+                    local error_msg = err_prefix .. err_msg
+
+                    if not collect_all_errors then
+                        return false, error_msg
+                    end
+                    validation_results.valid = false
+                    table_insert(validation_results.errors, {
+                        resource_type = key,
+                        index = index - 1,
+                        error = error_msg
+                    })
+                end
+
+                -- check for duplicate IDs
+                local duplicated, dup_err = check_duplicate(item, key, id_set)
+                if duplicated then
+                    if not collect_all_errors then
+                        return false, dup_err
+                    end
+                    validation_results.valid = false
+                    table_insert(validation_results.errors, {
+                        resource_type = key,
+                        index = index - 1,
+                        error = dup_err
+                    })
+                end
+            end
+        end
+    end
+
+    if collect_all_errors then

Review Comment:
   code style
   
   ```lua
       if collect_all_errors then
           return validation_results.valid, validation_results
       end
       
       return validation_results.valid



##########
apisix/admin/standalone.lua:
##########
@@ -158,6 +157,128 @@ local function check_conf(checker, schema, item, typ)
 end
 
 
+local function validate_configuration(req_body, collect_all_errors)
+    local validation_results = {
+        valid = true,
+        errors = {}
+    }
+
+    for key, conf_version_key in pairs(ALL_RESOURCE_KEYS) do
+        local items = req_body[key]
+        local resource = resources[key] or {}
+
+        -- Validate conf_version_key if present
+        local new_conf_version = req_body[conf_version_key]
+        if new_conf_version and type(new_conf_version) ~= "number" then
+            local error_msg
+            if collect_all_errors then
+                error_msg = conf_version_key .. " must be a number, got " .. 
type(new_conf_version)
+            else
+                error_msg = conf_version_key .. " must be a number"
+            end
+
+            if not collect_all_errors then
+                return false, error_msg
+            end
+            validation_results.valid = false
+            table_insert(validation_results.errors, {
+                resource_type = key,
+                error = error_msg
+            })
+        end
+
+        if items and #items > 0 then
+            local item_schema = resource.schema
+            local item_checker = resource.checker
+            local id_set = {}
+
+            for index, item in ipairs(items) do
+                local item_temp = tbl_deepcopy(item)
+                local valid, err = check_conf(item_checker, item_schema, 
item_temp, key)
+                if not valid then
+                    local err_prefix = "invalid " .. key .. " at index " .. 
(index - 1) .. ", err: "
+                    local err_msg = type(err) == "table" and err.error_msg or 
err
+                    local error_msg = err_prefix .. err_msg
+
+                    if not collect_all_errors then
+                        return false, error_msg
+                    end
+                    validation_results.valid = false
+                    table_insert(validation_results.errors, {
+                        resource_type = key,
+                        index = index - 1,
+                        error = error_msg
+                    })
+                end
+
+                -- check for duplicate IDs
+                local duplicated, dup_err = check_duplicate(item, key, id_set)
+                if duplicated then
+                    if not collect_all_errors then
+                        return false, dup_err
+                    end
+                    validation_results.valid = false
+                    table_insert(validation_results.errors, {
+                        resource_type = key,
+                        index = index - 1,
+                        error = dup_err
+                    })
+                end
+            end
+        end
+    end
+
+    if collect_all_errors then
+        return validation_results.valid, validation_results
+    else
+        return validation_results.valid, nil
+    end
+end
+
+local function validate(ctx)
+    local content_type = core.request.header(nil, "content-type") or 
"application/json"
+    local req_body, err = core.request.get_body()
+    if err then
+        return core.response.exit(400, {error_msg = "invalid request body: " 
.. err})
+    end
+
+    if not req_body or #req_body <= 0 then
+        return core.response.exit(400, {error_msg = "invalid request body: 
empty request body"})
+    end
+
+    local data
+    if core.string.has_prefix(content_type, "application/yaml") then
+        local ok, result = pcall(yaml.load, req_body, { all = false })
+        if not ok or type(result) ~= "table" then
+            err = "invalid yaml request body"
+        else
+            data = result
+        end
+    else
+        data, err = core.json.decode(req_body)
+    end
+
+    if err then
+        core.log.error("invalid request body: ", req_body, " err: ", err)
+        return core.response.exit(400, {error_msg = "invalid request body: " 
.. err})
+    end
+
+    local valid, validation_results = validate_configuration(data, true)
+
+    if valid then

Review Comment:
   ```lua
       if not valid then
           return core.response.exit(400, {
               error_msg = "Configuration validation failed",
               valid = false,
               errors = validation_results.errors
           })
       end
           
       return core.response.exit(200, {
             message = "Configuration is valid",
             valid = true
         })



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to