Hilzu / express-openapi-validate

Express middleware to validate requests based on an OpenAPI 3 document
Apache License 2.0
75 stars 12 forks source link

Unable to validate integer parameter in path #78

Closed lynchs61 closed 2 years ago

lynchs61 commented 2 years ago

I'm having trouble getting a correct validation for a parameter in path. I have the following in my API spec.

/v1/tick/{sequence}:
    get:
      parameters:
        - in: path
          name: sequence
          schema:
            type: integer
          description: The sequence number of the tick
          required: true
      tags:
        - Tick
      summary: Get a tick by sequence number
      operationId: GetSingleTick
      responses:
        "200":
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/tick'

And this is the setup of my express router:

// app.js
const tickRouter = require('./routes/tick');
app.use('/v1/tick', tickRouter);
// routes/tick.js
router.get('/:sequence', validator.validate('get', '/v1/tick/{sequence}'), (req, res, next) => {
  // Get the tick from DB and return
});

But when I make a call to the endpoint like this:

localhost:3000/v1/tick/290487

I get the following error saying that the parameter must be an integer:

{
    "error": {
        "name": "ValidationError",
        "message": "Error while validating request: request/params/sequence must be integer",
        "data": [
            {
                "instancePath": "/params/sequence",
                "schemaPath": "#/properties/params/properties/sequence/type",
                "keyword": "type",
                "params": {
                    "type": "integer"
                },
                "message": "must be integer"
            }
        ]
    }
}

Is this a bug? Or am I missing something important here?

lynchs61 commented 2 years ago

Nevermind. I figured it out and it was a misunderstanding I had with express routing. So I'll post it here in case anyone else runs into something similar.

I just thought that express would magically know that the incoming parameter should be an integer. But this is obviously not the case. So I had to add the following extra middleware to the route to first try to parse the parameter as an integer before it gets to the validator.

const convertSequenceToInt = (req, res, next) => {
  req.params.sequence = parseInt(req.params.sequence, 10);
  next();
};

Then my route is setup as follows with the conversion middleware before the validator:

// routes/tick.js
router.get('/:sequence', [convertSequenceToInt, validator.validate('get', '/v1/tick/{sequence}')], (req, res, next) => {
  // Get the tick from DB and return
});

And now everything works as expected and is validated correctly.