Code Monkey home page Code Monkey logo

Comments (4)

willfarrell avatar willfarrell commented on June 9, 2024

You don't need two validator middleware, event and response can be handled by one. I would suggest adding in http-error-handler to properly catch the error. Everything else looks fine otherwise.

from middy.

MohamedYehia1998 avatar MohamedYehia1998 commented on June 9, 2024

@willfarrell
Thank you for your input.

Unfortunately the issue still remains. I updated my middlewareWrapper to eliminate any uncertainties.
And this these are the middy packages I am using and their versions

    "@middy/core": "^3.6.2",
    "@middy/http-cors": "^3.6.2",
    "@middy/http-error-handler": "^3.6.2",
    "@middy/http-json-body-parser": "^5.0.3",
    "@middy/validator": "^5.0.3",

Problematic Endpoint

import middlewareWrapper from '../../utils/middlewareWrapper.js'
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { PutCommand, DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
import { v4 as uuid } from 'uuid';
import { eventSchema, responseSchema } from '../../specifications/createTodo.js';

const createTodo = async (event) => {
  const client = new DynamoDBClient({});
  const docClient = DynamoDBDocumentClient.from(client);

  const todo = event.body;
  const user = JSON.parse(event.requestContext.authorizer.user);

  const params = {
    TableName: process.env.TODOS_TABLE,
    Item: {
      userId: user.sub,
      todoId: uuid(),
      createdAt: new Date().toISOString(),
      name: todo.name,
      dueDate: todo.dueDate,
      done: false,
    }
  };

  const command = new PutCommand(params);

  await docClient.send(command);

  return {
    statusCode: 201,
    body: {item:{...params.Item}},
  }
}
export const handler = middlewareWrapper({handler: createTodo, eventSchema, responseSchema})

Middleware Wrapper

import middy from '@middy/core'
import cors from '@middy/http-cors'
import httpErrorHandler from '@middy/http-error-handler'
import httpJsonBodyParser from '@middy/http-json-body-parser'
import validator from '@middy/validator'

const middleware = (config) => {
    const {handler, eventSchema, responseSchema} = config
    
    return middy()
        .use(httpJsonBodyParser())
        .use(cors())
        .use(validator({eventSchema, responseSchema}))
        .use(httpErrorHandler())
        .handler(handler)
}

export default middleware;

Schemas

import { transpileSchema } from '@middy/validator/transpile'

const eventSchema = transpileSchema({
  type: 'object',
  required: ['body'],
  properties: {
    body: {
      type: 'object',
      required: ['name', 'dueDate'],
      additionalProperties: false,
      properties: {
        name: { type: 'string' },
        dueDate: { type: 'string' }
        // schema options https://ajv.js.org/json-schema.html#json-data-type
      }
    }
  }
})

const responseSchema = transpileSchema({
  type: 'object',
  required: ['body', 'statusCode'],
  properties: {
    body: {
      type: 'object',
      properties: {
        item: { 
          type: 'object' ,
          required: ['name', 'dueDate', 'userId', 'todoId', 'createdAt'],
          properties: {
            name: { type: 'string' },
            dueDate: { type: 'string' },
            userId: { type: 'string' },
            todoId: { type: 'string' },
            createdAt: { type: 'string' }
            // schema options https://ajv.js.org/json-schema.html#json-data-type
          } 
        },

      },

    },
    statusCode: {
      type: 'number'
    }
  }
})

export {eventSchema, responseSchema}

Despite using http-error-handler, this error does not show up in cloud watch.
image

When I return my response body as a string, the validation error shows up on cloud watch nonetheless
image

I am not sure the http-error-handler does not behave as expected as well.
Postman returns in the 2 cases
image

from middy.

MohamedYehia1998 avatar MohamedYehia1998 commented on June 9, 2024

@willfarrell
Upon using the http-response-serializer in conjunction with the rest of the middleware and returning my response as an object, the the response validator sees the data.

The problem now is narrowed down to the failed validation.

http-error-handler is not showing me the exact issue on my postman console (I merely get Internal server error)
and sadly the cloudwatch logs do not show the complete messge.

image

The http-error-handler catches the error from failed event validation nonetheless! But not the response

from middy.

MohamedYehia1998 avatar MohamedYehia1998 commented on June 9, 2024

Issue Resolved

To validate the response I had to use the validator middleware AND the httpResponseSerializer.
The lambda function should return an object (not a string).

The sequence of the middleware below dictates that those operations take place after the the lambda function returns a response in JSON not string in this sequece:

  1. The response is validated with the middy middleware (it receives it as JSON).
  2. The http response is serialized
  3. The relevant headers for CORS are inserted.

Without the http response serialization, it does not work.
@willfarrell please confirm this and if that's the case please update the documentation :)

lambda response

  return {
    statusCode: 201,
    body: Object({item:{...params.Item}}),
  }
``
**middleware**

const middleware = (config) => {
const { handler, eventSchema, responseSchema, parseJSON } = config

const middlewares = []

if (parseJSON || parseJSON === undefined) {
    middlewares.push(httpJsonBodyParser())
}

if (eventSchema || responseSchema) {
    const validatorObject = {};
    if (eventSchema) {
        validatorObject.eventSchema = eventSchema;
    }
    if (responseSchema) {
        validatorObject.responseSchema = responseSchema;
    }
    middlewares.push(validator(validatorObject))
}

return middy()
    .use(cors())
    .use(httpResponseSerializer({
        serializers: [
            {
                regex: /^application\/xml$/,
                serializer: ({ body }) => `<message>${body}</message>`
            },
            {
                regex: /^application\/json$/,
                serializer: ({ body }) => JSON.stringify(body)
            },
            {
                regex: /^text\/plain$/,
                serializer: ({ body }) => body
            }
        ],
        defaultContentType: 'application/json'
    }))
    .use(middlewares)
    .use(globalErrorHandler())
    .handler(handler)

}

from middy.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.