cloudflare / chanfana

OpenAPI 3 and 3.1 schema generator and validator for Hono, itty-router and more!
https://chanfana.pages.dev
MIT License
288 stars 38 forks source link

Empty body on post request #44

Closed altryne closed 1 year ago

altryne commented 1 year ago

Following the example code for requestBody I get an empty body in the handle function:

define the post like so:

router.post('/share', routes.ShareGPT)

Then my class:

export class ShareGPT extends OpenAPIRoute {
  static schema = {
    tags: ['sharegpt'],
    summary: 'Pass a JSON formatted conversation and receive a URL response from shareGPT',
    requestBody : {
      avatarUrl: new Str({
        description: 'Avatar URL',
        example: 'https://sharegpt.com/img/logo.png',
        required: false
      }),
      items: [
        {
          from: fromEnum,
          value: new Str({
            description: 'HTML formatted single message text',
            example: 'Hello, how are you?'
          }),
        },
      ] 
    },
    responses: {
      '200': {
        schema: {
          url: 'https://shareg.pt/1234567890'
        },
      },
    },
  }

  async handle(request: Request, data: Record<string, any>) {
    const {body} = data

    const shareID = '123123'
    return json({url: `https://shareg.pt/${shareID}`})
  }
} 

and body and data are both empty.

What am I doing wrong?

altryne commented 1 year ago

Just confirmed that the same happens with the post example from the docs : https://github.com/cloudflare/itty-router-openapi#request-body-validation

altryne commented 1 year ago

Looks like the documentation has a bug, there's a second parameter called context that's getting passed.

So changing the handle call schema to :

  async handle(request: Request, env: any, _ctx, data: Record<string, any>) {

works!

ericlewis commented 1 year ago

I have also noticed that you have to add them when using with cloudflare workers, otherwise, data never works. The documents should also suggest this.

G4brym commented 1 year ago

Like everything, it depends, because if you register the event listener like the first section of the docs says:

addEventListener('fetch', (event) => event.respondWith(router.handle(event.request)))

you are only sending the request parameter to the router, and thus the endpoint will have the validated data in the 2º position, like this handler(request: Request, data: Record<string, any>)

And everything below this first section, build upon this definition sending only the request to the router

Otherwise, following the Cloudflare ES6 module worker example, and exporting the fetch function this way:

export default {
  fetch: router.handle
}

Will result in the handler function receiving all ES6 parameter, and looking like this handler(request: Request, env, context, data: Record<string, any>)

But I agree, that the problem for all of this relies on the documentation not being clear about this. I'm thinking on changing all example to explicitly be like the ES6 example, and adding a new advanced usage section showing how can you define a worker, and not sending all parameters, or even sending additional parameters

G4brym commented 1 year ago

I've updated the README.md to always use the Cloudflare ES6 Module Worker format and all default parameters Let me know if you think the docs should be improved elsewere 😄