Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

redirect destination to lowercase #25586

Closed
BernardA opened this issue May 29, 2021 · 3 comments
Closed

redirect destination to lowercase #25586

BernardA opened this issue May 29, 2021 · 3 comments
Labels
bug Issue was opened via the bug report template.

Comments

@BernardA
Copy link

BernardA commented May 29, 2021

What version of Next.js are you using?

10.2.3

What version of Node.js are you using?

14.15.4

What browser are you using?

Firefox

What operating system are you using?

macOS

How are you deploying your application?

in development

Describe the Bug

Attempting to use next.config to redirect uppercase routes to lowercase ones.

While it seems to be simple enough to catch the concerned routes in source, that's not the case when it comes to modifying the route in destination.

I have a number of legacy routes that need to be redirected as follows:

/brands/Brand to /brands/brand

/models/Brand/Model to /models/brand/model

Legacy is Apache and today those redirections are handled with .htaccess

So I was expecting to achieve that with something like:

  async redirects() {
    return [
        {
            source: '/brands/:brand([A-Za-z].*)',
            destination: `/brands/:${brand.toLowerCase()}`, // pseudo code
            permanent: true,
        },
    ];
},

But next.config does not like that and throws an error.

Looking around your issues I found this one or this one #21498, but I am not sure a resolution exists.

One of the above issues includes a code similar to below as a workaround, but this is not really satisfactory, as it first sends the user to 404.

Importantly, this also does not address the issue of SEO, which would require a code HTTP 301.

   import React, { useEffect } from 'react';
  import { useRouter } from 'next/router';

 const ResolveRoute = () => {
    const router = useRouter();
    useEffect(() => {
        const asPath = router.asPath;
        const routes = ['/marques-voiture/', '/modeles-voiture/'];
        // check if includes uppercase characters
         const regexp = new RegExp('[A-Z][A-Z]{0,2}[a-z]{0,100}');
       if (
            (asPath.startsWith(routes[0]) || asPath.startsWith(routes[1])) &&
             regexp.test(router.asPath)
        ) {
             router.push(router.asPath.toLowerCase());
          }
     });

      return null;
 };

Expected Behavior

  • Redirect the user to lowercase route without flashing the screen.
  • Give the search engines a 301 code so as not to lose rankings

To Reproduce

see code above

@BernardA BernardA added the bug Issue was opened via the bug report template. label May 29, 2021
@BernardA
Copy link
Author

BernardA commented Jun 5, 2021

I've tried the following workaround, but it does not work properly nor in a consistent fashion between development and build.

Also is does not return a proper 301 code in either case ( dev or build ).

On getStaticPaths I am generating all my proper, lowercase routes, but changing fallback: true.

   return {
      paths,
      fallback: true,
   };

Then on getStaticProps, I am validating the route params and either:

  • returning notFound if the lowercase params are invalid

  • redirecting to the lowercase route otherwise

     export async function getStaticProps({ params }) {
           const { brand: brandParam } = params;
           let brands = await getBrandsModels();
           brands = brands.data.brands;
           const brandFilter = brands.filter((br) => {
                  return urlWriter(br.brand) === urlWriter(brandParam);
           });
          // if filter is empty, brandParam is invalid so sent to 404
           if (brandFilter.length === 0) {
                 return {
                    notFound: true,
                };
          }
         // redirect in case valid brand with capital letters
         if (/[A-Z]/.test(brandParam)) {
              return {
                  redirect: {
                      destination: `/marques-voiture/${urlWriter(brandParam)}`,
                      permanent: true,
               },
          };
       }
      ... 
     // proceed as usual if route is valid and was pre-built
     }
    

Note that I did see your notice below in the docs, but I am not sure is applicable in this case. And, in any case, the redirection in next.config.js is the issue here

Note: Redirecting at build-time is currently not allowed and if the redirects are known at build-time they should be added in next.config.js.

The bottom line though is, as said that this does not really solve the issue:

  • works in development with HTTP code 200
  • sometimes it does change the URL to the lowercase version, sometimes it doesn't (why)
  • works when build and start locally with the same caveats
  • does not work on Vercel at all

@BernardA
Copy link
Author

Any news on this one? I am about ready to deploy the app in production, but cannot afford to loose the search engines on this.

@jankaifer
Copy link
Contributor

This is not a bug in next.js. I'll convert this into a help discussion.

@vercel vercel locked and limited conversation to collaborators Nov 29, 2022
@jankaifer jankaifer converted this issue into discussion #43495 Nov 29, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
bug Issue was opened via the bug report template.
Projects
None yet
Development

No branches or pull requests

2 participants