8

My nodejs app has an open-api.yaml file and express-openapi-validate validator. I'm doing a POST request which is working and the api validator doesn't return any errors:

curl --request POST 'http://localhost:33004/my-app/settings' --data-raw '{"serials":["1234","2355"]}' -H 'Content-Type: application/json'

In my open-api.yaml I have:

openapi: '3.0.0'
servers:
 - url: 'http://{host}/my-app'
   variables:
     host:
     enum:
       - 'localhost'
       ....
...
paths:
    /settings:
      ...
      post:
        tags:
          - 'settings'
        operationId: 'postSettings'
        requestBody:
          content:
            application/json:
              schema:
                type: object
                properties:
                  serials:
                    type: array
                    items:
                      type: string
...

Then I tried dockerizing my app - created a docker container, and ran it inside with the pm2-runtime. However, when I send the same request to the docker container when the app is running in it, I get error while validating request: request should have required property '.headers' . I have no property '.headers' mentioned in the open-api.yaml file.

I tried removing the validator middleware, and the request went through just fine. Can you help me understand what is the validator complaining about?

EDIT:

I managed to find the error object:

{
  "data": [
    {
      "dataPath": "",
      "keyword": "required",
      "message": "should have required property '.headers'",
      "params": {
        "missingProperty": ".headers"
      },
      "schemaPath": "#/required"
    }
  ],
  "name": "ValidationError",
  "statusCode": 400
}

needless to say I have no required headers property...

m144
  • 305
  • 3
  • 13
  • Try adding `-H "Content-Type: application/json"` to your curl command. Does this help? – Helen Mar 01 '21 at 13:05
  • Edited my question, the curl also included this header, just forgot to add it here in the question. It doesn't help... – m144 Mar 01 '21 at 13:28
  • Not sure if it matters, but YAML indentation is off - e.g. `tags`, `operationId` and `requestBody` must be inside `post`, not alongside it. Try validating your YAML in https://editor.swagger.io. – Helen Mar 01 '21 at 15:21
  • copy-pasta indentation problems, the format is fine in the code – m144 Mar 01 '21 at 16:08
  • Same problem or probably related: https://stackoverflow.com/questions/70656096/openapi-request-should-have-required-property-body – Oscar Jul 15 '22 at 22:21
  • Still happening with Node 18 and generator 6.0.1. – Oscar Jul 15 '22 at 23:45

3 Answers3

7

I had the same for all node versions <= 14 and for express-openapi-validator version <= 3.

Impossible to have the validator working with node version 16 and we were stuck to an old dev version because of it.

The solution was to migrate to express-openapi-validator v4.

The migration is explained here https://github.com/cdimascio/express-openapi-validator#upgrading-from-3x

This (v3):

const validator = new OpenApiValidator({
  apiSpec: openApiYaml,
  operationHandlers: __dirname
})
app.use(validator)

becomes (v4):

const validator = OpenApiValidator.middleware({
  apiSpec: 'src/openapi.yaml'
})
app.use(validator)

The code was originally generated by https://hub.docker.com/r/openapitools/openapi-generator-cli

Benjam
  • 1,401
  • 2
  • 16
  • 22
3

Might be a little late but hopefully will be useful for others.

The problem is related to this code (this is the compiled version)

...
const reqToValidate = Object.assign({}, req, { cookies: req.cookies
                    ? Object.assign({}, req.cookies, req.signedCookies) : undefined });
const valid = validator(reqToValidate);
...

on OpenApiValidator and the fact that Express req object use accessor get/set for headers, as a result Object.assign will not propagate headers information and consequenlty the validator function will not find the required headers properties, only rawHeaders is available.

As a quick fix I implemented the following:

const validator = this.openApiValidator.validate(method, path);
return (req, res, next) => {
    const reqToValidate = Object.assign({}, req, {
        cookies: req.cookies
            ? Object.assign({}, req.cookies, req.signedCookies) : undefined
    });
   
    if (!reqToValidate.hasOwnProperty('headers')) {
        reqToValidate.headers = req.headers;
    }
    return validator(reqToValidate, res, next);
};

which adapts Express request and propagate all required information regarding headers.

Benjam
  • 1,401
  • 2
  • 16
  • 22
  • 1
    Which file did you make this edit to? I'm running into the same issue after generating server stub using the below command: `./openapi-generator-cli.sh generate -i petstore.json -g nodejs-express-server -o petstore/` – Steve G Aug 24 '22 at 20:46
1

For future reference if others come here for this problem:

I finally found the issue: I was using FROM node:alpine in my Dockerfile, which indicates the latest version of node. However, my application was running on node 10.18.1

Once I changed to FROM:node:10.18.1-alpine the issue was resolved.

Apparently, the express-openapi-validate plugin has some issues in the latest node module, or so it seems.

m144
  • 305
  • 3
  • 13
  • same problem, this worked for me in `v14.16.1` – ecoologic May 06 '21 at 06:13
  • Unfortunately this solution is not viable forever, the latest node version supporting this is not the current LTS anymore. – Benjam Jan 23 '22 at 22:08
  • 1
    I'm running Node 18.6.0 and am dead in the water with the same problem. Trying to test my API with the Node/Express combo and it's 100% no-go because every query fails with this header complaint. The server was generated by openapi-generator version 6.0.1. – Oscar Jul 15 '22 at 19:55
  • Same problem for me. It's so frustrating, after spending days trying out swagger and having issues. I spend another day getting openAPITools working and now I have to use Node 10? – Steve G Aug 24 '22 at 20:26