cloudflare/chanfana

Response body/format validation

Opened this issue ยท 2 comments

I just found out that itty-router-openapi was renamed/changed to chanfana, and I really like the concept ๐Ÿ‘
Class-based endpoints and then either using Hono or itty-router.

I wanted to try and created a new app using

npm create cloudflare@latest -- --type openapi
npm i chanfana --save

One part I'm missing is body response validation is that correct?

"Funny" thing is that even some of the example endpoints generated with -type openapi do not follow the defined response schema, e.g.:

import { OpenAPIRoute, OpenAPIRouteSchema } from '@cloudflare/itty-router-openapi';
import { Task } from '../types';

export class TaskCreate extends OpenAPIRoute {
  static schema: OpenAPIRouteSchema = {
    tags: ['Tasks'],
    summary: 'Create a new Task',
    requestBody: Task,
    responses: {
      '200': {
        description: 'Returns the created task',
        schema: {
          success: Boolean,
          result: {
            task: Task,
          },
        },
      },
    },
  };

  async handle(request: Request, env: any, context: any, data: Record<string, any>) {
    // Retrieve the validated request body
    const taskToCreate = data.body;

    // Implement your own object insertion here

    // return the new task
    return {
      success: true,
      task: {
        name: taskToCreate.name,
        slug: taskToCreate.slug,
        description: taskToCreate.description,
        completed: taskToCreate.completed,
        due_date: taskToCreate.due_date,
      },
    };
  }
}

The response should contain { success: true, result: { task: .. } } as defined in the schema, and not { success: true, task: .. } as actually returned.

Validating (and/or auto cleaning) responses is important for:

  • making sure returned data is as defined in schema (e.g. error when missing properties)
  • making sure no unwanted properties are returned that are not in schema.

Especially the latter is important when e.g. quering records from a database, but not all properties should be exposed.

What I'm doing currently is:

  ..
  async handle(c) {
    const data = await this.getValidatedData<typeof this.schema>();
    const task = .. // query task from database
    const resp = TaskShema.parse(task);
    return c.json(resp);
  }

This uses the zod parse function on the TaskSchema to validate all required properties are there, and cleans out all properties part of the task, but not part of the schema.

I'm wondering if this is the best approach, or chanfana could provide something for this out of the box?

G4brym commented

Hey @marceloverdijk sorry about the confusion, the command npm create cloudflare@latest -- --type openapi is still using an old template from itty-router-openapi. I have a pull request ready to update it to chanfana, but it didn't get release yet due to some company policies about release timings (pr here).

I think it makes sense for chanfana to also check for the response formats. It should be a 2-step validation, first typescript error when the returning object is not in the same format, and then clean the response object to allow only defined arguments to be returned.
I'm not sure when i will have time to implement this feature, so your way of handling this makes total sense until then.

Thx @G4brym for sharing! I will pay attention to that PR.
Although C3 can work with templates from git, I'm not sure if it can use specific branches.

โฏ npm create cloudflare@latest openapi-test -- --template https://github.com/G4brym/wrangler2/tree/update-c3-openapi-template/templates/worker-openapi

using create-cloudflare version 2.21.8

โ•ญ Create an application with Cloudflare Step 1 of 3
โ”‚ 
โ”œ In which directory do you want to create your application?
โ”‚ dir ./openapi-test
โ”‚
โ”œ What type of application do you want to create?
โ”‚ type Worker built from a template hosted in a git repository
โ”‚
โ”œ What's the url of git repo containing the template you'd like to use?
โ”‚ repository https://github.com/G4brym/wrangler2/tree/update-c3-openapi-template/templates/worker-openapi
โ”‚
โ”œ Cloning template from: https://github.com/G4brym/wrangler2/tree/update-c3-openapi-template/templates/worker-openapi 
โ”‚ template cloned and validated
โ”‚ 
โ•ฐ  ERROR  create-cloudflare templates must contain a "wrangler.toml" file.
npm ERR! code 1

But for now I will just copy some setup from your repo into my project ;-)

Also thx for confirming the way I'm handling the response body validation.
I guess we can keep this issue open to track this new feature to support this response body validation/cleaning out of the box.