流星服务器验证的方法不会在客户端上显示验证错误

时间:2019-04-18 14:20:09

标签: meteor meteor-autoform

我具有此经过服务器端验证的方法 imports / api / Shops / server / methods.js

export const shopGeocodeAddress = new ValidatedMethod({
  name: 'shops.geocodeAddress',
  validate: new SimpleSchema({
    streetName: { type: String },
    houseNumber: { type: Number },
    city: { type: String },
    state: { type: String },
    country: { type: String },
    zip: { type: String, optional: true },
  }).validator(),
  run({ streetName, houseNumber, city, state, country, zip }) {
...
...
...
...
    return location;
  },
});

要在客户端上测试验证错误消息,我将 houseNumber 作为字符串发送,这将导致方法失败,因为它期望 houseNumber 作为Number。到目前为止,一切都很好。我在服务器控制台上收到这样的验证错误:

I20190418-10:55:28.605(-3)? Exception while invoking method 'shops.geocodeAddress' { ClientError: House number must be of type Number
...
...
I20190418-10:55:28.608(-3)?   errorType: 'ClientError',
I20190418-10:55:28.608(-3)?   name: 'ClientError',
I20190418-10:55:28.608(-3)?   error: 'validation-error',
I20190418-10:55:28.609(-3)?   details: 
I20190418-10:55:28.609(-3)?    [ { name: 'houseNumber',
I20190418-10:55:28.609(-3)?        value: NaN,
I20190418-10:55:28.609(-3)?        type: 'expectedType',
I20190418-10:55:28.609(-3)?        dataType: 'Number',
I20190418-10:55:28.609(-3)?        message: 'House number debe ser del tipo Number' } ] }

但是在客户端上,我仅收到如下内部服务器错误:

details: undefined
error: 500
errorType: "Meteor.Error"
isClientSafe: true
message: "Internal server error [500]"
reason: "Internal server error"

因此,我无法指示客户端哪种错误类型,或者必须更改哪个字段才能正确运行该方法。

是否可以捕获服务器方法上的验证错误并将其发送给客户端?

感谢劝告!

3 个答案:

答案 0 :(得分:1)

您可以包围s schema.validator(尝试/捕获)并抛出自定义Meteor.Error,其中包含更好的可理解信息。

您可以对run中的代码执行相同的操作。

如果要对每个经过验证的方法都执行此操作,则可以创建一个简单的生成器函数:

const createMethod = options => new ValidatedMethod({
  name: options.name,
  validate(...args) {
    try {
      new SimpleSchema(options.schema).validate(...args)
    } catch (e) {
      throw new Meteor.Error('validationError', e.reason)
    }
  },
  run(...args) {
    try {
      return options.run.call(this, ...args)
    } catch (e) {
      throw new Meteor.Error('methodError', e.reason)
    }    
  }
})

请注意,您可以使用e.reason || e.message

答案 1 :(得分:1)

2件事: A)你可以写

city: String,
state: String,
zip: { type: String, optional: true }
...

B)您说“服务器端验证方法”。您的方法必须位于服务器和客户端均可访问的公共空间中。在该方法中,将所有内容都封装到Server中。您从客户端调用该方法(并到达该方法),但在服务器上运行该方法:

export const shopGeocodeAddress = new ValidatedMethod({
  name: 'shops.geocodeAddress',
  validate: new SimpleSchema({
    streetName: String,
    houseNumber: Number,
    city: String,
    state: String,
    country: String,
    zip: { type: String, optional: true },
  }).validator(),
  run({ streetName, houseNumber, city, state, country, zip }) {
     if (Meteor.isServer) {
      ...
      ...
      ...
      ...
    return location;
     }

  },
});

答案 2 :(得分:0)

最后,我在流星论坛https://forums.meteor.com/t/server-validated-method-doesnt-display-validation-error-on-client/48635/2?u=razor7

上使用了此答案

基本上,我需要创建一个新文件以在服务器启动时运行,以将验证错误路由到客户端

import SimpleSchema from 'simpl-schema';

SimpleSchema.defineValidationErrorTransform((error) => {
  const ddpError = new Meteor.Error(error.message);
  ddpError.error = 'validation-error';
  ddpError.details = error.details;
  ddpError.reason = error.message;

  return ddpError;
});