Gi60s / openapi-enforcer

Apache License 2.0
94 stars 22 forks source link

Recursion error when receiving Json object in the body #160

Closed alexayalaa closed 5 months ago

alexayalaa commented 6 months ago

It turns out that I have a problem with the openapi enforcer Middleware library, initially I am creating an instance to validate a series of openapi either version 2.0 or 3.0 it works correctly but when There is a very complex structure in the Body that generates a recursion error at the level of the internal object, for example:

{
    "data": [
        {
            "account": {
                "type": "SAVINGS_ACCOUNT",
                "number": "91200244139"
            }
        }
    ]
}

.... I send this structure and when I trace it it generates this when I print the incoming value: { data: [ { account: [Object] } ] } does the type validation correctly but is not going deeper than object especially this part, [Object]... I would like to know if we can make a solution or if I am overlooking something or if a body recursion function is needed, I am very attentive to your response and thank you very much for your attention .

Gi60s commented 6 months ago

Hello @alexayalaa and thank you for the issue. The library is set up for both nested and recursive objects and schemas. It is possible that there is a bug somewhere though.

To look more into this, will you please share with me the relevant parts of your OpenAPI schema definition file? Better yet, if you have a repo that I could look at to see your code that could help too.

Thank you for using the OpenAPI Enforcer library.

alexayalaa commented 6 months ago

hello men this is my code: import express from 'express'; import { Enforcer } from 'openapi-enforcer'; import middleware from 'openapi-enforcer-middleware'; const app = express(); const port = 3000; // Function to perform recursive transformation of the object const transformObject = (obj: any): any => { if (typeof obj === 'object') { if (Array.isArray(obj)) { return obj.map((item: any) => transformObject(item)); } else { const transformedObj: any = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { if (key === 'data' && Array.isArray(obj[key]) && obj[key][0] .hasOwnProperty('account')) { console.log(Processing data array: ${JSON.stringify(obj[key], null, 2)}); transformedObj[key] = obj[key].map((item: any) => { console.log(Processing account object: ${JSON.stringify(item. account, null, 2)}); return { account: transformObject(item.account) }; }); } else { transformedObj[key] = transformObject(obj[key]); } } } return transformedObj; } } return obj; };

async function startServer() { console.log('Iniciando el servidor...'); const options = { componentOptions: { requestBody: { dereference: { circular: true } }, exceptionSkipCodes: ['WSCH001', 'WOPE003', 'WSCH007', 'EDEV001', 'WSCH006', 'WRES001'], }, }; app.use(express.json()); const enforcer = await Enforcer('./api/openapi.yaml', options); // Custom middleware to transform the request body app.use((req, res, next) => { req.body = transformObject(req.body); console.log('Before Enforcer Request Validation. Modified Body:', req. body); next(); }); app.use(middleware(enforcer).init()); app.post('/accounts/retrieve-basic', async (req, res) => { console.log( 'Ruta específica /accounts/retrieve-basic:', 'Cuerpo de la solicitud antes de transformar:', JSON.stringify(req.body, null, 2) ); try { // Resto del código... res.status(200).json({ message: '¡Éxito!' }); } catch (err) { console.error('Error al procesar la solicitud:', err); res.status(500).json({ message: 'Error interno del servidor' }); } }); app.listen(port, () => { console.log(Servidor corriendo en http://localhost:${port}); }); } startServer().catch((err) => { console.error('Error iniciando el servidor:', err)}) and i will add the openapi for my case this is the body that in in the middleware { data: [ { account: [Object] } ] } and i send this body { "data": [ { "account": { "type": "CUENTA_DE_AHORRO", "number": "91200244139" } } ] } the only thing that i need is to validate the request have the same structure an the all params with the openapi.yaml. El mar, 9 de ene de 2024, 12:28 p. m., James Speirs < @.***> escribió:

Hello @alexayalaa https://github.com/alexayalaa and thank you for the issue. The library is set up for both nested and recursive objects and schemas. It is possible that there is a bug somewhere though.

To look more into this, will you please share with me the relevant parts of your OpenAPI schema definition file? Better yet, if you have a repo that I could look at to see your code that could help too.

Thank you for using the OpenAPI Enforcer library.

— Reply to this email directly, view it on GitHub https://github.com/Gi60s/openapi-enforcer/issues/160#issuecomment-1883485566, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGE4O7TFSDWI5ACFRDSB6HTYNV42BAVCNFSM6AAAAABBTILB7SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQOBTGQ4DKNJWGY . You are receiving this because you were mentioned.Message ID: @.***>

-- El contenido de este mensaje y sus anexos son únicamente para el uso del destinatario y pueden contener información  clasificada o reservada. Si usted no es el destinatario intencional, absténgase de cualquier uso, difusión, distribución o copia de esta comunicación.

Gi60s commented 6 months ago

Will you please also share your openapi.yaml file and the method, path, and body of the request that you're sending into the system?

Thank you.

Gi60s commented 6 months ago

I just saw that your response does include the body. Please share the openapi document. I might be able to figure out the rest.

alexayalaa commented 6 months ago

Hello James, yes of course the yaml I sent you is the openapi.yaml only that is the original name, I already sent you the consumption Curl for that api:

Hello James, yes of course the yaml I sent you is the openapi.yaml only that is the original name, I already sent you the consumption Curl for that api:

curl --location 'http://localhost:3000/accounts/retrieve-basic' \ --header 'Content-Type: application/json' \ --data '{ "data": [ { "account": { "type": "SAVINGS_ACCOUNT", "number": "91200244139" } } ] }'

that is with that you can consume the endpoint, and i will add the openapi.yaml beforehand thank you so much, i hope that we can solve the bug and i am waiting for your response or if you need anything.

El mié, 10 ene 2024 a las 0:51, James Speirs @.***>) escribió:

I just saw that your response does include the body. Please share the openapi document. I might be able to figure out the rest.

— Reply to this email directly, view it on GitHub https://github.com/Gi60s/openapi-enforcer/issues/160#issuecomment-1884233779, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGE4O7VYCKC3ZYFB6QT5C73YNYT6ZAVCNFSM6AAAAABBTILB7SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQOBUGIZTGNZXHE . You are receiving this because you were mentioned.Message ID: @.***>

-- El contenido de este mensaje y sus anexos son únicamente para el uso del destinatario y pueden contener información  clasificada o reservada. Si usted no es el destinatario intencional, absténgase de cualquier uso, difusión, distribución o copia de esta comunicación.

Gi60s commented 6 months ago

I'm not seeing your yaml. I noticed that you are using email to reply to the comments instead of using the gitlab webpage where you posted the issue. Maybe try visiting the gitlab page where you posted the issue and adding the yaml there.

alexayalaa commented 6 months ago

Hello James, no problem this is the link https://we.tl/t-bwPKpZWn8z can you test if you can download the file please.

El jue, 11 ene 2024 a las 0:20, James Speirs @.***>) escribió:

I'm not seeing your yaml. I noticed that you are using email to reply to the comments instead of using the gitlab webpage where you posted the issue. Maybe try visiting the gitlab page where you posted the issue and adding the yaml there.

— Reply to this email directly, view it on GitHub https://github.com/Gi60s/openapi-enforcer/issues/160#issuecomment-1886261437, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGE4O7WQNOHTZOJBABAWRN3YN5ZBXAVCNFSM6AAAAABBTILB7SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQOBWGI3DCNBTG4 . You are receiving this because you were mentioned.Message ID: @.***>

-- El contenido de este mensaje y sus anexos son únicamente para el uso del destinatario y pueden contener información  clasificada o reservada. Si usted no es el destinatario intencional, absténgase de cualquier uso, difusión, distribución o copia de esta comunicación.

Gi60s commented 5 months ago

I don't know that I'm seeing the same error as you based on what you provided me. This is the error I see when making the request:

Request has one or more errors
  In body
    Invalid value
      at: data > 0 > account
        Did not validate against all schemas
          at: 0 > type
            Value "SAVINGS_ACCOUNT" did not meet enum requirements

When I change the request to use CUENTA_DE_AHORRO for the type it is successful. So here is a successful request:

POST localhost:3000/accounts/retrieve-basic
{
    "data": [
        {
            "account": {
            "type": "CUENTA_DE_AHORRO",
            "number": "91200244139"
            }
        }
    ]
}
alexayalaa commented 5 months ago

Yes, but when i try to see what is the Json that enter in the library appears of the difference way { data: [ { account: [Object] } ] } I need to validate all the body, complete and the library are not validating the object intern in this case [object].

El vie, 12 de ene de 2024, 12:38 a. m., James Speirs < @.***> escribió:

I don't know that I'm seeing the same error as you based on what you provided me. This is the error I see when making the request:

Request has one or more errors In body Invalid value at: data > 0 > account Did not validate against all schemas at: 0 > type Value "SAVINGS_ACCOUNT" did not meet enum requirements

When I change the request to use CUENTA_DE_AHORRO for the type it is successful. So here is a successful request:

POST localhost:3000/accounts/retrieve-basic { "data": [ { "account": { "type": "CUENTA_DE_AHORRO", "number": "91200244139" } } ] }

— Reply to this email directly, view it on GitHub https://github.com/Gi60s/openapi-enforcer/issues/160#issuecomment-1888465845, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGE4O7VDU4DXYM3GRXHLQGLYODD4LAVCNFSM6AAAAABBTILB7SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQOBYGQ3DKOBUGU . You are receiving this because you were mentioned.Message ID: @.***>

-- El contenido de este mensaje y sus anexos son únicamente para el uso del destinatario y pueden contener información  clasificada o reservada. Si usted no es el destinatario intencional, absténgase de cualquier uso, difusión, distribución o copia de esta comunicación.

Gi60s commented 5 months ago

Could you record a video demonstrating what you are seeing?

alexayalaa commented 5 months ago

Hello James, thank you very much in advance for the help, since through github issues it only allows 10mb I decided to upload the video ( https://we.tl/t-tvgoTTP2Zu )on the same WeTranfer platform, the video I want to show you that the body arrives in the library and it validates almost everything except what it has inside [Object] in my case it is this { data: [ { account: [Object] } ] } it correctly generates the external validations but not the internal one in that case [Object], which prevents validating if the values ​​are being sent correct and it is not matching with the openapi.yaml since all the parameters are required, it is ignoring them.

Gi60s commented 5 months ago

@alexayalaa Thanks for sending the video. I now understand what the issue is. What you're running into is simply the way that node logs objects to the console. This has nothing to do with the OpenAPI Enforcer.

The reason that some of your logs show the complete object instead of just { data: [ { account: [Object] } ] } is because you're converting those objects into a string prior to logging them to the console.

In node, objects that are logged to the console will be shortened automatically by node to improve log readability. If you want to see the entire object you'll need to stringify it first.

I've taken a screenshot of your code, highlighting the two spots where one is logged as a string and the other is logged as an object. I hope that answers your questions. Good luck and happy coding.

image