2014-10-06 15 views
5

Moim celem jest utworzenie indeksu indeksu trasy dla postów. Użytkownik powinien mieć możliwość określenia niektórych parametrów zapytania (tj. Tagów, typu), ale nie powinien być w stanie określić innych. Aby wyjaśnić:Hapijs i Joi: sprawdzanie poprawności parametrów zapytań z obecnością: "zabronione"

To jest w porządku:

/posts 
/posts?tags=food 
/posts?type=regular&tags=stackoverflow 

To nie jest w porządku:

/posts?title=Hello 

To Hapi paczka config:

servers: [ 
     { 
      host: 'localhost', 
      port: 3000, 
      options: { 
       labels: ["api"], 
       validation: { 
        abortEarly: false, 
        presence: 'forbidden' 
       } 
      } 
     } 
    ], 

Proszę zauważyć opcję presence: forbidden.

To config trasa:

handler: function (request, reply) { 
    Post.find(request.query, function (err, posts) { 
     if(err) { 
      console.log(err); 
     } 

     reply(posts); 
    }); 
}, 
validate: { 
    query: { 
     type: Joi.string().optional(), 
     tags: Joi.string().optional() 
    } 

} 

Mój pomysł był taki, że walidacja powinna dopuszczać dowolny podzbiór type i tags params (w tym pustym zapytania). Jednak po wykonaniu dowolnego z dozwolonych żądań pojawia się następujący błąd:

{ 
    "statusCode": 400, 
    "error": "Bad Request", 
    "message": "value is not allowed", 
    "validation": { 
     "source": "query", 
     "keys": [ 
      "value" 
     ] 
    } 
} 

Dlaczego tak jest? Nie ma oczywiście klucza o nazwie value. Jak sprawić, by walidacja zachowywała się tak, jak tego chcę?

Odpowiedz

8

Jeśli zdefiniujesz obiekt schematu inny niż typ, Joi konwertuje go wewnętrznie na typ object(). Więc ten schemat:

var schema = { 
    type: Joi.string().optional(), 
    tags: Joi.string().optional() 
}; 

staje:

var schema = Joi.object().keys({ 
    type: Joi.string().optional(), 
    tags: Joi.string().optional() 
}); 

Ponieważ ustawienie presence do forbidden w ustawieniach serwera, jest on stosowany do typu obiektu, więc schemat staje:

var schema = Joi.object().forbidden().keys({ 
    type: Joi.string().optional(), 
    tags: Joi.string().optional() 
}); 

Jak widać oznacza to główny obiekt jako zabroniony, który nie zezwala na żadną wartość poza: undefined:

var Joi = require('joi'); 

var schema = Joi.object().forbidden().keys({ 
    type: Joi.string().optional(), 
    tags: Joi.string().optional() 
}); 

var value = {}; 

Joi.validate(value, schema, { presence: 'forbidden' }, function (err, value) { 

    console.log(err); 
}); 

To Wyjścia:

{ [ValidationError: value is not allowed] 
    name: 'ValidationError', 
    details: 
    [ { message: 'value is not allowed', 
     path: 'value', 
     type: 'any.unknown' } ], 
    _object: {}, 
    annotate: [Function] } 

Więc co trzeba zrobić, to zaznaczyć główny przedmiot albo required lub optional przesłonić forbidden:

validate: { 
    query: Joi.object().required().keys({ 
     type: Joi.string().optional(), 
     tags: Joi.string().optional() 
    }) 
} 
+0

Dziękujemy! Ta odpowiedź wyjaśniła kilka innych pytań, które miałem. Wydaje się, że to, co naprawdę chciałem jako ustawienie globalne, to obecność: "wymagane". Nie zdawałem sobie sprawy, że "zakazane" ustawienie było tak surowe. – zir

Powiązane problemy