Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a colander body validator ? #386

Closed
leplatrem opened this issue Sep 28, 2016 · 1 comment
Closed

Add a colander body validator ? #386

leplatrem opened this issue Sep 28, 2016 · 1 comment

Comments

@leplatrem
Copy link
Contributor

leplatrem commented Sep 28, 2016

With the new validation API in #376, it is now possible to have schemas that validate things accross different parts of the request (e.g. querystring/headers/body). This is very convenient and powerful but can be tedious if you only need to validate body payloads because you have to define schemas like this:

    from cornice.validators import colander_validator

    class Payload(colander.MappingSchema):
        username = colander.SchemaNode(colander.String())

    class SignupSchema(colander.MappingSchema):
        body = Payload()

    signup = cornice.Service()

    @signup.get(schema=SignupSchema, validators=(colander_validator,))
    def signup_get(request):
        username = request.validated['body']['username']
        return {'success': True}

We could have a colander_body_validator that validates the body only, which would prevent having to define a upper level schema:

    from cornice.validators import colander_body_validator

    class SignupSchema(colander.MappingSchema):
        username = colander.SchemaNode(colander.String())

    signup = cornice.Service()

    @signup.get(schema=SignupSchema, validators=(colander_body_validator,))
    def signup_get(request):
        username = request.validated['username']  # no ['body']
        return {'success': True}

The code is short and would look like this:

diff --git a/cornice/validators/_colander.py b/cornice/validators/_colander.py
index 5136dca..ba83424 100644
--- a/cornice/validators/_colander.py
+++ b/cornice/validators/_colander.py
@@ -1,12 +1,28 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
-from colander import Invalid
+import colander
+
+from cornice.validators import extract_cstruct
+
+
+def _body_deserializer(request):
+    request_data = extract_cstruct(request)
+    return request_data['body']
+
+
+def body_validator(request, **kwargs):
+    schema = kwargs.get('schema')
+    if schema is not None:
+        request_schema = colander.MappingSchema()
+        request_schema.add('body', schema())
+        kwargs['schema'] = request_schema
+        kwargs['deserializer'] = _body_deserializer
+    return validator(request, **kwargs)


 def validator(request, deserializer=None, **kw):
     if deserializer is None:
-        from cornice.validators import extract_cstruct
         deserializer = extract_cstruct

     schema = kw.get('schema')
@@ -19,7 +35,7 @@ def validator(request, deserializer=None, **kw):
     try:
         deserialized = schema.deserialize(cstruct)
         request.validated.update(deserialized)
-    except Invalid as e:
+    except colander.Invalid as e:
         translate = request.localizer.translate
         error_dict = e.asdict(translate=translate)
         for name, msg in error_dict.items():
@tarekziade
Copy link
Contributor

+1

leplatrem added a commit that referenced this issue Oct 20, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants