2018-12-27 kong api 数据操作验证过程分析

在插件的api.lua经常用到crud 类。例如

local crud = require "kong.api.crud_helpers"
crud.patch(self.params, dao_factory.nmg_cors, self.plugin)
crud.paginated_set(self, dao_factory.nmg_cors)
crud.find_plugin_by_filter(self, dao_factory, {
        name = "nmg-plugin-cors"
      }, helpers)

crud_helpers 是操作DB的封装类,它封装了find_by_id_or_field,find_api_by_name_or_id,find_plugin_by_filter,paginated_set,post,patch,put,delete等常用DB操作的方法。实际的DB操作是通过dao_collection类操作的。dao_factory.XXX 是api.lua的方法中的参数传递的,可以通过before 方法过滤查询条件。

--- Partial update of an entity.
-- Filter keys must be given to get the row to update.
function _M.patch(params, dao_collection, filter_keys, post_process)
  if not next(params) then
    return responses.send_HTTP_BAD_REQUEST("empty body")
  end
  local updated_entity, err = dao_collection:update(params, filter_keys)
  if err then
    return app_helpers.yield_error(err)
  elseif updated_entity == nil then
    return responses.send_HTTP_NOT_FOUND()
  else
    return responses.send_HTTP_OK(post_process_row(updated_entity, post_process))
  end
end

真正执行更新的是dao_collection:update。dao_collection对应的类是dao/dao.lua


--- Update a row.
-- Update a row in the related table. Perform a partial update by default (only fields in `tbl` will)
-- be updated. If asked, can perform a "full" update, replacing the entire entity (assuming it is valid)
-- with the one specified in `tbl` at once.
-- @param[type=table] tbl A table containing the new values for this row.
-- @param[type=table] filter_keys A table which must contain the primary key(s) to select the row to be updated.
-- @param[type=table] options Options to use for this update. (`full`: performs a full update of the entity, `quiet`: does not send event).
-- @treturn table res A table representing the updated entity.
-- @treturn table err If an error occurred, a table describing the issue.
function DAO:update(tbl, filter_keys, options)
  options = options or {}
  check_arg(tbl, 1, "table")
  check_not_empty(tbl, 1)
  check_arg(filter_keys, 2, "table")
  check_not_empty(filter_keys, 2)
  check_arg(options, 3, "table")

  for k, v in pairs(filter_keys) do
    if tbl[k] == nil then
      tbl[k] = v
    end
  end

  local model = self.model_mt(tbl)
  local ok, err = model:validate {dao = self, update = true, full_update = options.full}
  if not ok then
    return ret_error(self.db.name, nil, err)
  end

  local primary_keys, values, nils, err = model:extract_keys()
  if err then
    return ret_error(self.db.name, nil, Errors.schema(err))
  end

  local old, err = self.db:find(self.table, self.schema, primary_keys)
  if err then
    return ret_error(self.db.name, nil, err)
  elseif old == nil then
    return
  end

  if not options.full then
    fix(old, values, self.schema)
  end

  local res, err = self.db:update(self.table, self.schema, self.constraints, primary_keys, values, nils, options.full, model, options)
  if err then
    return ret_error(self.db.name, nil, err)
  elseif res then
    if not options.quiet then
      if self.events then
        local _, err = self.events.post_local("dao:crud", "update", {
          schema     = self.schema,
          operation  = "update",
          entity     = res,
          old_entity = old,
        })
        if err then
          ngx.log(ngx.ERR, "could not propagate CRUD operation: ", err)
        end
      end
    end
    return setmetatable(res, nil)
  end
end

在执行更新之前会执行验证

 local ok, err = model:validate {dao = self, update = true, full_update = options.full}

验证内容是plugin的schema和plugin的config是否匹配。验证类是dao/schemas_validation.lua

注意下面

-- Check for unexpected fields in the entity
      for k in pairs(t) do
        if schema.fields[k] == nil then
          if schema.flexible then
            if utils.strip(tk) ~= "" and k ~= tk then
              errors = utils.add_error(errors, error_prefix .. k, k .. " is an unknown field")
            end
          else
            errors = utils.add_error(errors, error_prefix .. k, k .. " is an unknown field")
          end
        end
      end

这是比较plugins表的数据结构和shema的配置是否一致。t是table。shema是shema.lua的配置项。如果plugins表有值,而shema中没有,则会提示xxx is an unknown field。例如我在某个plugin设置了route_id,但是shema中是没有的,就会出

{route_id:'route_id is an unknown field'}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值