Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
isSameOrigin
function(){
// will annotate once complete
}
function(a,b,c){b=document.createElement("a");b.href=a;return(a=location)[c="protocol"]==b[c]&&a[c="hostname"]==b[c]&&+a.port||80==+b.port||80}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 YOUR_NAME_HERE <YOUR_URL_HERE>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "isSameOrigin",
"description": "Determines whether a URL has the same origin as the current browser page.",
"keywords": [
"url",
"uri",
"origin",
"same-origin",
"browser"
]
}
<!DOCTYPE html>
<title>Same-origin tester</title>
<div>Expected value: <b>true</b></div>
<div>Actual value: <b id="ret"></b></div>
<script>
var myFunction = function(a,b,c){b=document.createElement("a");b.href=a;return(a=location)[c="protocol"]==b[c]&&a[c="hostname"]==b[c]&&+a.port||80==+b.port||80}
document.getElementById( "ret" ).innerHTML = myFunction("//gist.github.com:80")
</script>
@jed

This comment has been minimized.

Copy link
Owner Author

@jed jed commented Aug 30, 2011

this was inspired by @sstephenson's tweet.

the base case is trivial, but port support is difficult. chrome, for example, returns "0" for the port of a URL in which the port isn't specified.

there are still 3 bytes to golf until 140...

@sstephenson

This comment has been minimized.

Copy link

@sstephenson sstephenson commented Aug 30, 2011

Fun. This should probably also check for 443 if the protocol is https :)

@Kambfhase

This comment has been minimized.

Copy link

@Kambfhase Kambfhase commented Aug 30, 2011

You can try replacing && by just &.

@eligrey

This comment has been minimized.

Copy link

@eligrey eligrey commented Aug 30, 2011

If you're not going to allow the default ports of other protocols, such as https and ftp, you might as well drop the port 80 checks.

@jed

This comment has been minimized.

Copy link
Owner Author

@jed jed commented Aug 30, 2011

i'd like to cover cases for 80 and 443, ideally. i also attempted a try/catch with XHR, but alas, it doesn't work unless you send something.

@tiff

This comment has been minimized.

Copy link

@tiff tiff commented Aug 30, 2011

Sorry maybe I still didn't get the problem:
What's the problem with using location.host instead of location.hostname? You then could skip the port check.
location.host will return the hostname and port (but only when the port doesn't match the protocol). That's at least how my Firefox, Safari and Chrome behave (haven't tested IE).

a=document.createElement("a");
a.href = "http://twitter.com";
a.host; // twitter.com
a.href = "http://twitter.com:80";
a.host; // twitter.com
a.href = "http://twitter.com:100";
a.host; // twitter.com:100
a.href = "https://twitter.com:443";
a.host; // twitter.com

So the whole thing could become:

function(a,b,c){b=document.createElement("a");b.href=a;return(a=location)[c="protocol"]==b[c]&&a[c="host"]==b[c]}
@sstephenson

This comment has been minimized.

Copy link

@sstephenson sstephenson commented Aug 31, 2011

@tiff If your address bar says https://twitter.com/ and your link href is https://twitter.com:443/, hostname won't match, but they point to the same origin.

@jed

This comment has been minimized.

Copy link
Owner Author

@jed jed commented Aug 31, 2011

what @tiff is saying is that the serialized href is normalized. so your link of https://twitter.com:443/ would normalize to https://twitter.com/. this is pretty great, and if true for IE, would be all we need.

at that point, we could even just compare href prefixes.

@eligrey

This comment has been minimized.

Copy link

@eligrey eligrey commented Aug 31, 2011

@sstephenson you shouldn't be checking hostname. An origin is the protocol + host (which comprises the hostname and non-standard port), not protocol + hostname.

@sstephenson

This comment has been minimized.

Copy link

@sstephenson sstephenson commented Aug 31, 2011

Oh, fantastic.

@jed

This comment has been minimized.

Copy link
Owner Author

@jed jed commented Aug 31, 2011

so, that would be 113 bytes:

function(a,b){(b=document.createElement("a")).href=a;return!location.href.indexOf(b.href.split(a="/",3).join(a))}

or in 103:

function(a){with(document.createElement("a"))return href=a,!href.indexOf(/^.*?\w\//.exec(location)[0])}

kudos for that discovery, @tiff.

@adriengibrat

This comment has been minimized.

Copy link

@adriengibrat adriengibrat commented Jun 13, 2012

@jed & @tiff,
IE8+ seems OK (tested only in IE8)
IE7 (using IE8 in IE7 mode) doesn't seems to normalize anything (as expected?!):
neither blank protocol -> //twitter.com not normalized to http(s)://twitter.com/
neither port -> https://twitter.com:443 not normalized to https://twitter.com/
neither final slash -> https://twitter.com not normalized to https://twitter.com/

@adriengibrat

This comment has been minimized.

Copy link

@adriengibrat adriengibrat commented Jun 13, 2012

Whoaaaaa, it seems that setting the host in IE trigger some href normalization!
So, adding host=host, as dumb as it seems, solve the problem in IE.

function(a){with(document.createElement("a"))return href=a,host=host,!href.indexOf(/^.*?\w\//.exec(location)[0])}

does the trick in 114 bytes.
Someone could test it on real IE7 & IE6?

@adriengibrat

This comment has been minimized.

Copy link

@adriengibrat adriengibrat commented Jun 13, 2012

After testin with browserstack.com & browserling.com, it appears the trick does'nt work on
IE6 & Safari 4 port isn't normalized... to be continued

@jed

This comment has been minimized.

Copy link
Owner Author

@jed jed commented Jun 14, 2012

good work, @adriengibrat. let us know if you find something.

@adriengibrat

This comment has been minimized.

Copy link

@adriengibrat adriengibrat commented Feb 14, 2014

function λ(l){with(λ.a||(λ.a=document.createElement("a")))return href=l,host=host,!href.indexOf(/^.*?\w\//.exec(location)[0])}

127 bytes, use a cached dom link node.
Still does'nt work on IE6 (4.5%) & Safari 4 (lt 0.5%), but both browsers have no/buggy CORS implementation, so who cares?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment