Skip to content

Instantly share code, notes, and snippets.

@rmkane
Last active August 29, 2015 14:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rmkane/718566dba322a952ae9f to your computer and use it in GitHub Desktop.
Save rmkane/718566dba322a952ae9f to your computer and use it in GitHub Desktop.
A URL parser written in JavaScript

URL Parser

The following module handles parsing a URL in JavaScript. If this script is run outside of a browser, where the DOM is inaccessible, a regular expression will be executed to parse the provided URL.

Demo

@JSFiddle

Examples

Example A

https://www.example.org:5887/foo/bar?a=1&b=-2#section-1

{
    "protocol": "https:",
    "host": "www.example.org:5887",
    "hostname": "www.example.org",
    "port": "5887",
    "pathname": "/foo/bar",
    "search": "?a=1&b=-2",
    "hash": "section-1",
    "href": "https://www.example.org:5887/foo/bar?a=1&b=-2#section-1",
    "requestUri": "/foo/bar?a=1&b=-2",
    "parameters": {
        "a": 1,
        "b": -2
    }
}

Example B

ftp://www.files.com:22/folder?version=2.31&type=doc

{
    "protocol": "ftp:",
    "host": "www.files.com:22",
    "hostname": "www.files.com",
    "port": "22",
    "pathname": "/folder",
    "search": "?version=2.31&type=doc",
    "hash": "",
    "href": "ftp://www.files.com:22/folder?version=2.31&type=doc",
    "requestUri": "/folder?version=2.31&type=doc",
    "parameters": {
        "version": 2.31,
        "type": "doc"
    }
}
/**
* A URL parser written in JavaScript.
* Copyright (C) 2015 Ryan Kane
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var URLParser = (function(document) {
var COMPONENTS = 'protocol host hostname port pathname search hash href'.split(' ');
var PROPS = COMPONENTS.concat('port requestUri parameters'.split(' '));
var URI_PATTERN = /^((?:ht|f)tp(?:s?)?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)(\/[^?#]*)(\?[^#]*|)(#.*|)$/;
var prependIf = function(value, char) {
return value.indexOf(char) !== 0 ? char + value : value;
};
var parseParamVal = function(value) {
if (value.match(/^-?\d+$/)) {
return parseInt(value, 10);
} else if (value.match(/^-?\d+\.\d+$/)) {
return parseFloat(value);
}
return value;
};
var parseParams = function(query) {
query = query.substring(1) || '';
var params = {};
var pairs = query.split('&');
if (pairs[0].length > 1) {
pairs.forEach(function(pair) {
var param = pair.split("=");
var key = decodeURI(param[0]);
var val = parseParamVal(decodeURI(param[1]));
if (params[key] === undefined) {
params[key] = val;
} else if (typeof params[key] === "string") {
params[key] = [params[key], val];
} else {
params[key].push(val);
}
}, this);
}
return params;
};
var self = function(debug) {
this.debug = debug;
this.domExists = document !== undefined;
if (this.domExists) {
this.aEl = document.createElement('a');
}
};
self.prototype.parse = function(url) {
var success = false;
if (this.domExists && !this.debug) {
this.aEl.href = url;
if (this.aEl.host == "") {
this.aEl.href = this.aEl.href;
}
COMPONENTS.forEach(function(prop) {
this[prop] = this.aEl[prop];
}, this);
success = true;
} else {
var match = url.match(URI_PATTERN);
if (match) {
COMPONENTS.forEach(function(component, index) {
this[component] = match[index + 1] || '';
}, this);
success = true;
}
}
if (success) {
this.href = url;
this.hash = this.hash.substr(1);
this.pathname = prependIf(this.pathname, '/');
this.requestUri = this.pathname + this.search;
this.parameters = parseParams(this.search);
}
return this.toObj();
};
self.prototype.toObj = function() {
var obj = {};
PROPS.forEach(function(prop) {
obj[prop] = this[prop];
}, this);
return obj;
};
self.prototype.toString = function() {
return this.href;
};
return self;
})(document);
/**
* A URL parser written in JavaScript.
* Copyright (C) 2015 Ryan Kane
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var URLParser=function(t){var s="protocol host hostname port pathname search hash href".split(" "),h=s.concat("port requestUri parameters".split(" ")),i=/^((?:ht|f)tp(?:s?)?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)(\/[^?#]*)(\?[^#]*|)(#.*|)$/,r=function(t,s){return 0!==t.indexOf(s)?s+t:t},e=function(t){return t.match(/^-?\d+$/)?parseInt(t,10):t.match(/^-?\d+\.\d+$/)?parseFloat(t):t},a=function(t){t=t.substring(1)||"";var s={},h=t.split("&");return h[0].length>1&&h.forEach(function(t){var h=t.split("="),i=decodeURI(h[0]),r=e(decodeURI(h[1]));void 0===s[i]?s[i]=r:"string"==typeof s[i]?s[i]=[s[i],r]:s[i].push(r)},this),s},n=function(s){this.debug=s,this.domExists=void 0!==t,this.domExists&&(this.aEl=t.createElement("a"))};return n.prototype.parse=function(t){var h=!1;if(this.domExists&&!this.debug)this.aEl.href=t,""==this.aEl.host&&(this.aEl.href=this.aEl.href),s.forEach(function(t){this[t]=this.aEl[t]},this),h=!0;else{var e=t.match(i);e&&(s.forEach(function(t,s){this[t]=e[s+1]||""},this),h=!0)}return h&&(this.href=t,this.hash=this.hash.substr(1),this.pathname=r(this.pathname,"/"),this.requestUri=this.pathname+this.search,this.parameters=a(this.search)),this.toObj()},n.prototype.toObj=function(){var t={};return h.forEach(function(s){t[s]=this[s]},this),t},n.prototype.toString=function(){return this.href},n}(document);
var urls = [
'https://www.example.org:5887/foo/bar?a=1&b=-2#section-1',
'ftp://www.files.com:22/folder?version=2.31&type=doc'
];
var parser1 = new URLParser();
var parser2 = new URLParser(true);
urls.forEach(function(url) {
println(parser1.parse(url), '#FFF', '#00A');
println(parser2.parse(url), '#FFF', '#A00');
});
function println(val, bgColor, fgColor) {
if (typeof val === 'object') {
val = JSON.stringify(val, undefined, ' ');
}
console.log('%c ' + val, 'background: ' + bgColor + '; color: ' + fgColor);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment