用于转义html标签的Joi扩展

问题描述

我想创建扩展名以清理字符串输入并剥离html标签

为此,我正在使用sanitize-html npm软件包。

这是我到目前为止尝试过的。

const sanitizeHtml = require('sanitize-html');

module.exports = function htmlStrip(joi) {
  return {
    type: 'htmlStrip',base: joi.string(),messages: {
      htmlStrip: 'Should not contain any html tags.',},validate(value,helpers) {
      const clean = sanitizeHtml(value,{
        allowedTags: [],allowedAttributes: {},});
      if (clean) {
        return clean;
      }
      return { value,errors: helpers.error('htmlStrip') };
    },};
};

但是我遇到了错误

TypeError:Joi.string(...)。trim(...)。htmlStrip不是函数

我还尝试过如下所示的传递规则对象,但仍然遇到相同的错误

const sanitizeHtml = require('sanitize-html');

module.exports = function htmlStrip(joi) {
  return {
    type: 'htmlStrip',rules: {
      htmlStrip: {
        validate(params,value,state,options) {
          const clean = sanitizeHtml(value,{
            allowedTags: [],});
          if (clean) {
            return clean;
          }
          return this.createError('string.htmlStrip',{ value },options);
        },};
};

我正在关注提到的文档here

这就是我使用扩展验证器的方式。

const Joi = require('@hapi/joi').extend(require('@hapi/joi-date')).extend(require('../utils/sanitize-html-joi'));

const validateAddressCreateData = (data) => {
  const schema = Joi.object({
    address: Joi.string().trim().htmlStrip().required(),label: Joi.string()
      .required(),});
  return schema.validate(data);
};

解决方法

考虑到您扩展了Joi.string().trim()对象,但仍希望Joi可用,因此不确定为什么您假设Joi的类型将与htmlStrip相同Joi.string().trim()个结果。

两种类型的简单console.log显示它们是不同的类型。

console.log(Object.keys(Joi))

[ '_types','alternatives','any','array','boolean',...
  'htmlStrip' ]

console.log(Object.keys(Joi.string().trim());

[ 'type','$_root','$_temp','_ids','_preferences','_valids','_invalids','_rules','_singleRules','_refs','_flags','_cache','$_terms','$_super' ]

trim的结果$_super似乎不包含任何键,因此它们实际上并不相关。

我相信,如果您要预处理输入内容然后再使用htmlStrip,请执行以下操作:

const sanitizeHtml = require('sanitize-html');

module.exports = function htmlStrip(joi) {
  return {
    type: 'htmlStrip',base: joi.string(),messages: {
      htmlStrip: 'Should not contain any html tags.',},validate(value,helpers) {
      const clean = sanitizeHtml(value,{
        allowedTags: [],allowedAttributes: {},});
      if (clean == value) {
        return { clean,errors: [] };
      }
      return { value,errors: helpers.error('htmlStrip') };
    },};
};

这是我的使用方式:

const Joi = require('@hapi/joi').extend(require('@hapi/joi-date')).extend(require('./san'));

const validateAddressCreateData = (data) => {
  const schema = Joi.object({
    address: Joi.htmlStrip(Joi.string().trim()).required(),label: Joi.string().required(),});
  return schema.validate(data);
};

console.log(validateAddressCreateData({ address: "<body>test</body>",label: "abc"}));

但是我不确定输出是否如您所愿:

{ value: { address: '<body>test</body>',label: 'abc' },error:
   { ValidationError: Should not contain any html tags.
     _original: { address: '<body>test</body>',details: [ [Object] ] } }

因此,似乎根据定义的验证消息来验证输入。还是您实际上要修改要传递的地址html?

编辑现已说明,并相应修改了htmlStrip。请查看比较if(value == clean)。如果消毒剂不需要修剪任何东西,则意味着输入字符串不包含任何html标记。在其他情况下返回错误。