Skip to content

Instantly share code, notes, and snippets.

@jed
Forked from 140bytes/LICENSE.txt
Created August 30, 2011 23:01
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jed/1182343 to your computer and use it in GitHub Desktop.
Save jed/1182343 to your computer and use it in GitHub Desktop.
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
Copy link
Author

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
Copy link

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

@Kambfhase
Copy link

You can try replacing && by just &.

@eligrey
Copy link

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
Copy link
Author

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
Copy link

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
Copy link

@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
Copy link
Author

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
Copy link

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
Copy link

Oh, fantastic.

@jed
Copy link
Author

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
Copy link

@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
Copy link

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
Copy link

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
Copy link
Author

jed commented Jun 14, 2012

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

@adriengibrat
Copy link

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