Cornices / cornice

Build Web Services with Pyramid.
https://cornice.readthedocs.io
Other
383 stars 149 forks source link

Question: Ambiguity regarding multi-validator use case with colander #587

Open fmigneault opened 5 months ago

fmigneault commented 5 months ago

When using


class SomeSchema(colander.MappingSchema):
    path = ...
    header = ...
    querystring = ...

some_service = cornice.Service(...)

@some_service.get(validators=colander_validator, schema=SomeSchema())
def some_view(request): ...

Everything seems to work as expected.

However, when using multiple colander-based validators simultaneously (i.e.: validators=[colander_path_validator, colander_querystring_validator, colander_header_validator], I get some weird behavior where each validator seems to consider that specified schema is only representing their own sub-location rather than the full "request" as in the case of colander_validator, leading to response errors:

{
  "status": "error",
  "errors": [
    {
      "location": "path",
      "name": "path",
      "description": "Missing value for required field without any default."
    },
    {
      "location": "path",
      "name": "header",
      "description": "Missing value for required field without any default."
    },
    {
      "location": "path",
      "name": "querystring",
      "description": "Missing value for required field without any default."
    },
    {
      "location": "path",
      "name": "path",
      "description": "Missing value for required field without any default."
    },
    {
      "location": "path",
      "name": "header",
      "description": "Missing value for required field without any default."
    },
    {
      "location": "path",
      "name": "querystring",
      "description": "Missing value for required field without any default."
    }
  ]
}

My specific use case is that I have a single view that can handle 2 distinct content-type simultaneously. Therefore, it is decorated with distinct schema references for the corresponding content-type representation, but I must explicitly ignore the "headers" validator, otherwise both fail against the opposite definition (not sure why they are not handled automatically by the appropriate renderer and/or accept, but maybe this another issue...). Anyway, this leads to a definition similar to the following:

@sd.some_service.get(
    schema=SomeSchemaHTML(),
    accept="text/html",
    validators=[colander_path_validator, colander_querystring_validator],
    renderer="templates/some.mako",
    response_schemas={"200": HTMLReponse()},
)
@sd.some_service.get(
    schema=SomeSchemaJSON(),
    accept="application/json",
    validators=[colander_path_validator, colander_querystring_validator],
    renderer="json",
    response_schemas={"200": JSONReponse()},
)
def some_view(request): ...

Is the above the correct use? So far, I have used multi-decorator service/views for a while (to support redirects or otherwise "compatible" URI for similar contents), and they seemed to work correctly and as intended. My only recent addition is the validators, and I would like to know if the list approach is valid. It seems listing validators is supported after looking at the code, but maybe the use of multiple colander_[...]_validator is not supported? What would be the alternative?

fmigneault commented 5 months ago

@leplatrem Would like to get your insights about this. I don't think anyone else can guide me better than you. Thanks in advance!