Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

url-parse

Package Overview
Dependencies
Maintainers
2
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

url-parse - npm Package Compare versions

Comparing version 0.0.4 to 0.1.0

fuzzy.js

190

index.js
'use strict';
var required = require('requires-port')
, lolcation = require('./lolcation')
, qs = require('querystringify');
//
// MOARE: Mother Of All Regular Expressions.
//
var regexp = /^(?:(?:(([^:\/#\?]+:)?(?:(?:\/\/)(?:(?:(?:([^:@\/#\?]+)(?:\:([^:@\/#\?]*))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((?:\/?(?:[^\/\?#]+\/+)*)(?:[^\?#]*)))?(\?[^#]+)?)(#.*)?/
, keys = ',,protocol,username,password,host,hostname,port,pathname,query,hash'.split(',')
, parts = keys.length;
/**
* A DOM and Node.js compatible URL parser which leverages the DOM to do the
* actual parsing of our URLs.
* The actual URL instance. Instead of returning an object we've opted-in to
* create an actual constructor as it's much more memory efficient and
* faster and it pleases my CDO.
*
* @type {Function}
* @param {String} url URL that needs to be parsed.
* @param {Boolean} qs Also parse the query string.
* @returns {Object} A parsed URL.
* @constructor
* @param {String} address URL we want to parse.
* @param {Boolean|function} parser Parser for the query string.
* @param {Object} location Location defaults for relative paths.
* @api public
*/
var parse = 'undefined' !== typeof document ? function parse(url, qs) {
var div = document.createElement('div')
, data = {}
, key
, a;
function URL(address, location, parser) {
if (!(this instanceof URL)) return new URL(address, location, parser);
//
// Uses an innerHTML property to obtain an absolute URL for older browser
// support like IE6.
// The following if statements allows this module two have compatibility with
// 2 different API:
//
// @see http://grack.com/blog/2009/11/17/absolutizing-url-in-javascript/
// 1. Node.js's `url.parse` api which accepts a URL, boolean as arguments
// where the boolean indicates that the query string should also be parsed.
//
div.innerHTML = '<a href="' + url + '"/>';
a = div.firstChild;
// 2. The `URL` interface of the browser which accepts a URL, object as
// arguments. The supplied object will be used as default values / fall-back
// for relative paths.
//
// Transform it from a readOnly object to a read/writable object so we can
// change some parsed values. This is required if we ever want to override
// a port number etc. (as browsers remove port 443 and 80 from the URL's).
//
for (key in a) {
if ('string' === typeof a[key] || 'number' === typeof a[key]) {
data[key] = a[key];
}
}
if ('object' !== typeof location) { parser = location; location = null; }
if (parser && 'function' !== typeof parser) parser = qs.parse;
//
// encodeURI and decodeURI are needed to normalize URL between IE and non-IE,
// since IE doesn't encode the href property value and return it
//
// @see http://jsfiddle.net/Yq9M8/1/
//
data.href = encodeURI(decodeURI(data.href));
location = lolcation(location);
//
// If we don't obtain a port number (e.g. when using zombie) then try
// and guess at a value from the 'href' value.
//
if (!data.port) {
var splits = (data.href || '').split('/');
if (splits.length > 2) {
var host = splits[2]
, atSignIndex = host.lastIndexOf('@');
for (var i = 0, bits = regexp.exec(address), key; i < parts; key = keys[++i]) {
if (key) {
this[key] = bits[i] || location[key] || '';
if (~atSignIndex) host = host.slice(atSignIndex + 1);
splits = host.split(':');
if (splits.length === 2) data.port = splits[1];
//
// The protocol, host, host name should always be lower cased even if they
// are supplied in uppercase. This way, when people generate an `origin`
// it be correct.
//
if (i === 2 || i === 5 || i === 6) this[key] = this[key].toLowerCase();
}

@@ -65,93 +58,60 @@ }

//
// IE quirk: The `protocol` is parsed as ":" when a protocol agnostic URL
// is used. In this case we extract the value from the `href` value. In
// addition to that, it's possible in IE11 that the protocol is an string for
// relative URL's.
// Also parse the supplied query string in to an object. If we're supplied
// with a custom parser as function use that instead of the default build-in
// parser.
//
// @see https://github.com/primus/primus/issues/242
//
if (!data.protocol || ':' === data.protocol) {
data.protocol = data.href.substr(0, data.href.indexOf(':') + 1);
}
if (parser) this.query = parser(this.query);
//
// Safari 5.1.7 (windows) quirk: When parsing a URL without a port number
// the `port` in the data object will default to "0" instead of the expected
// "". We're going to do an explicit check on "0" and force it to "".
// We should not add port numbers if they are already the default port number
// for a given protocol. As the host also contains the port number we're going
// override it with the hostname which contains no port number.
//
if ('0' === data.port) data.port = '';
//
// Browsers do not parse authorization information, so we need to extract
// that from the URL.
//
if (~data.href.indexOf('@') && !data.auth) {
var start = data.protocol.length + 2;
data.auth = data.href.slice(start, data.href.indexOf(data.pathname, start)).split('@')[0];
if (!required(this.port, this.protocol)) {
this.host = this.hostname;
this.port = '';
}
if (qs && 'string' === typeof data.query) {
data.query = querystring(data.query || data.search);
}
data.query = data.query || data.search;
return data;
} : require('url').parse;
/**
* Simple query string parser.
*
* @param {String} query The query string that needs to be parsed.
* @returns {Object}
* @api public
*/
function querystring(query) {
var parser = /([^=?&]+)=([^&]*)/g
, result = {}
, part;
//
// Little nifty parsing hack, leverage the fact that RegExp.exec increments
// the lastIndex property so we can continue executing this loop until we've
// parsed all results.
// The href is just the compiled result.
//
for (;
part = parser.exec(query);
result[decodeURIComponent(part[1])] = decodeURIComponent(part[2])
);
return result;
this.href = this.toString();
}
/**
* Transform a query string to an object.
* Transform the properties back in to a valid and full URL string.
*
* @param {Object} obj Object that should be transformed.
* @param {Function} stringify Optional query stringify function.
* @returns {String}
* @api public
*/
function querystringify(obj, prefix) {
prefix = prefix || '';
URL.prototype.toString = function toString(stringify) {
if (!stringify || 'function' !== typeof stringify) stringify = qs.stringify;
var pairs = [];
var result = this.protocol +'//'
, query;
//
// Optionally prefix with a '?' if needed
//
if ('string' !== typeof prefix) prefix = '?';
if (this.username) result += this.username +':'+ this.password +'@';
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
pairs.push(encodeURIComponent(key) +'='+ encodeURIComponent(obj[key]));
}
result += this.hostname;
if (this.port) result += ':'+ this.port;
result += this.pathname;
if (this.query) {
if ('object' === typeof this.query) query = stringify(this.query);
else query = this.query;
result += (query.charAt(0) === '?' ? '' : '?') + query;
}
return prefix + pairs.join('&');
}
if (this.hash) result += this.hash;
return result;
};
//
// Expose the module.
// Expose the URL parser.
//
parse.querystringify = querystringify;
parse.querystring = querystring;
module.exports = parse;
URL.qs = qs;
module.exports = URL;
{
"name": "url-parse",
"version": "0.0.4",
"version": "0.1.0",
"description": "Parse URL in node using the URL module and in the browser using the DOM",

@@ -10,3 +10,3 @@ "main": "index.js",

"test-travis": "istanbul cover node_modules/.bin/_mocha --report lcovonly -- --reporter spec --ui bdd test.js",
"browserify": "browserify index.js -o browserified.js"
"browserify": "browserify index.js -o dist/url-parse.js --standalone URLParse"
},

@@ -53,3 +53,7 @@ "keywords": [

"url": "https://github.com/unshiftio/url-parse"
},
"dependencies": {
"querystringify": "0.0.x",
"requires-port": "0.0.x"
}
}
# url-parse
[![Made by unshift](https://img.shields.io/badge/made%20by-unshift-00ffcc.svg?style=flat-square)](http://unshift.io)[![Version npm](http://img.shields.io/npm/v/url-parse.svg?style=flat-square)](http://browsenpm.org/package/url-parse)[![Build Status](http://img.shields.io/travis/unshiftio/url-parse/master.svg?style=flat-square)](https://travis-ci.org/unshiftio/url-parse)[![Dependencies](https://img.shields.io/david/unshiftio/url-parse.svg?style=flat-square)](https://david-dm.org/unshiftio/url-parse)[![Coverage Status](http://img.shields.io/coveralls/unshiftio/url-parse/master.svg?style=flat-square)](https://coveralls.io/r/unshiftio/url-parse?branch=master)[![IRC channel](http://img.shields.io/badge/IRC-irc.freenode.net%23unshift-00a8ff.svg?style=flat-square)](http://webchat.freenode.net/?channels=unshift)
[![Build Status](https://travis-ci.org/unshiftio/url-parse.svg?branch=master)](https://travis-ci.org/unshiftio/url-parse)
[![NPM version](https://badge.fury.io/js/url-parse.svg)](http://badge.fury.io/js/url-parse)
[![Coverage Status](https://img.shields.io/coveralls/unshiftio/url-parse.svg)](https://coveralls.io/r/unshiftio/url-parse?branch=master)
The `url-parse` method exposes two different API interfaces. The `url` interface
that you know from Node.js and the new `URL` interface that is available in the
latest browsers.
When required on node it will expose the `url` module's `.parse` method. When
required in the browser it will offload the URL parsing to the `<a>` element in
the DOM. This allows the module to be really tiny on the browser and still be
usable on node.
Since `0.1` we've moved away from using the DOM's `<a>` element for URL parsing
and moving to a full Regular Expression solution. The main reason for this
change is to make the URL parser available in different JavaScript environments
as you don't always have access to the DOM like `Worker` environments. This
module still have a really small foot print as this module's main intention is
to be bundled with client-side code.
In addition to parsing URL's it also has a really simple query string parser and
query string stringify.
In addition to URL parsing we also expose the bundled `querystringify` module.

@@ -31,33 +33,45 @@ ## Installation

var parse = require('url-parse');
var URL = require('url-parse');
```
To parse an URL simply call the `parse` method with the URL that needs to be
To parse an URL simply call the `URL` method with the URL that needs to be
transformed in to an object.
```js
var url = parse('https://github.com/foo/bar');
var url = new URL('https://github.com/foo/bar');
```
The URL should now be somewhat the same as the node.js's `url.parse` output. The
notable exception being that in the browser not all properties would be set to
null.
The `new` keyword is optional but it will save you an extra function invocation.
In the example above we've demonstrated the URL interface, but as said in the
module description we also support the node.js interface. So you could also use
the library in this way:
### parse.querystring()
```js
'use strict';
Parse the given query string and return an object representation from it.
```js
parse.querystring('foo=bar&bar=foo');
parse.querystring('?foo=bar&bar=foo');
var parse = require('url-parse')
, url = parse('https://github.com/foo/bar', true);
```
### parse.querystringify()
The returned `url` instance contains the following properties:
Take an object and make a query string from it.
- `protocol`: Without slashes `http:`.
- `username`: Username of basic authentication.
- `password`: Password of basic authentication.
- `host`: Host name with port number.
- `hostname`: Host name without port number.
- `port`: Optional port number.
- `pathname`: URL path.
- `query`: Prefixed with `?`
- `hash`: Prefixed with `#`
## URL.stringify()
The returned `url` object comes with a custom `toString` method which will
generate a full URL again when called. The method accepts an extra function
which will stringify the query string for you. If you don't supply a function we
will use our default method.
```js
parse.querystringify({ foo: 'bar' }); // foo=bar
parse.querystringify({ foo: 'bar' }, true); // ?foo=bar
parse.querystringify({ foo: 'bar' }, '&'); // &foo=bar
var location = url.toString(); // http://example.com/whatever/?qs=32
```

@@ -64,0 +78,0 @@

@@ -5,5 +5,3 @@ describe('url-parse', function () {

var assume = require('assume')
, parse = require('./')
, qs = parse.querystring
, qsify = parse.querystringify;
, parse = require('./');

@@ -14,53 +12,104 @@ it('exposes parse as a function', function () {

describe('#querystringify', function () {
var obj = {
foo: 'bar',
bar: 'foo'
};
it('parsers the query string', function () {
var url = 'http://google.com/?foo=bar'
, data = parse(url, true);
it('is exposed as method', function () {
assume(qsify).is.a('function');
});
assume(data.query).is.a('object');
assume(data.query.foo).equals('bar');
});
it('transforms an object', function () {
assume(qsify(obj)).equals('foo=bar&bar=foo');
});
it('allows a custom function as parser', function () {
var url = 'http://google.com/?foo=bar'
, data = parse(url, function () { return '1337'; });
it('can optionally prefix', function () {
assume(qsify(obj, true)).equals('?foo=bar&bar=foo');
});
assume(data.query).equals('1337');
});
it('can prefix with custom things', function () {
assume(qsify(obj, '&')).equals('&foo=bar&bar=foo');
});
it('allows a custom stringify function', function () {
var url = 'http://google.com/?foo=bar'
, data = parse(url, true)
, str;
str = data.toString(function () { return 'lolcakes'; });
assume(str).equals('http://google.com/?lolcakes');
});
describe('querystring', function () {
it('is exposed as method', function () {
assume(qs).is.a('function');
});
it('allows a custom location object', function () {
var url = '/foo?foo=bar'
, data = parse(url, parse('http://google.com'));
it('will parse a querystring to an object', function () {
var obj = qs('foo=bar');
assume(data.href).equals('http://google.com/foo?foo=bar');
});
assume(obj).is.a('object');
assume(obj.foo).equals('bar');
});
it('is blob: location aware', function () {
var blob = {"hash":"","search":"","pathname":"https%3A//gist.github.com/3f272586-6dac-4e29-92d0-f674f2dde618","port":"","hostname":"","host":"","protocol":"blob:","origin":"https://gist.github.com","href":"blob:https%3A//gist.github.com/3f272586-6dac-4e29-92d0-f674f2dde618"}
, url = '/unshiftio/url-parse'
, data = parse(url, blob);
it('will parse the `query` property of the parse', function () {
var url = parse('https://google.com?foo=bar')
, obj = qs(url.query);
assume(data.href).equals('https://gist.github.com/unshiftio/url-parse');
});
assume(obj).is.a('object');
assume(obj.foo).equals('bar');
});
it('converts protocol to lowercase', function () {
var url = 'HTTP://example.com';
it('will also work if querystring is prefixed with ?', function () {
var obj = qs('?foo=bar&shizzle=mynizzle');
assume(parse(url).protocol).equals('http:');
});
assume(obj).is.a('object');
assume(obj.foo).equals('bar');
assume(obj.shizzle).equals('mynizzle');
});
it('converts hostname to lowercase', function () {
var url = 'HTTP://fOo.eXaMPle.com';
assume(parse(url).hostname).equals('foo.example.com');
});
it('does not lowercase the USER:PASS', function () {
var url = 'HTTP://USER:PASS@EXAMPLE.COM';
assume(parse(url).username).equals('USER');
assume(parse(url).password).equals('PASS');
});
it('does not lowercase the path', function () {
var url = 'HTTP://X.COM/Y/Z';
assume(parse(url).pathname).equals('/Y/Z');
});
it('removes default port numbers', function () {
var url = 'http://example.com:80'
, parsed = parse(url);
assume(parsed.port).equals('');
assume(parsed.host).equals('example.com');
assume(parsed.hostname).equals('example.com');
assume(parsed.href).equals('http://example.com');
});
it('accepts @ in pathnames', function () {
var url = 'http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=';
assume(parse(url).pathname).equals('/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=');
});
it('accepts multiple ???', function () {
var url = 'http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=';
assume(parse(url).query).equals('???&hl=en&src=api&x=2&y=2&z=3&s=');
});
describe('fuzzy', function () {
var fuzz = require('./fuzzy')
, times = 10;
for (var i = 0; i < times; i++) {
(function (spec) {
it('parses: '+ spec.href, function () {
var url = parse(spec.href)
, prop;
for (prop in spec) {
assume(url[prop]).equals(spec[prop]);
}
});
})(fuzz());
}
});
});

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc