cdimascio / express-openapi-validator

🦋 Auto-validates api requests, responses, and securities using ExpressJS and an OpenAPI 3.x specification
MIT License
918 stars 209 forks source link

Error about destructuring a property for missing request body -- on a GET #550

Open kutenai opened 3 years ago

kutenai commented 3 years ago

Describe the bug I have an API specification that is valid according to swaggerhub.com, where I author it. I submitted an issue previously about a pattern that failed, since I was using 'format', instead of 'pattern'

I have fixed that issue, so I no longer get a syntax error, but I'm getting an error when I call my api endpoints now.

The error is: Cannot destructure property 'content' of 'request.openapi.schema.requestBody' as it is null.

The problem is that I have no idea where this is coming from, but it only seems to happen on "GET" requests, where there is no body. As far as I know, that is proper formatting for openapi spec. Am I wrong?

To Reproduce Probably difficult. I might need some direction on where to debug the source code in order to narrow down the issue.

Actual behavior A call to certain API endpoints returns an error response with the exact output

Cannot destructure property 'content' of 'request.openapi.schema.requestBody' as it is null.

Expected behavior Well, if the API is valid (as indicated by swaggerhub.com), it should not raise an error. Also, requestBody should be empty or null in GET requests.

Examples and context I'm not sure, but a GET request with no defined request body I guess would be a good example.

kutenai commented 3 years ago

I should mention that if I back up to 4.9.x, it works fine. So far, this fails in the same way on 4.10.x and 4.12.x (latest), so it is consistent.

kutenai commented 3 years ago

Sorry, one more comment -- it is not even valid to add a requestBody to a GET request, swaggerhub raises an error.

cdimascio commented 3 years ago

@kutenai, thanks for the issue. Could u provide a canonical example that demonstrates the issue. If I have a reproducible example, I can get it a fix out relatively quickly. Feel free to post here or crate a github repo with the example and I'll have a look

kutenai commented 3 years ago

Yes, I can do that, but I'm under a deadline for a code release this week, AND I'm taking a week of vacation right after that (I know, not such a great plan!! but it's release to a test system only).

I'll get back on this next week when I finish. I'll find the smallest working bit that I can to make it work and commit it.

Cheers -- Ed

cdimascio commented 3 years ago

@kutenai no problems. once you post the example, I'll certainly have a look

enjoy your vacation!

lynchmattj commented 3 years ago

I just ran into this issue myself on version 4.12.8 and repro'd using this simple demo yaml:

openapi: 3.0.0
info:
  title: test
  version: '1.0'
servers:
  - url: 'http://localhost:3000'
tags:
  - name: user
paths:
  /user:
    get:
      description: Returns a user
      operationId: getUser
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
          description: OK
      summary: Get a user
      tags:
        - user
      x-eov-operation-handler: controllers/UserController
components:
  schemas:
    User:
      example:
        firstName: firstName
        lastName: lastName
        emailVerified: true
        dateOfBirth: '1997-10-31'
        id: 0
        email: email@email.com
        createDate: '2000-01-23'
      properties:
        id:
          description: Unique identifier for the given user.
          type: integer
        firstName:
          type: string
        lastName:
          type: string
        email:
          format: email
          type: string
        dateOfBirth:
          example: '1997-10-31'
          format: date
          type: string
        emailVerified:
          description: Set to true if the user's email has been verified.
          type: boolean
        createDate:
          description: The date that the user was created.
          format: date
          type: string
      required:
        - email
        - emailVerified
        - firstName
        - id
        - lastName
      title: User
      type: object
      x-examples:
        Alice Smith:
          id: 142
          firstName: Alice
          lastName: Smith
          email: alice.smith@gmail.com
          dateOfBirth: '1997-10-31'
          emailVerified: true
          signUpDate: '2019-08-24'
      x-tags:
        - user

The error I get is the same: Cannot destructure property 'content' of 'request.openapi.schema.requestBody' as it is null.

lynchmattj commented 3 years ago

I figured out my issue, which may or may not be the cause of @kutenai 's problem. It seems that somewhere between 4.9.x and 4.12.x the value of request.openapi.schema.requestBody for GET requests with no body switched from undefined to null and I was checking for undefined when destructuring but not null.

rocketmaniac commented 3 years ago

Thanks for posting the results of your digging, @lynchmattj ! I'm using the Controller.js code from openapi-generator for nodejs-express-server and it had this line:

if (request.openapi.schema.requestBody !== undefined) {

It's all fixed up now!

rocketmaniac commented 3 years ago

Unfortunately, I forgot that there is another issue that may force me back to 4.9.5...higher versions (at least up to 4.12.8) no longer set request.openapi.schema.requestBody.content['application/json'].schema.$ref, where appropriate. It leads to this bug, where the 'foo' parameter in the example code is not defined at runtime:

https://github.com/OpenAPITools/openapi-generator/issues/8140

The other option is to stop using reusable request bodies, which would be an unwelcome step backwards.

bogi158 commented 1 year ago

Hello, I am still getting this error Cannot destructure property 'content' of 'request.openapi.schema.requestBody' as it is null on version 4.13.8 and node v16.20.0. The request I am testing is a GET request.

EDIT: I have actually solved this, but it is not a problem of the validator library, this is a problem of using a >= 4 version of the validator with the code generated by the node express server generator. There are two things to fix:

// Controller.js
static collectRequestParams(request) {
  // Change from undefined to null
  if (request.openapi.schema.requestBody !== null) {
  // ...
  }
  // ...
  // Add this if here otherwise you will get "Cannot read properties of undefined (reading 'forEach')" error
  if (request.openapi.schema.parameters !== undefined) {
  // ...
  }
}
wilml commented 7 months ago

Thank you @bogi158! Its taken a lot to get the openapi nodejs-express-server generator working for me. I documented all the steps I had to take to get it working with node v20 and validator v4 here. Hope this helps others.