Skip to content

Recipes

Authentication

Generally you just need to follow one of the Authentication guides here, depending on the type of authentication you're using.

Bearer Auth Example

ts
const app = new Hono().get(
  '/example',
  openApi({
    responses: {
      200: z.object({}),
    },
    security: [{ bearerAuth: [] }],
  }),
  async (c) => {
    return c.json({}, 200);
  },
);

createOpenApiDocument(app, {
  info: {
    title: 'Some API',
    version: '0.0.1',
  },
  components: {
    securitySchemes: {
      bearerAuth: {
        type: 'http',
        scheme: 'bearer',
      },
    },
  },
  // if you use bearer auth in every endpoint, you can add
  // this here instead of adding `security` to every route:
  // security: [{ bearerAuth: [] }],
});

Reusing Common Fields

Adding the same fields to various routes over and over can be a bit tedious. You can create your own typesafe wrapper, which will provide the fields shared by multiple endpoints. For example, if a lot of your endpoints require a security field and a tag, you can create a function like this:

ts
import { defineOpenApiOperation } from 'hono-zod-openapi';
import type {
  HonoOpenApiOperation,
  HonoOpenApiRequestSchemas,
  HonoOpenApiResponses,
} from 'hono-zod-openapi';

const taggedAuthRoute = <
  Req extends HonoOpenApiRequestSchemas,
  Res extends HonoOpenApiResponses,
>(
  doc: HonoOpenApiOperation<Req, Res>,
) => {
  return defineOpenApiOperation({
    ...doc,
    tags: ['MyTag'],
    security: [{ apiKey: [] }],
  });
};

And use it with the openApi middleware:

ts
openApi(
  taggedAuthRoute({
    request: {
      json: z.object({ field: z.number() }),
    },
  }),
);

Custom Error Handling

In general, hono-zod-openapi stays away from error handling and delegates it fully to zod-validator. zod-validator, however, accepts a third argument hook, using which you can intercept the validation result for every usage of the middleware. There is no direct equivalent for that in hono-zod-openapi, as in my experience it made more sense to create a custom middleware that wraps zod-validator and handles the errors in a unified way.

That approach is supported. You can create your own openApi middleware using createOpenApiMiddleware - it's used internally to create the openApi exported by the library.

Example with zod-validation-error

Using the excellent zod-validation-error library that translates ZodErrors into user-friendly strings:

ts
import { zValidator } from '@hono/zod-validator';
import { HTTPException } from 'hono/http-exception';
import { createOpenApiMiddleware } from 'hono-zod-openapi';
import { fromZodError } from 'zod-validation-error';
import * as z from 'zod';

// works exactly the same way as `openApi` exported by `hono-zod-openapi`
export const openApi = createOpenApiMiddleware((target, schema) =>
  zValidator(target, schema, (result, c) => {
    if (!result.success) {
      const validationError = fromZodError(result.error, {
        includePath: false,
      });
      // you can handle that in `new Hono().onError()` or just use e.g. `c.json()` directly instead
      throw new HTTPException(400, {
        message: validationError.message,
        cause: validationError,
      });
    }
  }),
);

If there is a need for handling errors on a case-by-case basis - create an issue and let's try to find a sensible solution for that!