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

redirect loop #111

Open
toddpadwick opened this issue Jan 31, 2022 · 6 comments
Open

redirect loop #111

toddpadwick opened this issue Jan 31, 2022 · 6 comments

Comments

@toddpadwick
Copy link

I have the following redirect which seem to cause an infinite redirect loop. I can't quite figure out why.
Do you know why this might be happening? If not, is there a way to set up some kind of log or debugger to track what the redirect module is actually doing behind the scenes for each redirect?

This is the rule:
/get-the-positive-edge => /forms/get-the-positive-edge

And this is what happens when I enter /get-the-positive-edge into the browser:
/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/forms/get-the-positive-edge

@Webbist-dev
Copy link

Experiencing the same issue, but only on one redirect in thousands.

@Webbist-dev
Copy link

So we ditched this module and wrote our own.

In server middleware we have


module.exports = function (req, res, next) {
  const host = req.headers.host
  const env = process.env.NODE_ENV
  const notWww = host.slice(0, 4) !== 'www.'
  const isDomain = host.includes('domain.com')
  const redirect = redirects.find(r => r.from === req.url)

  if (env === 'production' && isDomain && notWww) {
    const newHost = 'www.' + host
    if (redirect) {
      const newLocation = redirect.to

      res.writeHead(parseInt(redirect.statusCode), {
        Location: 'https://' + newHost + newLocation
      })
      res.end()
    } else {
      res.writeHead(301, {
        Location: 'https://' + newHost + req.url
      })
      res.end()
    }
  } else if (redirect) {
    const newLocation = redirect.to

    res.writeHead(parseInt(redirect.statusCode), {
      Location: newLocation
    })
    res.end()
  } else {
    next()
  }
}

This works for all redirect objects passed to it, extensively tested on over 4k varying redirects.
This also handles redirects for non-www to www and HTTP to HTTPS.

@toddpadwick
Copy link
Author

Fantastic. thank you @Webbist-dev .
So do you query and store your redirects on build in the same way as the redirect-module?
We're currently doing a GQL query to get all our redirects in nuxt.config

@toddpadwick
Copy link
Author

toddpadwick commented Mar 3, 2022

@Webbist-dev could you explain what the methods inside if (env === 'production' && isDomain && notWww) are for? Trying to work it out so I can adapt for our own needs. I am wondering if we can ditch that whole conditional considering we have some redirects that go to other sites and occasional some that do not have www.

Also presumably this does not accept regex redirects?

@toddpadwick
Copy link
Author

Inspired by the code supplied by @Webbist-dev , I've found an adjusted working solution for our setup to meet the following requirements:

  1. query redirects from an endpoint on our CMS
  2. Support RegEx when matching redirects
  3. Allow redirects to include URLs that are not on the current domain – eg /example => https://someotherdomain.com/example

My solution to replace the requirement for the Nuxt Redirect-Module:

OPTIONAL – for those who need to query an endpoint for redirects array, In /store/index.js I am fetching all redirects from retour plugin in Craft CMS, in nuxtServerInit – this only occurs once during the initial build. I am then formatting them using map to prepare them for use:

import Vuex from 'vuex';
import fetch from 'node-fetch';
import fs from 'fs';



const createStore = () => {
  return new Vuex.Store({
    actions: {
        async nuxtServerInit({commit}, {app, $config}) {
            
            if (process.env.NODE_ENV == 'dev') {
                
                // GET AND STORE REDIRECTS
                const baseUrl = process.env.API_BASE_URL; // get API url
                const endpoint = '/actions/retour/api/get-redirects'; // get endpoint path
                const api = baseUrl+endpoint;
                fetch(api, {
                    method: 'GET',
                    headers: { 'Content-Type': 'application/json' }
                })
                .then(result => result.json())
                .then(result => {
                    console.info('Redirects generated');
                    if (result) {
                        const formattedRedirects = result.map(redirect => { // map redirect array and reformat it for redirect module requirements
                            let formattedRedirect = {};
                            formattedRedirect.from = redirect.redirectSrcUrl
                            formattedRedirect.to = redirect.redirectDestUrl
                            formattedRedirect.statusCode = redirect.redirectHttpCode
                            return formattedRedirect
                        })
                        fs.writeFile('./server-middleware/assets/redirects.json', JSON.stringify(formattedRedirects), err => {
                            if (err) {
                                console.error('Error writing redirect file', err);
                            }
                        });
                    } else {
                        console.log('No redirects in result');
                    }
                });

            }
            
        },
    }
  });
};

export default createStore

REQUIRED – in /server-middleware/redirects.js I am importing the file I created in nuxtServerInit (but this can just be an array of redirects you generate however you like) and then querying it for redirects:

import redirects from './assets/redirects.json'; // import redirects file generated in build via /store/index.js

module.exports = function (req, res, next) {
  const url = req.url;
  const redirect = redirects.find(obj => new RegExp(`^${obj.from}`).test(url));  // RegEx check to find url in redirect array
  if (redirect) { // if redirect exists, redirect it
    const newLocation = redirect.to 
    res.writeHead(parseInt(redirect.statusCode), { // apply status code eg 301
      Location: newLocation
    })
    res.end()
  } else { 
    next()
  }
}

And lastly, in nuxt.config.js, include the server middleware file

  serverMiddleware:['~/server-middleware/redirects.js'],

@sylvan0s
Copy link

Hi,

I've been struggling with this issue too since days.
I figured out with a solution that works for me

Before : { from: "/get-the-positive-edge", to: "/forms/get-the-positive-edge", statusCode: 301 }
After : { from: '^/get-the-positive-edge$', to: '/forms/get-the-positive-edge', statusCode: 301 }

I don't know if there is some issue with the spelling between "simple quote / double quote", regex mode in the from attribute but it works like this, no need for a middleware.

Regards,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants