Skip to content

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 04 Sep 21:03
· 62 commits to master since this release
4215613
  • Fixed. OAS 3.0 documents that use a boolean additionalProperties no
    longer fail validation (#49). additionalProperties was grouped with items
    and not, which really do forbid a boolean before OAS 3.1, but the 3.0
    specification spells this one out as "Value can be boolean or object" — and
    additionalProperties: false is the standard closed-object idiom of the 3.0
    corpus. The document loaded and then every validateRequest() /
    validateResponse() threw UnsupportedSchema.

  • Fixed. A property whose name is numeric or whose schema is a boolean is
    validated instead of being silently dropped (#50). PHP normalizes the array
    key "2020" to an integer, and the directional filter discarded any member
    it did not recognise — together with its required entry — so the whole
    declaration went unchecked in both directions, with no diagnostic. Direction
    (readOnly/writeOnly) is now the only reason a property is dropped;
    anything else is passed through for the compiler and the backend to judge,
    and the compiler no longer rejects an integer-normalized name in properties
    or $defs.

  • Fixed. A boolean property schema in a form or multipart body no longer
    escapes as a bare InvalidArgumentException out of validateRequest()
    (#51). The body decoders read properties through a helper that accepted
    object schemas only; a boolean member now maps to the unconstrained schema
    for decoding, and the backend enforces what the boolean says.

  • Internal. MediaType::isJson() normalizes its own argument, like the
    twin helper in property-testing-openapi. It assumed a pre-normalized value,
    so the answer depended on which caller had remembered to normalize first —
    the same asymmetry that hid a multipart bug in mediaMatches() until 0.5.1.

  • Fixed. A + in the query string is read as a space (#52). A query is
    application/x-www-form-urlencoded content, so + spells a space — which is
    what an HTML form submits over GET and what every SAPI hands the application.
    Percent-decoding it literally reported a violation for the exact value the
    application receives as correct, and disagreed with this package's own form
    body decoder, which has always folded + first.

  • Fixed. A query or cookie key with no = carries the empty value instead
    of failing deserialization (#53). An exploded object parameter is handed
    every pair a sibling parameter does not claim, so one stray &flag in the
    request failed an unrelated parameter. The styles that have no valueless
    form — simple, label, matrix — stay strict.

  • Fixed. A multipart body whose closing delimiter carries no trailing CRLF,
    or is followed by an epilogue, is accepted (#54). RFC 2046 §5.1.1 makes both
    legal and league/openapi-psr7-validator accepts them; requiring the exact
    bytes --<boundary>--\r\n turned a conforming client into a
    request.body.decode violation. A body with no parts at all stays rejected —
    the same clause requires at least one — and tests/Differential/ now pins
    every one of these four verdicts against league.

  • Fixed. encoding.contentType is honoured for
    application/x-www-form-urlencoded bodies (#55). It was neither applied nor
    rejected, so a property declared application/json arrived as a string,
    failed its own object schema, and was reported as request.body.schema — a
    valid request called invalid, with a message pointing away from the cause.
    A JSON media type is now decoded and validated against the property schema;
    any other is validated as the string it already is, the rule an undecoded
    body already follows.

  • Fixed. A declared multipart part header is validated against its schema,
    not merely checked for presence (#58). The constraint was stated by the
    document and enforced by nothing, while the same declaration on a response
    header was fully validated. A part header is read with the simple style,
    like a request header parameter; a content-form or non-simple declaration
    fails closed rather than passing an unchecked value through.

  • Fixed. A path template whose placeholder shares its segment with literals
    — /report.{format}, /v{version}/items, /{a}-{b} — is matched (#56). Such
    a path compiled and then matched nothing at all, so the operation was
    unreachable, and a request that literally equalled the template was blamed for
    a missing parameter instead. Concrete paths still win over templated ones, a
    decoded separator still cannot escape a segment, and the literal runs are
    matched as written.

  • Fixed. A parameter violation renders its actual value again (#63).
    redactsActual() returned true for header, cookie, query and body —
    every location a violation normally carries — so expected was printed in
    full, schema and all, beside an actual that always said [redacted]. The
    class already carried a name-based rule written for exactly those locations
    and unreachable behind the location check. It decides now, and it is applied
    to container members too, so a credential sitting under a member name the
    instance path does not reach is still replaced. Bodies stay redacted
    wholesale: their member names belong to the application, and a whole-body
    violation has the instance path $.

  • Changed. Schema compilation is cached per Contract instance, keyed by
    schema, direction and dialect. The directional rewrite, the JSON round trip
    and the backend's parse ran on every validated message, which made
    fromArray() a parser and validateRequest() the compiler. Measured on a
    document with three parameters and a twenty-property body,
    validateRequest() went from 1.173 ms to 0.067 ms per call. The new
    ValidateRequestBench measures the hot path; the benchmark suite covered
    only response selection before.

  • Added. response.body.missing — a response that declares a schema and
    arrives with an empty body is a violation (#57), the mirror of
    request.body.missing. Checking only the bodies that arrived meant the one
    failure contract testing exists to catch, an endpoint answering 200 with
    nothing, was the one it passed. Excluded: 204, 304, every response to a
    HEAD request, and a media type entry declaring no schema or the
    unconstrained boolean one.