redirect-module
redirect-module copied to clipboard
redirect loop
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
Experiencing the same issue, but only on one redirect in thousands.
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.
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
@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?
Inspired by the code supplied by @Webbist-dev , I've found an adjusted working solution for our setup to meet the following requirements:
- query redirects from an endpoint on our CMS
- Support RegEx when matching redirects
- 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'],
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,