Skip to content

Feature request: opt-in strict validation when response Content-Type is not declared in spec #477

Description

@whoward

Problem
When Committee::Middleware::ResponseValidation processes a response whose Content-Type doesn't match any media type declared in the spec's content block for that operation, it silently skips body schema validation entirely. The request passes as if it were valid.

This creates a false-confidence problem: a response carrying a content type that the spec doesn't declare at all will pass committee without any schema checking occurring. There's no way to know from the outside whether committee actually validated the response body or quietly gave up.

Why it's hard to solve from outside the middleware
The silent-skip is hardcoded deep in the validation flow. openapi_parser's select_media_type_from_content returns nil when no match is found, and committee's response validation does return unless media_type — the skip. There is no hook, option, or callback to change this behaviour.

The only workarounds available from outside the middleware are:

  • Monkey-patching OpenAPIParser::Schemas::Response#select_media_type directly — brittle and global
  • Wrapping the app in a custom Rack layer that re-implements committee's path-matching logic just to replicate the content-type lookup - duplicates internals

Proposed solution
Add an opt-in option — strict_response_content_type: true (or whatever name feels right) - to Committee::Middleware::ResponseValidation. When enabled:

  • If select_media_type_from_content returns nil for a response
  • And the spec declares at least one media type for that operation's response (i.e. the content hash is non-empty)
  • Raise Committee::InvalidResponse identifying the undeclared content type

The guard on content being non-empty matters: operations with no declared response body schema (bare 204 No Content, response objects with no content block) should still pass silently — the strictness only kicks in when the spec has opinions about what the content type should be and the actual response disagrees.

Defaulting to false preserves full backwards compatibility.

I'm happy to implement this if the approach sounds reasonable to you.

This seems to be similar to a previous issue #317 which implemented a similar approach but for response codes

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions