Wildcard redirects with javascript? - javascript

I'm trying to match URLs at a specific path and redirect them to a subdomain (don't ask why I'm doing this in Javascript).
Basically I can do this for the basics, this is on a page at example.com:
if (window.location.pathname == "/weddings" || window.location.pathname == "/weddings/"){
window.location.replace("https://blog.example.com/weddings/");
}
But now I need to do something similar for wildcards. I need to match /weddings/* and redirect to https://blog.example.com/weddings/*.
How do I do this with Javascript?
UPDATE
This seems to work, but is this the best method?
if (window.location.pathname.startsWith("/weddings/")) {
window.location.replace("https://blog.example.com" + window.location.pathname);
}

You can try this sample code.
const urlRegex = '/weddings/*';
if (window.location.pathname.match(urlRegex) !== null){
window.location.replace("https://blog.example.com/weddings/");
}

You could use String.prototype.match with regex
const regex = /\/weddings\/(.*)/
const pathnames = [
"/wedding",
"/weddings",
"/weddings/",
"/weddings/a",
"/weddings/b",
"/weddings/c/d?e=f",
]
pathnames.forEach((pathname) => {
const match = pathname.match(regex)
if (match) {
console.log(`https://blog.example.com/weddings/${match[1]}`)
}
})
Reference
String.prototype.match()

You can simplify this with URL API
The properties are are the same as window.location so you can check what's in the pathname and change the host accordingly. Then redirect to the resultant
Simplified example looping over a couple of test cases for demo purposes:
For live version just use new URL(location.href)
const samples = [
'http://example.com/food/',
'http://example.com/weddings/',
'http://example.com/weddings/nice-one',
'http://example.com/weddings/foo?param=1'
]
samples.forEach(str => {
const url = new URL(str);
if (url.pathname.startsWith('/weddings')) {
url.host = 'blog.' + url.host;
}
console.log(url.href)
})

Related

check if urls have the same origin

I have a function that runs before every API request to check if the request is from a valid origin.
I have an array of valid origins
const whitelist = [ 'a.com', 'b.co.uk' ]
const validOrigin = str => {
const url = new URL( str )
return whitelist.includes( url.host )
}
console.log(validOrigin('https://www.a.com'))
It returns false because of the www. I dont want to just add a copy with www. to the array of valid origins. I would like a way that covers this and everything else thats unexpected.
Keeping in mind that, by the rules, www.example.com and example.com are different origins:
If you want to match any origin on the same domain or a subdomain of the domains in the whitelist, then you need to:
Strip off the scheme and port - which you are doing already
Check for an exact match - which you are doing already
Check for a match which ends in . followed by the string (to stop third-party-hacker-a.com matching)
So something like:
const validOrigin = str => {
const url = new URL( str )
const host = url.host;
return whitelist.some( element => {
if (element === host) return true;
return element.endsWith(`.${host}`);
} )
}
you can try something like this
str = str.replace( new RegExp("((http)(s)?:\/\/)?(www.)?","gm"),"")
this will delete the first part of the url
The Array.prototype.includes function only accepts the value to search for, and looks for an exact match.
You would need to use a function that accepts a callback to test the elements - for example, the Array.prototype.findIndex function.
As you mention in the comments, you'll also need to change the whitelist so that you can exclude domains whose name ends with one of your valid domains.
const whitelist = [ /(^|\.)a\.com$/i, /(^|\.)b\.co\.uk$/i ];
const validOrigin = str => {
const url = new URL(str);
const index = whitelist.findIndex(el => el.test(url.host));
return index !== -1;
};
document.querySelectorAll("#tests > li").forEach(li => {
const str = li.dataset.value;
const result = validOrigin(str);
li.textContent = `${str} = ${result}`;
});
<ul id="tests">
<li data-value="http://a.com/foo"></li>
<li data-value="http://www.a.com/foo"></li>
<li data-value="http://dev.a.com/foo"></li>
<li data-value="http://banana.com/foo"></li>
<li data-value="http://a.com.b.ru/foo"></li>
</ul>

How to get value of URL query parameter with dynamic name?

I need to extract the value of a query parameter in a URL, but the parameter changes on each page.
For example, I want to get the color variable, but it always changes based on the productID. In this case it is 'dwvar_2000440926_color' but for another product it will be 'dwvar_545240926_color'. _color stays consistent, so I'd like to key off that:
https://www.example.com/us/2000440926.html?dwvar_2000440926_color=02
Thanks!
Basic regular expression would work
const myURL = new URL("https://www.example.com/us/2000440926.html?dwvar_2000440926_color=02")
console.log(myURL.search.match(/_color=([^&]+)/)[1]);
// more specfic
console.log(myURL.search.match(/dwvar_\d+_color=([^&]+)/)[1]);
You should use regex. Based on the description of the URL behavior you described you could do something like this:
const url = new URL("https://www.example.com/us/2000440926.html?dwvar_2000440926_color=02");
// Now url.search contains your query parameters.
// We gonna apply the regex on it to capturing the color id
let matches = url.search.match(/dwvar_\d+_color=(\d+)/)
// `matches` now contains the captured groups
console.log(matches[1])
// log : 02
Assuming that 1) you want to do this on the client side 2) the color param always begins with dwvar as shown in your example and 3) that there is never more than one dwvar param, you can use the following javascript:
let searchParams = new URLSearchParams(document.location.search);
searchParams.forEach((param_value, param_name) => {
if (param_name.indexOf('dwvar') == 0) {
console.log(param_value)
}
})
window.location.search.slice(1).split('&').reduce((acc, it) => {
const [key, val] = it.split('=');
return {
...acc,
[key]: val,
};
}, {});

Javascript need website URLS shortening down

I am fetching all the websites links and putting them into a array where I will eventually compare them with a JSON list. I need the websites to be shortened down to
Examples (What I'm trying to get the array to look like)
google.com
computers.intercom-clicks.com
mad-websites.ru
just-eat.com
Example links
https://mad-websites.ru/via/e?ob=RohpF3uuLGksOJfxJOwcgRL5vknYi4kC2aQRzvu2v3s%3D&h=04ce1caed8c7cf4b69d751230eaf7a2450660d67-o26qxr01_77963700909352&l=6ef96bea4775c44a5bc10cdaa661c5053819c0b8-7456283
https://notifications.google.com/g/p/AD-FnEwlAH83isfsH0zLOoNuynSmz1pMuK9Y8guqew5CkdyaEu28Zu30iRcw-SI6y7LRO7v8Tqy6p_9LhGcQClO1e2P5WYSVNa9dWPVhmA
https://finance.rambler.ru/?utm_source=head&utm_campaign=self_promo&utm_medium=topline&utm_content=finance_media
https://www.google.com/covid19?utm_source=Google-Maps-timeline&utm_medium=email&utm_campaign=COVID-site-promo
My code currently only shortens some websites down while others are still the same. It will also remove any duplicates.
const links = Array.from(document.querySelectorAll(".a3s a")).map(link => {
const url = new URL(link.href);
url.search = '';
return url.toString();
})
//removes duplicate links
const uniq = [...new Set(links)];
//window.alert(uniq);
return warningPopup(uniq);
}
Is this what you look for?
const links = Array.from(document.querySelectorAll(".a3s a")).map(link => {
const url = new URL(link.href);
return url.hostname;
})
//removes duplicate links
const uniq = [...new Set(links)];
document.write(uniq.join(', '))
<div class="a3s">
</div>

Check if two URL strings are equal

I'm building out a function to handle dynamic phone number swapping, identifying the referral url, mapping through a data set, and then outputting the promoUrl's related phone number. The data is formatted like this:
const phoneNumbers = [
{
promoUrl: '/interior-doors/',
promoNumber: '589-918-0710',
},
{
promoUrl: '/promo4/',
promoNumber: '307-789-8615',
},
];
And the function maps through the data and reduces it, allowing me to sort through it like this:
const url = location.pathname.replace(/\/+$/, '');
const promoNumber = phoneNumbers.reduce((promoNumber, results) => {
const hasPromo = results.promoUrl.includes(url);
if (hasPromo) {
return results.promoNumber;
}
return promoNumber;
}, '');
I'm having some issues with hasPromo. The way it's built right now allows for the promoUrl to have some variance and still work, meaning as long as it includes what is returned from url then it works i.e. /interior-doors/, /interior-doors, and interior-doors will all work, which is great, but it also works if url is /interior-do. I need it to not do that. It should work independent of formatting, but only return the promoNumber if the string of letters is exact.
I'm assuming this is a regex thing, but I don't know what I'm doing with regex. Any help would be greatly appreciated.
Use == to do an exact match. And since the promoURL property always has / around it, add those delimiters when you set url
const url = '/' + location.pathname.replace(/\/+$/, '') + '/';
const promoNumber = phoneNumbers.reduce((promoNumber, results) => {
const hasPromo = results.promoUrl == url;
if (hasPromo) {
return results.promoNumber;
}
return promoNumber;
}, '');
reduce also seems like the wrong function for this. You just need to find the matching promoUrl, you don't have to continue reducing, since the reduction function doesn't merge the results in any way.
const promo = phoneNumbers.find(({promoUrl}) => promoUrl == url);
const promoNumber = promo ? promo.promoNumber : '';

How to match string with a wildcard in javascript

I am trying to write a function that checks if a route is included in an array of routes:
const routes = ['/test', '/documentation/*']
function checkRoute(route) {
if (routes.includes(route)) {
console.log('Included!!')
} else {
console.log('Not included!')
}
}
The part I need help with is how to handle the wildcard * - basically, I want any route that has the /docs/ prefix to be included such as:
/documentation/docs.json, /documentation/index.html
Besides doing some very messy string manipulation, I am not sure how to achieve this. Any help would be greatly appreciated!
You can use regex.
const routes = ['\\/test\\/*', '\\/documentation\\/*']
function checkRoute(route) {
let regex = new RegExp(route);
let matchedRoutes = routes.filter(route => regex.test(route))
}
Here is a simple form of wildcard match function. It is not a bad idea to use it and support all types of wildcard comparrsion:
https://stackoverflow.com/a/32402438/635891

Categories