I always want to shoot myself in the head when looking at code like the following:
var url = "http://example.org/foo?bar=baz",
separator = url.indexOf('?') > -1 ? '&' : '?';
url += separator + encodeURIComponent("foo") + "=" + encodeURIComponent("bar");
I still can't believe javascript - the f**ing backbone-language of the web - doesn't offer an API for mutating URLs. Browsers (Firefox) don't expose the Location
object (the structure behind window.location). Yes, one could think of decomposed IDL attributes as a native URL management library. But it relies on the DOM element <a>, it's slow and doesn't offer any convenienve at all.
How about a nice, clean and simple API for mutating URIs:
var url = new URI("http://example.org/foo?bar=baz");
url.addQuery("foo", "bar");
URI.js is here to help with that.
// mutating URLs
URI("http://example.org/foo.html?hello=world")
.username("rodneyrehm")
// -> http://[email protected]/foo.html?hello=world
.username("")
// -> http://example.org/foo.html?hello=world
.directory("bar")
// -> http://example.org/bar/foo.html?hello=world
.suffix("xml")
// -> http://example.org/bar/foo.xml?hello=world
.query("")
// -> http://example.org/bar/foo.xml
.tld("com")
// -> http://example.com/bar/foo.xml
.query({ foo: "bar", hello: ["world", "mars"] });
// -> http://example.com/bar/foo.xml?foo=bar&hello=world&hello=mars
// cleaning things up
URI("?&foo=bar&&foo=bar&foo=baz&")
.normalizeQuery();
// -> ?foo=bar&foo=baz
// working with relative paths
URI("/foo/bar/baz.html")
.relativeTo("/foo/bar/world.html");
// -> ./baz.html
URI("/foo/bar/baz.html")
.relativeTo("/foo/bar/sub/world.html")
// -> ../baz.html
.absoluteTo("/foo/bar/sub/world.html");
// -> /foo/bar/baz.html
See the About Page and API Docs for more stuff.
npm install URIjs
var URI = require('URIjs');
URI("/foo/bar/baz.html")
.relativeTo("/foo/bar/sub/world.html")
// -> ../baz.html
// ==ClosureCompiler==
// @compilation_level SIMPLE_OPTIMIZATIONS
// @output_file_name URI.min.js
// @code_url http://medialize.github.com/URI.js/src/IPv6.js
// @code_url http://medialize.github.com/URI.js/src/punycode.js
// @code_url http://medialize.github.com/URI.js/src/SecondLevelDomains.js
// @code_url http://medialize.github.com/URI.js/src/URI.js
// ==/ClosureCompiler==
Docs where you get more info on parsing and working with URLs
- Uniform Resource Identifiers (URI): Generic Syntax (superseded by 3986)
- Internationalized Resource Identifiers (IRI)
- IPv6 Literal Addresses in URL's (superseded by 3986)
- Punycode - Internationalized Domain Name (IDN) (html version)
- URI - Reference Resolution
- Parsing URLs for Fun and Profit
- application/x-www-form-urlencoded (Query String Parameters) and application/x-www-form-urlencoded encoding algorithm
- Naming URL components
- Java URI Class
- Java Inet6Address Class
- Node.js URL API
- https://www.w3.org/Bugs/Public/show_bug.cgi?id=14148
- http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#workerlocation
- MozURLProperty (not documented yet?!) https://developer.mozilla.org/User:trevorh/Interface_documentation_status
If you don't like URI.js, you may like one of these:
- The simple URL Mutation "Hack" (jsPerf comparison)
- URI Parser
- jQuery-URL-Parser
- URL.js
- furl (Python)
- mediawiki Uri (needs mw and jQuery)
- Google Closure Uri
- URI.js by Gary Court
- jurlp
if you want to get involved, these are things you could help out with…
- modifiers for domain, tld, directory, file, suffix are hardly the most performant solutions
- add Media Fragments
- add URI Templating
- add :local-link to jquery.URI.js
- punycode.js - Mathias Bynens
- IPv6.js - Rich Brown - (rewrite of the original)
URI.js is published under the MIT license and GPL v3.
- fixing
.absoluteTo()
to join two relative paths properly (Issue #29) - adding
.clone()
to copy an URI instance
.directory()
now returns empty string if there is no directory- fixing
.absoluteTo()
to join two relative paths properly (Issue #29)
- fixing TypeError on domain() with dot-less hostnames (Issue #27)
- adding URN (
javascript:
,mailto:
, ...) support - adding
.scheme()
as alias of.protocol()
- adding
.userinfo()
to comply with terminology of RFC 3986 - adding jQuery Plugin
src/jquery.URI.js
- Fixing relative scheme URLs (Issue #19 byroot)
- adding Second Level Domain (SLD) Support (Issue #17)
- fixed global scope leakage (Issue #15 mark-rushakoff)
- added CommonJS compatibility (Issue #11, Evangenieur)
- added URI.iso8859() and URI.unicode() to switch base charsets (Issue #10, mortenn)
- added .iso8859() and .unicode() to convert an URI's escape encoding
- Updated Punycode.js to version 0.3.0
- added edge-case tests ("jim")
- fixed edge-cases in .protocol(), .port(), .subdomain(), .domain(), .tld(), .filename()
- fixed parsing of hostname in .hostname()
- added .subdomain() convenience accessor
- improved internal deferred build handling
- fixed thrown Error for
URI("http://example.org").query(true)
(Issue #6) - added examples for extending URI.js for fragment abuse, see src/URI.fragmentQuery.js and src/URI.fragmentURI.js (Issue #2)
- added .equals() for URL comparison
- proper encoding/decoding for .pathname(), .directory(), .filename() and .suffix() according to RFC 3986 3.3
- escape spaces in query strings with
+
according to application/x-www-form-urlencoded - allow URI.buildQuery() to build duplicate key=value combinations
- added URI(string, string) constructor to conform with the specification
- added .readable() for humanly readable representation of encoded URIs
- fixed bug where @ in pathname would be parsed as part of the authority
- URI.withinString()
- added .normalizeProtocol() to lowercase protocols
- made .normalizeHostname() lowercase hostnames
- replaced String.substr() by String.substring() (Issue #1)
- parse "?foo" to
{foo: null}
Algorithm for collecting URL parameters - build
{foo: null, bar: ""}
to "?foo&bar=" Algorithm for serializing URL parameters - fixed RegExp escaping
- Initial URI.js