Validation and security

Requests are checked against their operation: path, query, header and cookie parameters in every style, and JSON, XML, form and multipart bodies. A request that doesn’t match is answered with 422 and the problems, a body that can’t be parsed (JSON, XML, multipart) with 400, an unknown media type with 415. Security requirements are checked for presence (API keys, HTTP basic and bearer, OAuth2 and OpenID Connect tokens; 401 with WWW-Authenticate), and against configured credentials in enforce mode (403). Responses the mock makes are checked too: problems are logged and counted in X-Apigenie-Mock-Violations, or answered with 500 under --strict.

Schemas’ format values are checked as the OpenAPI format registry defines them, for the JSON types each format applies to (int8 ranges, http-date, decimal, language, …); validation.formats: false turns these checks off. Formats of your own, declared in openapi.custom_formats of the configuration file, are accepted as they are, and an entry there naming a registry format replaces that format’s type and its check.

XML bodies

Bodies of application/xml, text/xml and +xml media types are parsed as XML 1.0 with namespaces, mapped to a JSON value as the schema’s xml objects describe it, and checked against the schema like JSON bodies; the mock, the validating proxy and apigenie test do the same, and the mock and apigenie test --generate write XML the same way in reverse. For this schema

Order:
  type: object
  xml: {name: order, namespace: "urn:orders", prefix: o}
  properties:
    id: {type: integer, xml: {nodeType: attribute}}   # OpenAPI 3.0/3.1: attribute: true
    customer: {$ref: "#/components/schemas/Customer"} # Customer has xml: {name: Buyer}
    note: {type: string, xml: {nodeType: cdata}}
    tags: {type: array, items: {type: string, xml: {name: tag}}}
    lines:
      type: array
      xml: {name: Lines, nodeType: element}           # 3.0/3.1: wrapped: true
      items: {$ref: "#/components/schemas/Line"}      # Line has xml: {name: Line}

the body is

<o:order xmlns:o="urn:orders" id="7">
  <Buyer><name>Ann</name></Buyer>
  <![CDATA[Leave at the <door>]]>
  <tag>a</tag><tag>b</tag>
  <Lines><Line sku="x"><quantity>2</quantity></Line></Lines>
</o:order>
  • The root element is named by the schema’s xml.name, else by the component a $ref points to; another name is a xml-root violation. A schema without either names no root.
  • A property is a child element named by its xml.name (its own, or that of the schema it references), else by the property name. nodeType: attribute makes it an attribute, text and cdata the element’s character data.
  • An array’s items repeat in the parent element, named by the items’ xml.name or the property name; with nodeType: element (wrapped: true) they sit in a wrapper element.
  • A declared xml.namespace must match; without one, elements are matched by local name in any namespace. An element with a property’s local name in another namespace isn’t that property: it is kept as {namespace}name, so the property is missing and additionalProperties: false reports the element.
  • Child elements are written in the order the schema declares its properties, as XML Schema sequences require.
  • Text becomes an integer, number, boolean or null where the schema allows it (white space around such values is ignored); xsi:nil="true" is null. Elements and attributes the schema doesn’t declare are kept by local name, so additionalProperties: false reports them.
  • A body that isn’t well-formed is malformed-xml (request.body.malformed, answered with 400; response.body.malformed), with its line and column. Document type declarations are refused, so external entities and entity expansion are errors.

A SOAP service described in WSDL 1.1 is served after apigenie convert --to openapi31: the converted document describes the SOAP envelopes with these xml objects.

Was this helpful?