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

Inconsistent behavior of resulting from/to path in createRedirect #38562

Open
2 tasks done
techfg opened this issue Sep 18, 2023 · 0 comments
Open
2 tasks done

Inconsistent behavior of resulting from/to path in createRedirect #38562

techfg opened this issue Sep 18, 2023 · 0 comments
Labels
status: triage needed Issue or pull request that need to be triaged and assigned to a reviewer type: bug An issue or pull request relating to a bug in Gatsby

Comments

@techfg
Copy link

techfg commented Sep 18, 2023

Preliminary Checks

Description

When pathPrefix is not enabled, the effective basePath (/) is not applied to the path resulting in from/to path's passed to createRedirect passing through unmodified. However, when pathPrefix is enabled, the effective basePath (specified by pathPrefix) is applied unless the path is absolute or starts with //. This leads to inconsistent behavior between the two configuration options.

Additionally, the current code (and all subsequent downstream code) assumes that the path values specified in createRedirect start with a / and does not perform any validation and/or apply a leading slash if missing.

The behavior should be consistent in all scenarios to avoid different results based on prefixPath configuration. Also, given plugins and now adapters can support their own functionality with regards to from/to path, there should be a method for passing through paths unmodified (e.g., regex's).

  1. Always apply the effective basePath regardless of pathPrefix configuration and ensure leading slash and path separators
  2. Provide a way to have from/to path's pass through unmodified regardless of pathPrefix setting (possibly a basePath property defaulting to true on createRedirect that allows bypassing the default functionality of applying the basePath by configuring to false)

Example:

  createRedirect({
    fromPath: `(?i)^/oldpath(.*)`,
    toPath: `/newpath$1`
  })

pathPrefix disabled

  {
    "fromPath": "(?i)^/oldpath(.*)", // unmodified
    "toPath": "/newpath$1"  // unmodified
  },

pathPrefix enabled to /blog

  {
    "fromPath": "/blog(?i)^/oldpath(.*)",  // /blog prepended
    "toPath": "/blog/newpath$1" // /blog prepended
  },

Reproduction Link

https://github.com/techfg/gatsby-redirect-prefix-paths-issues

Steps to Reproduce

  1. Clone the repro
  2. npm run build
  3. review output in terminal window of redirects when prefixPath disabled
  4. npm run build:pathprefix
  5. review output in terminal window of redirects when prefixPath enabled

Expected Result

  1. behavior is consistent regardless of pathPrefix enabled/disabled
  2. behavior always ensures a valid path
  3. there is a way to pass through paths unmodified regardless of prefixPath configuration
  createRedirect({
    fromPath: `/old-page-1`,
    toPath: `/new-page-1`,
  })  

  createRedirect({
    fromPath: `old-page-2`,
    toPath: `new-page-2`,
  })    

  createRedirect({
    fromPath: `https://www.gatsbyjs.org`,
    toPath: `https://www.netlify.com`,
  })

  createRedirect({
    fromPath: `(.*)\.gif$`,
    toPath: `$1.jpg`
  })

  createRedirect({
    fromPath: `(?i)^/oldpath(.*)`,
    toPath: `/newpath$1`
  })

  createRedirect({
    fromPath: `adapterspecificfromkeyword`,
    toPath: `adapterspecifickeytokeyword`
  })

pathPrefix disabled

[
  {
    "fromPath": "/old-page-1", // same as input
    "toPath": "/new-page-1" // same as input
  },
  {
    "fromPath": "/old-page-2", // leading slash added
    "toPath": "/new-page-2" // leading slash added
  },
  {
    "fromPath": "https://www.gatsbyjs.org", // same as input
    "toPath": "https://www.netlify.com" // same as input
  },
  {
    "fromPath": "(.*).gif$", // same as input (assuming new createRedirect property to instruct)
    "toPath": "$1.jpg" // same as input (assuming new createRedirect property to instruct)
  },
  {
    "fromPath": "(?i)^/oldpath(.*)", // same as input (assuming new createRedirect property to instruct)
    "toPath": "/newpath$1" // same as input (assuming new createRedirect property to instruct)
  },
  {
    "fromPath": "adapterspecificfromkeyword", // same as input (assuming new createRedirect property to instruct)
    "toPath": "adapterspecifickeytokeyword" // same as input (assuming new createRedirect property to instruct)
  }
]

pathPrefix /blog

[
  {
    "fromPath": "/blog/old-page-1", // pathprefix added
    "toPath": "/blog/new-page-1" // pathprefix added
  },
  {
    "fromPath": "/blog/old-page-2", // pathprefix & path separator added
    "toPath": "/blog/new-page-2" // pathprefix & path separator added
  },
  {
    "fromPath": "https://www.gatsbyjs.org", // same as input
    "toPath": "https://www.netlify.com" // same as input
  },
  {
    "fromPath": "(.*).gif$", // same as input (assuming new createRedirect property to instruct)
    "toPath": "$1.jpg"  // same as input (assuming new createRedirect property to instruct)
  },
  {
    "fromPath": "(?i)^/oldpath(.*)", // same as input (assuming new createRedirect property to instruct)
    "toPath": "/newpath$1" // same as input (assuming new createRedirect property to instruct)
  },
  {
    "fromPath": "adapterspecificfromkeyword", // same as input (assuming new createRedirect property to instruct)
    "toPath": "adapterspecifickeytokeyword" // same as input (assuming new createRedirect property to instruct)
  }
]
```json

### Actual Result

1. behavior is not consistent when applying effective basePath between pathPrefix enabled/disabled
2. behavior does not always ensure a valid path
3. there is no way to pass through paths unmodified when `pathPrefix` is enabled

```js
  createRedirect({
    fromPath: `/old-page-1`,
    toPath: `/new-page-1`,
  })  

  createRedirect({
    fromPath: `old-page-2`,
    toPath: `new-page-2`,
  })    

  createRedirect({
    fromPath: `https://www.gatsbyjs.org`,
    toPath: `https://www.netlify.com`,
  })

  createRedirect({
    fromPath: `(.*)\.gif$`,
    toPath: `$1.jpg`
  })

  createRedirect({
    fromPath: `(?i)^/oldpath(.*)`,
    toPath: `/newpath$1`
  })

  createRedirect({
    fromPath: `adapterspecificfromkeyword`,
    toPath: `adapterspecifickeytokeyword`
  })

pathPrefix disabled

[
  {
    "fromPath": "/old-page-1", // correct, same as input
    "toPath": "/new-page-1" // correct, same as input
  },
  {
    "fromPath": "old-page-2", // path is invalid, should add leading slash
    "toPath": "new-page-2" // path is invalid, should add leading slash
  },
  {
    "fromPath": "https://www.gatsbyjs.org", // correct, same as input
    "toPath": "https://www.netlify.com"  // correct, same as input
  },
  {
    "fromPath": "(.*).gif$", // allows direct pass-through unmodified
    "toPath": "$1.jpg" // allows direct pass-through unmodified
  },
  {
    "fromPath": "(?i)^/oldpath(.*)", // allows direct pass-through unmodified
    "toPath": "/newpath$1" // allows direct pass-through unmodified
  },
  {
    "fromPath": "adapterspecificfromkeyword", // allows direct pass-through unmodified
    "toPath": "adapterspecifickeytokeyword" // allows direct pass-through unmodified
  }
]

pathPrefix /blog

[
  {
    "fromPath": "/blog/old-page-1", // correct
    "toPath": "/blog/new-page-1" // correct
  },
  {
    "fromPath": "/blogold-page-2", // no separator
    "toPath": "/blognew-page-2" // no separator
  },
  {
    "fromPath": "https://www.gatsbyjs.org", // no separator
    "toPath": "https://www.netlify.com" // no separator
  },
  {
    "fromPath": "/blog(.*).gif$", // prefix added with no way to avoid and different result than prefix disabled
    "toPath": "/blog$1.jpg" // prefix added with no way to avoid and different result than prefix disabled
  },
  {
    "fromPath": "/blog(?i)^/oldpath(.*)", // prefix added with no way to avoid and different result than prefix disabled
    "toPath": "/blog/newpath$1" // prefix added with no way to avoid and different result than prefix disabled
  },
  {
    "fromPath": "/blogadapterspecificfromkeyword", // prefix added with no way to avoid and different result than prefix disabled
    "toPath": "/blogadapterspecifickeytokeyword" // prefix added with no way to avoid and different result than prefix disabled
  }
]

Environment

System:
    OS: Linux 5.15 Ubuntu 20.04.6 LTS (Focal Fossa)
    CPU: (20) x64 12th Gen Intel(R) Core(TM) i9-12900HK
    Shell: 5.0.17 - /bin/bash
  Binaries:
    Node: 18.17.1 - ~/.nvm/versions/node/v18.17.1/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v18.17.1/bin/yarn
    npm: 9.8.1 - ~/.nvm/versions/node/v18.17.1/bin/npm
  Browsers:
    Chrome: 116.0.5845.179
  npmPackages:
    gatsby: ^5.11.0 => 5.12.4
  npmGlobalPackages:
    gatsby-cli: 5.12.1

Config Flags

N/A

@techfg techfg added the type: bug An issue or pull request relating to a bug in Gatsby label Sep 18, 2023
@gatsbot gatsbot bot added the status: triage needed Issue or pull request that need to be triaged and assigned to a reviewer label Sep 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: triage needed Issue or pull request that need to be triaged and assigned to a reviewer type: bug An issue or pull request relating to a bug in Gatsby
Projects
None yet
Development

No branches or pull requests

1 participant