Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compatibility with next-connect middlewares #728

Open
mkbctrl opened this issue Dec 19, 2023 · 2 comments
Open

Compatibility with next-connect middlewares #728

mkbctrl opened this issue Dec 19, 2023 · 2 comments
Labels
area: integrations contributions welcome Good for people looking to contribute enhancement New feature or request

Comments

@mkbctrl
Copy link

mkbctrl commented Dec 19, 2023

Is your feature request related to a problem? Please describe.

I prefer to organize my middlewares with next-connect, however after installing next-intl I run into the following issue:

import { createEdgeRouter } from 'next-connect'
import { NextResponse, type NextRequest } from 'next/server'
import { i18nMiddleware } from './services/i18n/i18n-middleware'
import { redirectMiddleware } from './services/next-connect/redirects-middleware'

const router = createEdgeRouter<NextRequest, NextResponse>()

router.use(i18nMiddleware, redirectMiddleware)

router.all(() => {
  // default if none of the above matches
  return NextResponse.next()
})

export function middleware(request: NextRequest, response: NextResponse) {
  return router.run(request, response)
}

export const config = {
  // Match only internationalized pathnames, dynamically based on the locales
  matcher: ['/', `/(en)/:path*`],
}

My redirectMiddleware did not trigger. I tried several different combinations trying to build a custom wrapper around the i18nMiddleware that normally looks like this:

import createMiddleware from 'next-intl/middleware'
import { defaultLocale, localePrefix, locales } from './i18n-config'

export const i18nMiddleware = createMiddleware({
  locales,
  defaultLocale,
  localePrefix,
})

here is one example of the attempt:
https://github.com/hoangvvo/next-connect?tab=readme-ov-file#nextjs-middleware

export const i18nMiddleware = (req: NextRequest, _: unknown, next: NextHandler) => {
  try {
    nextIntlMiddleware(req);
    next();
  } catch (error) {
    // Handle the error as needed
    // For example, you can log it or return a specific response
  }
};

but this was creating the following error:

{ time: 1702941952447, level: 30, msg: 'Navigating to: ' }
 ⨯ node_modules/next-intl/dist/esm/server/react-server/RequestLocale.js (1:612) @ eval
 ⨯ Error: Unable to find `next-intl` locale because the middleware didn't run on this request. See https://next-intl-docs.vercel.app/docs/routing/middleware#unable-to-find-locale
    at Home (./src/app/[locale]/page.tsx:26:68)
    at AsyncLocalStorage.run (node:async_hooks:346:14)
    at Object.apply (./src/app/[locale]/page.tsx:101:10)
    at async Promise.all (index 0)
    at async Promise.all (index 0)
null

It's my first time with next-intl so maybe I am missing smth obvious, but been bumping my head against this for few hours, and I can't figure it out, chat-gpt couldn't help as well 😅

Describe the solution you'd like

router.use(i18nMiddleware, redirectMiddleware) or router.use(i18nMiddleware).use(redirectMiddleware)

Describe alternatives you've considered

Currently I have this blob that works, but it's hard to look at it (that's why I want to decouple it with next-connect):

export async function middleware(req: NextRequest) {
  const { locale, pathname } = extractPathAttrs(req)

  try {
    const res = i18nMiddleware(req)
    const { dbServerClient } = composeDbReqResClient(req, res)
    const {
      data: { session },
    } = await dbServerClient.auth.getSession() // automatically refreshes the session if expired

    logger.info({ body: 'Navigating to: ', pathname, locale, session })
    if (!session && isPathUser(pathname)) {
      logger.info(`Redirecting to LOGIN page, no session found. Tried to access: ${pathname}`)
      // TODO: Later on add more sophisticated logic to handle redirect to profile if it doesn't exists
      return NextResponse.redirect(new URL(`/${locale}${Path.AuthRegister}`, req.url))
    }

    if ((session && isPathAuth(pathname)) || (session && isPathRoot(pathname))) {
      // TODO: Redirect to dashboard
      logger.info(
        `Redirecting to DASHBOARD page, public visitor screens not allowed. Tried to access: ${pathname}`,
      )
      return NextResponse.redirect(new URL(`/${locale}${Path.UserProfileCreate}`, req.url))
    }

    return res
  } catch (error) {
    logger.error(error)
    return NextResponse.rewrite(new URL(`/${locale}${Path.Error}`, req.url))
  }
}
@milandekruijf
Copy link

+1. Having this issue as well.

@amannn
Copy link
Owner

amannn commented Feb 7, 2024

I don't have experience with next-connect, but if someone is interested in adapting the middleware accordingly and this doesn't have any negative side effects for the standalone usage (same API, no significant change in bundle size), I'd be happy to review a PR!

@amannn amannn added contributions welcome Good for people looking to contribute and removed unconfirmed Needs triage. labels Feb 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: integrations contributions welcome Good for people looking to contribute enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants