middleware icon indicating copy to clipboard operation
middleware copied to clipboard

`@hono/zod-openapi`: App `basePath` is not used for OpenAPI route registration

Open SimulatedGREG opened this issue 10 months ago • 2 comments

Summary

OpenAPIHono#openapi does not take into account a custom basePath. The path provided to openAPIRegistry.registerPath is incorrect when the app instance has a custom basePath defined.

Basic Reproduction

import { OpenAPIHono, createRoute } from '@hono/zod-openapi'
import { swaggerUI } from '@hono/swagger-ui'

// all routes are prefixed with "/foo"
const fooApp = new OpenAPIHono().basePath('/foo')

const route = createRoute({
  method: 'get',
  summary: 'foobar',
  path: '/bar',
  responses: {
    200: {
      description: 'OK'
    }
  }
})

fooApp.doc('/doc', {
  openapi: '3.0.0',
  info: {
    version: '0.0.0',
    title: 'localhost',
  },
})
fooApp.get('/swagger-ui', swaggerUI({ url: '/foo/doc' }))

// This produces the proper endpoint "GET /foo/bar"
// but Swagger UI shows route as "GET /bar"
fooApp.openapi(route, c => c.text('OK'))

// using CF Worker as test environment
export default fooApp

Swagger UI

http://localhost:8787/foo/swagger-ui image

Testing "GET /foo/bar"

❯ http http://localhost:8787/foo/bar   
HTTP/1.1 200 OK
Content-Length: 2
Content-Type: text/plain;charset=UTF-8

OK

Proposed Solution

Use mergePath from hono/utils/url to ensure the path provided to registerPath includes the app _basePath.

https://github.com/honojs/middleware/blob/dde9854e51eeab6729050c48a400924dead975c9/packages/zod-openapi/src/index.ts#L268

this.openAPIRegistry.registerPath({
  ...route,
  path: mergePaths(this._basePath, route.path)
})

In local testing this works at one level of routing, but breaks when OpenAPIHono instances are nested. A separate fix would be needed to support Groups that change base or documentation would need to explain that nested app instances must be Grouped without changing base.

SimulatedGREG avatar Apr 16 '24 22:04 SimulatedGREG

Any update here ? I couldn't use the proposed solution unfortunately...

mehdinourollah avatar Apr 30 '24 18:04 mehdinourollah

I'm using a workaround to make the requests from Swagger work, but it's definitely not a solution for the whole problem and it doesn't display the whole path for the endpoints.

export const app = new OpenAPIHono<{ Bindings: Bindings }>().basePath('/accounts/me');

app.doc('/doc', {
    ...
    servers: [
        {
            url: '/accounts/me'
        }
    ]
});

image

a4vg avatar May 08 '24 21:05 a4vg

any updates here? this issue is still relevant since it does not generate correct openapi json file

leognmotta avatar Jun 28 '24 12:06 leognmotta