Will 'http:url' work for all browsers and devices? - javascript

In making a function that validates a user URL and prepends http: at the front, I have to take cases of www, https and // into account as being valid urls. The way I have it written now (see below), I only prepend http: , so that cases of //stackoverflow.com don't turn into http: ////stackoverflow.com.
This means that a url like stackoverflow.com becomes http:stackoverflow.com.
In Firefox and Chrome, this works just fine, but these URLS will be clicked from a variety of browsers and devices. Is it something that'll work universally? It'll be easy to rewrite this check for a // case, but I'm interested in the answer.
Prepend method:
function prependHTTPtoWebURL() {
var url = (el('org_website').value);
var httpVar;
var testFor;
if (url) {// If there's a website URL value
testFor = url.toLowerCase();
if (testFor.indexOf("http") != 0){
httpVar = 'http:'; //add it
url = httpVar + url;
el('org_website').value = url;
}
}
}

Try playing with regex. Check this code for instance:
var someurl = "www.google.com";
var otherurl = "google.com";
var anotherurl = "//google.com";
function prependHTTPtoWebURL(url) {
var newurl = url.replace(/^(http)?(:)?(\/\/)?/i,'');
return 'http://' + newurl;
}
console.log(prependHTTPtoWebURL(someurl));
console.log(prependHTTPtoWebURL(otherurl));
console.log(prependHTTPtoWebURL(anotherurl));
The ouput in console.log will be:
http://www.google.com
http://google.com
http://google.com
Since you are specifying a subdomain (www) on the first one, that is respected. It avoids ending with four diagonals, like http:////. If your url was something like :google.com, it would also fix it correctly.
You can see it live here: http://jsfiddle.net/zRBUj/
Edit: Adding the /i Kate mentioned.

Change http: to http://
See these links for more info:
Anatomy of a URL
How the web works

Related

Simplest way to check if the current url contains a subdomain

I'm looking for the simplest way to check if the user is on the normal domain (domain.com) or is on a subdomain et.domain.com and display content based on that. If it matters I'm trying to do that on shopify.
You can split the url with dot(.) and check the length. This will only work for .com url.
Note: This will not work for domains like google.co.in
const domain = 'domain.com';
const subDomain = 'et.domain.com'
const isSubdomain = (domain) => domain.split('.').length > 2;
console.log(isSubdomain(domain));
console.log(isSubdomain(subDomain));
You can actually use regex method.
var isSubdomain = function(url) {
url = url || 'http://www.test-domain.com'; // just for the example
var regex = new RegExp(/^([a-z]+\:\/{2})?([\w-]+\.[\w-]+\.\w+)$/);
return !!url.match(regex); // make sure it returns boolean
}
console.log(isSubdomain("example.com"));
console.log(isSubdomain("http://example.com:4000"));
console.log(isSubdomain("www.example.com:4000"));
console.log(isSubdomain("https://www.example.com"));
console.log(isSubdomain("sub.example.com"));
console.log(isSubdomain("example.co.uk")); //it doesn't work on these very specific cases

Javascript conditional replace not working

Javascript conditional replace image src to https if url prefix is in http:// and ignore https:// currently i have this piece of code added to the source part.
Javascript:
src="' + p.replace("http","https") + '"
The issue:
http:// gets replace to https:// but the problem is its also replacing https:// to httpss:// which is breaking the src attribute and images are returning 404 error.
How to fix this issue?
UPDATE:
The variable p contains image URL which is sometimes http and sometimes its https. the above code replaces http to https successfully but when a url have https it adds another s like this httpss:// which returns 404 and image cant load
Just expand the selection, so that you are replacing http:// instead of just http, i.e.:
p.replace("http://", "https://")
See example below:
const urls = [
'https://example.com',
'http://example.com'
];
urls.forEach(url => {
console.log(`Original URL: ${url}`);
// Incorrect behavior
console.log(url.replace('http', 'https'));
// Correct behavior
console.log(url.replace('http://', 'https://'));
});
An alternative way to solve this problem will be to leverage the URL API, which is supported by anything after IE11. You simply parse your string using the new URL() constructor, and then modify its protocol property, i.e.:
const urls = [
'https://example.com',
'http://example.com'
];
urls.forEach(url => {
console.log(`Original URL: ${url}`);
const modifiedUrl = new URL(url);
modifiedUrl.protocol = 'https';
console.log(modifiedUrl.toString());
});
It is working fine. But could you please define your code why you add double quotes?
var p = 'http://google.com';
var src= p.replace("http","https");
console.log(src);
UPDATED
Please have a look to this updated solution.
var p = prompt('Enter URL?');
let str = p.split("://")[0];
var src= str === 'http' ? p.replace("http","https") : p;
console.log(src);
It doesn't work because your match string, http, is a subset of your replace string, https. So you need to suggest not to match https strings, or you could say match only http that doesn't have an s after it.
const urlVariants = [
'http://www.google.com',
'https://www.google.com'
]
urlVariants.forEach(url=> {
console.log( url, '->', url.replace('http:','https:') )
console.log( url, '->', url.replace(/http([^s])/,"https$1") )
})
You should match using regular expression. The regular expression to check if the url has uses http is :
/http[^(?=s)]{0}/i
Below is the working snippet to replace http by https successfully.
"http://www.google.com".replace(/http[^(?=s)]{0}/i,'https')

JavaScript - Detecting External Site Protocol - Client-side

I want to know a protocol of a site which is not my current page
E.g. I execute code and the current page which the code is executed on is http://www.example.org, and I want to get the protocol of which is https:
What I know is window.location.protocol should return the current page, which is http:, but is there something like 'google.com'.protocol to return https: ..
Thank you :)
My code:
var returnProtocolOf(site_url) = function {
return (String(site_url)).location.protocol // VIRTUAL COMMAND
};
You can do so with a elements:
function getProtocol(url){
var link = document.createElement('a');
link.href = url;
return link.protocol;
}
You can also just match it with an expression:
var protocol = url.match(/^([a-z]+?:)\/\//)[1];
Checks might be needed.

Rewriting a URL if it 404's

first timer here so be nice :3.
I am attempting to write a jQuery function that rewrites Amazon URL's to include affiliate tags, similar to what StackExchange does but with a twist.
The main differences is that I am attempting to the user to their closest Amazon Store - e.g. amazon.de - for german visitors. Due to Amazon's ASIN's differing in some countries I first want to check the new link, if it 404's I obviously don't want to direct my visitor there [1]
Here is my code that selects links to amazon.com, grabs the ASIN number and writes a shortlink to the product including the affiliate tag.
var tld_table = {'GB' : ".co.uk",'DE' : ".de",'CN' : ".cn",'AU' : ".ca",'IT' : ".it",'FR' : ".fr",'CA' : ".ca",'JP' : ".jp",};
var country = $.cookie("CountryCode");
//$.cookie by http://plugins.jquery.com/files/jquery.cookie.js.txt
var tld = tld_table[country] || '.com';
var regex = RegExp("http://www.amazon.com/([\\w-]+/)?(dp|gp/product)/(\\w+/)?(\\w{10})");
$('a[href*="amazon.com"]').each(function(){
var url = $(this).attr('href');
m = url.match(regex);
if (m) { //if ASIN found
var ASIN = m[4];
var shorturl = "http://www.amazon"+tld+"/dp/" + ASIN + "?tag="+ affTag[tld];
//http test for 404
//if 404 do not rewrite
//else $(this).attr('href',shorturl);
}
});
This works fine and will re-write the URL's but when I introduce ajax into the equation the script fails to rewrite any URL's.
EDIT
$('a[href*="amazon.com"]').each(function(){
var url = $(this).attr('href');
m = url.match(regex);
if (m) { //if ASIN found http://www.amazon.com/dp/B003DZ1Y8Q/?tag=derp
var ASIN = m[4];
var ajaxCall = $.get('ASIN.php?ASIN='+ASIN+'&tld='+tld+'&tag='+affTags[tld], function(data) {
var newlink = data;
console.log('New Link: '+newlink)
$(this).attr('href',newlink); //does not rewrite
})
ajaxCall.success(function() {
if(newlink != '404'){
$(this).attr('href',newlink);//does not rewrite
}
})
}
});
Above is the code I am attempting to use currently, ASIN.php builds & requests the new link, opens it using php's cURL and returns either a new link or '404'.
I think $(this) is failing to reference the link correctly, but I have no idea why.
The error says it all: is not allowed by Access-Control-Allow-Origin
It basically means that your javascript is not allowed to retrieve any URL outside of your domain. You can fix this by rewriting your ajax request to a local PHP script that checks the url.
It has something to do with http://en.wikipedia.org/wiki/Same_origin_policy
you can also use apache mod_proxy
ProxyPass /mirror/foo/ http://foo.com/
Then you can call the url /mirror/foo/ on your domain and it will pass the request to the forwarding remote url.
This is a common way of overcoming cross-domain browser restrictions.
http://httpd.apache.org/docs/1.3/mod/mod_proxy.html#proxypass

Getting an absolute URL from a relative one. (IE6 issue)

I'm currently using the following function to 'convert' a relative URL to an absolute one:
function qualifyURL(url) {
var a = document.createElement('a');
a.href = url;
return a.href;
}
This works quite well in most browsers but IE6 insists on returning the relative URL still! It does the same if I use getAttribute('href').
The only way I've been able to get a qualified URL out of IE6 is to create an img element and query it's 'src' attribute - the problem with this is that it generates a server request; something I want to avoid.
So my question is: Is there any way to get a fully qualified URL in IE6 from a relative one (without a server request)?
Before you recommend a quick regex/string fix I assure you it's not that simple. Base elements + double period relative urls + a tonne of other potential variables really make it hell!
There must be a way to do it without having to create a mammoth of a regex'y solution??
How strange! IE does, however, understand it when you use innerHTML instead of DOM methods.
function escapeHTML(s) {
return s.split('&').join('&').split('<').join('<').split('"').join('"');
}
function qualifyURL(url) {
var el= document.createElement('div');
el.innerHTML= 'x';
return el.firstChild.href;
}
A bit ugly, but more concise than Doing It Yourself.
As long as the browser implements the <base> tag correctly, which browsers tend to:
function resolve(url, base_url) {
var doc = document
, old_base = doc.getElementsByTagName('base')[0]
, old_href = old_base && old_base.href
, doc_head = doc.head || doc.getElementsByTagName('head')[0]
, our_base = old_base || doc_head.appendChild(doc.createElement('base'))
, resolver = doc.createElement('a')
, resolved_url
;
our_base.href = base_url || '';
resolver.href = url;
resolved_url = resolver.href; // browser magic at work here
if (old_base) old_base.href = old_href;
else doc_head.removeChild(our_base);
return resolved_url;
}
Here's a jsfiddle where you can experiment with it: http://jsfiddle.net/ecmanaut/RHdnZ/
You can make it work on IE6 just cloning the element:
function qualifyURL(url) {
var a = document.createElement('a');
a.href = url;
return a.cloneNode(false).href;
}
(Tested using IETester on IE6 and IE5.5 modes)
I found on this blog another method that really looks like #bobince solution.
function canonicalize(url) {
var div = document.createElement('div');
div.innerHTML = "<a></a>";
div.firstChild.href = url; // Ensures that the href is properly escaped
div.innerHTML = div.innerHTML; // Run the current innerHTML back through the parser
return div.firstChild.href;
}
I found it a little more elegant, not a big deal.
URI.js seems to solve the issue:
URI("../foobar.html").absoluteTo("http://example.org/hello/world.html").toString()
See also http://medialize.github.io/URI.js/docs.html#absoluteto
Not testeed with IE6, but maybe helpful for others searching to the general issue.
I actually wanted an approach to this that didn't require modifying the original document (not even temporarily) but still used the browser's builtin url parsing and such. Also, I wanted to be able to provide my own base (like ecmanaught's answer). It's rather straightforward, but uses createHTMLDocument (could be replaced with createDocument to be a bit more compatible possibly):
function absolutize(base, url) {
d = document.implementation.createHTMLDocument();
b = d.createElement('base');
d.head.appendChild(b);
a = d.createElement('a');
d.body.appendChild(a);
b.href = base;
a.href = url;
return a.href;
}
http://jsfiddle.net/5u6j403k/
This solution works in all browsers.
/**
* Given a filename for a static resource, returns the resource's absolute
* URL. Supports file paths with or without origin/protocol.
*/
function toAbsoluteURL (url) {
// Handle absolute URLs (with protocol-relative prefix)
// Example: //domain.com/file.png
if (url.search(/^\/\//) != -1) {
return window.location.protocol + url
}
// Handle absolute URLs (with explicit origin)
// Example: http://domain.com/file.png
if (url.search(/:\/\//) != -1) {
return url
}
// Handle absolute URLs (without explicit origin)
// Example: /file.png
if (url.search(/^\//) != -1) {
return window.location.origin + url
}
// Handle relative URLs
// Example: file.png
var base = window.location.href.match(/(.*\/)/)[0]
return base + url
However, it doesn't support relative URLs with ".." in them, like "../file.png".
This is the function I use to resolve basic relative URLs:
function resolveRelative(path, base) {
// Absolute URL
if (path.match(/^[a-z]*:\/\//)) {
return path;
}
// Protocol relative URL
if (path.indexOf("//") === 0) {
return base.replace(/\/\/.*/, path)
}
// Upper directory
if (path.indexOf("../") === 0) {
return resolveRelative(path.slice(3), base.replace(/\/[^\/]*$/, ''));
}
// Relative to the root
if (path.indexOf('/') === 0) {
var match = base.match(/(\w*:\/\/)?[^\/]*\//) || [base];
return match[0] + path.slice(1);
}
//relative to the current directory
return base.replace(/\/[^\/]*$/, "") + '/' + path.replace(/^\.\//, '');
}
Test it on jsfiddle: https://jsfiddle.net/n11rg255/
It works both in the browser and in node.js or other environments.
I found this blog post that suggests using an image element instead of an anchor:
http://james.padolsey.com/javascript/getting-a-fully-qualified-url/
That works to reliably expand a URL, even in IE6. But the problem is that the browsers that I have tested will immediately download the resource upon setting the image src attribute - even if you set the src to null on the next line.
I am going to give bobince's solution a go instead.
If url does not begin with '/'
Take the current page's url, chop off everything past the last '/'; then append the relative url.
Else if url begins with '/'
Take the current page's url and chop off everything to the right of the single '/'; then append the url.
Else if url starts with # or ?
Take the current page's url and simply append url
Hope it works for you
If it runs in the browser, this sort of works for me..
function resolveURL(url, base){
if(/^https?:/.test(url))return url; // url is absolute
// let's try a simple hack..
var basea=document.createElement('a'), urla=document.createElement('a');
basea.href=base, urla.href=url;
urla.protocol=basea.protocol;// "inherit" the base's protocol and hostname
if(!/^\/\//.test(url))urla.hostname=basea.hostname; //..hostname only if url is not protocol-relative though
if( /^\//.test(url) )return urla.href; // url starts with /, we're done
var urlparts=url.split(/\//); // create arrays for the url and base directory paths
var baseparts=basea.pathname.split(/\//);
if( ! /\/$/.test(base) )baseparts.pop(); // if base has a file name after last /, pop it off
while( urlparts[0]=='..' ){baseparts.pop();urlparts.shift();} // remove .. parts from url and corresponding directory levels from base
urla.pathname=baseparts.join('/')+'/'+urlparts.join('/');
return urla.href;
}

Categories