connect-es
connect-es copied to clipboard
[connect-next] Example using new app routing
Is your feature request related to a problem? Please describe. I noticed there is a new package to work with NextJS but the example is based on Next 12.
Describe the solution you'd like I would appreciate some documentation on best practices when working with Next 13.
Describe alternatives you've considered Using the Next 12 pages style
I tries to integrate Connect with Next via Middleware, there is an issue on Edge Runtime. It only supports subset of available Node.js APIs.
@AshotN, the new app directory in Next.js is still an experimental opt-in. We do not support it yet.
Are there any plans for the near future?
Hey @AshotN, yes we plan to support it. The first step was https://github.com/bufbuild/connect-es/pull/575 - it adds support for creating handlers using the fetch Request/Response types, which the new Route Handlers are using under the hood.
Related discussion for support for edge runtimes: https://github.com/connectrpc/connect-es/discussions/829
Any update on this?
I just set this up myself this weekend, it was pretty straightforward. I used the cloudflare workers example as reference. Here's the code others can use:
import {
ConnectRouter,
ConnectRouterOptions,
createConnectRouter,
} from "@connectrpc/connect"
import {
UniversalHandler,
universalServerRequestFromFetch,
universalServerResponseToFetch,
} from "@connectrpc/connect/protocol"
interface HandlerOptions extends ConnectRouterOptions {
/**
* Route definitions.
*/
routes: (router: ConnectRouter) => void
/**
* The directory/prefix in which the Connect RPC server is mounted.
*/
prefix: string
}
/**
* Creates Next.js app route handlers for the given Connect service routes.
*/
export function nextAppRouter({ routes, prefix, ...options }: HandlerOptions) {
const router = createConnectRouter(options)
routes(router)
const paths = new Map<string, UniversalHandler>()
for (const handler of router.handlers) {
paths.set(prefix + handler.requestPath, handler)
}
async function handler(req: Request) {
const url = new URL(req.url)
const handler = paths.get(url.pathname)
if (handler === undefined) {
return new Response(undefined, { status: 404 })
}
const uReq = universalServerRequestFromFetch(req, {})
const uRes = await handler(uReq)
return universalServerResponseToFetch(uRes)
}
return {
POST: handler,
GET: handler,
}
}
// app/rpc/[[...connect]]/route.ts
export const { GET, POST } = nextAppRouter({
prefix: "/rpc",
routes(router) {
// Register your service implementations here
router.service(MyService, myServiceImpl)
},
})
Mounting it at /rpc was of course an arbitrary choice, you could do /connect or wherever else, too. Your directory just needs to match your prefix parameter.
Are there other methods that need to be handled other than GET and POST? Maybe OPTIONS for people needing CORS? I didn't need that for my use case, and would be trivial enough to make your own OPTIONS handler function there to return the appropriate headers.
Hopefully this gets incorporated into a new plugin package or official example!
Thanks @lourd !! that worked for me.