harlan-zw / nuxt-seo

The complete SEO solution for Nuxt.

Home Page:https://nuxtseo.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Redirects to canonical url don't work

sergenux opened this issue · comments

Describe the bug

I try to enable redirects by "redirectToCanonicalSiteUrl: true" but it is don't work.
I found source file in module "src/runtime/nitro/middleware/redirect.ts"

import { defineEventHandler, sendRedirect } from 'h3'
import { joinURL } from 'ufo'
import { useNitroOrigin, useSiteConfig } from '#imports'

export default defineEventHandler((e) => {
  const siteConfig = useSiteConfig(e)
  if (siteConfig.site) {
    const siteConfigHostName = new URL(e.path, siteConfig.site).hostname
    const origin = useNitroOrigin(e)
    const originHostname = new URL(e.path, origin).hostname
    // if origin doesn't match site, do a redirect
    if (originHostname !== siteConfigHostName)
      return sendRedirect(e, joinURL(siteConfig.site, e.path), 301)
  }
})

console.log(siteConfig) outputs the following structure:

{
  env: 'production',
  name: 'app',
  trailingSlash: true,
  url: 'https://example.com'
}

siteConfig.site) is this true or should siteConfig.url be there?
And other use case if user landed for page "https://example.com/some/path" without trailing slash but in config "trailingSlash: true". Should this redirect to the path with trailing slash?
Thanks for any help.

Reproduction

No response

System / Nuxt Info

No response

I made a temporary solution universal for SPA and SSR mode using router middleware. Maybe it can be useful in some way:

import { withTrailingSlash, withoutTrailingSlash, resolveURL } from "ufo";
import { getRequestURL } from "h3";
import { useRequestEvent, useRequestURL, useError, useSiteConfig } from "#imports";

export default defineNuxtRouteMiddleware(() => {
  if (import.meta.prerender) return;

  const siteConfig = useSiteConfig();
  const error = useError();
  const event = useRequestEvent();

  const url = event ? getRequestURL(event) : useRequestURL();

  const originalUrl = url.href;

  let canonicalUrl =
    siteConfig.url && !import.meta.dev
      ? resolveURL(siteConfig.url, url.pathname, url.search, url.hash)
      : originalUrl;

  if (siteConfig.trailingSlash !== undefined) {
    canonicalUrl = siteConfig.trailingSlash
      ? withTrailingSlash(canonicalUrl, true)
      : withoutTrailingSlash(canonicalUrl, true);
  }

  if (canonicalUrl != originalUrl && !error) {
    return navigateTo(canonicalUrl, { redirectCode: 301, external: true });
  }
});

When the problem is solved nuxt/nuxt#25763 It might be a little easier:

import { withTrailingSlash, withoutTrailingSlash, resolveURL } from "ufo";
import { useRequestURL, useError, useSiteConfig } from "#imports";

export default defineNuxtRouteMiddleware(() => {
  if (import.meta.prerender) return;

  const siteConfig = useSiteConfig();
  const error = useError();
  const url = useRequestURL();

  const originalUrl = url.href;

  let canonicalUrl =
    siteConfig.url && !import.meta.dev
      ? resolveURL(siteConfig.url, url.pathname, url.search, url.hash)
      : originalUrl;

  if (siteConfig.trailingSlash !== undefined) {
    canonicalUrl = siteConfig.trailingSlash
      ? withTrailingSlash(canonicalUrl, true)
      : withoutTrailingSlash(canonicalUrl, true);
  }

  if (canonicalUrl != originalUrl && !error) {
    return navigateTo(canonicalUrl, { redirectCode: 301, external: true });
  }
});