├── .checkbuild ├── .editorconfig ├── .gitignore ├── .jshintrc ├── .nvmrc ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.js ├── package.json ├── scripts ├── changelog └── ci │ └── start └── test └── main.js /.checkbuild: -------------------------------------------------------------------------------- 1 | { 2 | "checkbuild": { 3 | // "buddyjs" 4 | "enable": ["david", "jshint", "jsinspect", "nsp"], 5 | // don't exit immediately if one of the tools reports an error (default true) 6 | "continueOnError": true, 7 | // don't exit(1) even if we had some failures (default false) 8 | "allowFailures": false 9 | }, 10 | "jshint": { 11 | "args": ["*.js"] 12 | }, 13 | "jsinspect": { 14 | "args": ["*.js"] 15 | }, 16 | "jscs": { 17 | "args": ["lib/**.js"], 18 | "url":"https://raw.githubusercontent.com/FGRibreau/javascript/master/.jscsrc" 19 | }, 20 | "david": { 21 | "error": { 22 | "ESCM": false 23 | } 24 | }, 25 | "nsp": {} 26 | } 27 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | # 4 space indentation 12 | [*.js] 13 | indent_style = space 14 | indent_size = 2 15 | 16 | 17 | # Indentation override for all JS under lib directory 18 | #[lib/**.js] 19 | #indent_style = space 20 | #indent_size = 2 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Deployed apps should consider commenting this line out: 24 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 25 | node_modules 26 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "maxerr" : 50, // {int} Maximum error before stopping 3 | 4 | // Enforcing 5 | "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) 6 | "camelcase" : false, // true: Identifiers must be in camelCase 7 | "curly" : true, // true: Require {} for every new block or scope 8 | "eqeqeq" : true, // true: Require triple equals (===) for comparison 9 | "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() 10 | "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` 11 | "indent" : 2, // {int} Number of spaces to use for indentation 12 | "latedef" : false, // true: Require variables/functions to be defined before being used 13 | "newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()` 14 | "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` 15 | "noempty" : true, // true: Prohibit use of empty blocks 16 | "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment) 17 | "plusplus" : false, // true: Prohibit use of `++` & `--` 18 | "quotmark" : false, // Quotation mark consistency: 19 | // false : do nothing (default) 20 | // true : ensure whatever is used is consistent 21 | // "single" : require single quotes 22 | // "double" : require double quotes 23 | "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) 24 | "unused" : true, // true: Require all defined variables be used 25 | "strict" : true, // true: Requires all functions run in ES5 Strict Mode 26 | "trailing" : false, // true: Prohibit trailing whitespaces 27 | "maxparams" : 5, // {int} Max number of formal params allowed per function 28 | "maxdepth" : 4, // {int} Max depth of nested blocks (within functions) 29 | "maxstatements" : 25, // {int} Max number statements per function 30 | "maxcomplexity" : 6, // {int} Max cyclomatic complexity per function 31 | "maxlen" : false, // {int} Max number of characters per line 32 | 33 | // Relaxing 34 | "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) 35 | "boss" : false, // true: Tolerate assignments where comparisons would be expected 36 | "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. 37 | "eqnull" : false, // true: Tolerate use of `== null` 38 | "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) 39 | "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`) 40 | "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) 41 | // (ex: `for each`, multiple try/catch, function expression…) 42 | "evil" : false, // true: Tolerate use of `eval` and `new Function()` 43 | "expr" : false, // true: Tolerate `ExpressionStatement` as Programs 44 | "funcscope" : false, // true: Tolerate defining variables inside control statements" 45 | "globalstrict" : true, // true: Allow global "use strict" (also enables 'strict') 46 | "iterator" : false, // true: Tolerate using the `__iterator__` property 47 | "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block 48 | "laxbreak" : false, // true: Tolerate possibly unsafe line breakings 49 | "laxcomma" : true, // true: Tolerate comma-first style coding 50 | "loopfunc" : false, // true: Tolerate functions being defined in loops 51 | "multistr" : true, // true: Tolerate multi-line strings 52 | "proto" : false, // true: Tolerate using the `__proto__` property 53 | "scripturl" : false, // true: Tolerate script-targeted URLs 54 | "smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment 55 | "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` 56 | "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation 57 | "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` 58 | "validthis" : false, // true: Tolerate using this in a non-constructor function 59 | 60 | // Environments 61 | "browser" : true, // Web Browser (window, document, etc) 62 | "couch" : false, // CouchDB 63 | "devel" : true, // Development/debugging (alert, confirm, etc) 64 | "dojo" : false, // Dojo Toolkit 65 | "jquery" : false, // jQuery 66 | "mootools" : false, // MooTools 67 | "node" : true, // Node.js 68 | "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) 69 | "prototypejs" : false, // Prototype and Scriptaculous 70 | "rhino" : false, // Rhino 71 | "worker" : false, // Web Workers 72 | "wsh" : false, // Windows Scripting Host 73 | "yui" : false, // Yahoo User Interface 74 | 75 | // Legacy 76 | "nomen" : false, // true: Prohibit dangling `_` in variables 77 | "onevar" : false, // true: Allow only one `var` statement per function 78 | "passfail" : false, // true: Stop on first error 79 | "white" : false, // true: Check against strict whitespace and indentation rules 80 | 81 | // Custom Globals 82 | "predef" : [ 83 | "Buffer", 84 | "view", 85 | "test", 86 | "factoryKey", 87 | "RedisStub", 88 | "equal", 89 | "strictEqual", 90 | "ok", 91 | "deepEqual", 92 | "expect", 93 | "checkGrid", 94 | 95 | "describe", 96 | "beforeEach", 97 | "afterEach", 98 | "it", 99 | 100 | "module", 101 | "prompt", 102 | "require", 103 | "exports", 104 | "console", 105 | "__dirname", 106 | "process", 107 | "setInterval", 108 | "setTimeout", 109 | "clearTimeout", 110 | "Redsmin", 111 | "window", 112 | "Backbone", 113 | "bootbox", 114 | "Highcharts", 115 | "ReadLine", 116 | "CodeMirror", 117 | "$", 118 | "jQuery", 119 | "document", 120 | "angular", 121 | "alert", 122 | "grunt", 123 | "escape", 124 | "walk", 125 | "deepStrictEqual", 126 | "returnfalse", 127 | "forEachAsync", 128 | "humanize", 129 | "Mousetrap", 130 | "store", 131 | "Slick", 132 | "Slickback"] // additional predefined global variables 133 | } 134 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v0.10 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## [v1.2.0](https://github.com/fgribreau/node-tolerant-url-parser/tree/v1.2.0) (2015-04-05) 4 | 5 | [Full Changelog](https://github.com/fgribreau/node-tolerant-url-parser/compare/v1.1.0...v1.2.0) 6 | 7 | ## [v1.1.0](https://github.com/fgribreau/node-tolerant-url-parser/tree/v1.1.0) (2015-04-05) 8 | 9 | 10 | 11 | \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Francois-Guillaume Ribreau 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | tolerant url-parser [![Build Status](https://drone.io/github.com/FGRibreau/node-tolerant-url-parser/status.png)](https://drone.io/github.com/FGRibreau/node-tolerant-url-parser/latest) [![Deps](https://david-dm.org/FGRibreau/node-tolerant-url-parser.png)](https://david-dm.org/FGRibreau/node-tolerant-url-parser) 2 | ======================== 3 | 4 | Overly tolerant url parser specialized in parsing protocol, auth (even invalid ones), host and port url parts. 5 | 6 | [![npm](https://nodei.co/npm/tolerant.png)](https://npmjs.org/package/tolerant) 7 | 8 | ### Sponsored by 9 | 10 |

11 | tolerant-url-parser development was sponsored by Redsmin, a fully loaded administration service for Redis.

12 | 13 |

14 | 15 | ### Usage 16 | 17 | ```javascript 18 | var TolerantUrl = require('tolerant'); 19 | 20 | console.log(TolerantUrl.parse('protocol://user:auth@domain.com:port/path/a')); 21 | 22 | // should print 23 | { 24 | 'protocol': 'protocol:', 25 | 'auth': 'user:auth', 26 | 'hostname': 'domain.com', 27 | 'host': 'domain.com:port', 28 | 'port': 'port', 29 | 'href': 'protocol://user:auth@domain.com:port/path/a', 30 | 'path': '/path/a' 31 | } 32 | 33 | // and that's all. 34 | ``` 35 | 36 | ### How `tolerant` differs from nodejs url.parse 37 | 38 | NodeJS [url standard library](nodejs.org/docs/latest/api/url.html): 39 | 40 | ```javascript 41 | require('url') 42 | .parse('redis://plop:z4fsoV:_git://53c2nd@koo3@1hFldzFG/2ojyPwcTCPZgRo=@redsmin.com:6379') 43 | { 44 | protocol: 'redis:', 45 | slashes: true, 46 | auth: null, 47 | host: 'plop', 48 | port: null, 49 | hostname: 'plop', 50 | hash: null, 51 | search: null, 52 | query: null, 53 | pathname: '/:z4fsoV:_git//53c2nd@koo3@1hFldzFG/2ojyPwcTCPZgRo=@redsmin.com:6379', 54 | path: '/:z4fsoV:_git//53c2nd@koo3@1hFldzFG/2ojyPwcTCPZgRo=@redsmin.com:6379', 55 | href: 'redis://plop/:z4fsoV:_git//53c2nd@koo3@1hFldzFG/2ojyPwcTCPZgRo=@redsmin.com:6379' 56 | } 57 | ``` 58 | 59 | `url.parse` was not able to extract the auth while the tolerant url-parser can: 60 | 61 | ```javascript 62 | require('tolerant') 63 | .parse('redis://plop:z4fsoV:_git://53c2nd@koo3@1hFldzFG/2ojyPwcTCPZgRo=@redsmin.com:6379') 64 | { 65 | protocol: 'redis:', 66 | auth: 'plop:z4fsoV:_git://53c2nd@koo3@1hFldzFG/2ojyPwcTCPZgRo=', 67 | hostname: 'redsmin.com', 68 | host: 'redsmin.com:6379', 69 | port: '6379', 70 | href: 'redis://plop:z4fsoV:_git://53c2nd@koo3@1hFldzFG/2ojyPwcTCPZgRo=@redsmin.com:6379', 71 | path: null 72 | } 73 | ``` 74 | 75 | Check `test/main.js` for examples of weird urls parsed by `tolerant`. 76 | 77 | ### [Changelog](/CHANGELOG.md) 78 | 79 | ### License 80 | 81 | Copyright (c) 2014, Francois-Guillaume Ribreau node@fgribreau.com. 82 | 83 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 84 | 85 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 86 | 87 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 88 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | Overly tolerant url parser 4 | */ 5 | 6 | var Url = module.exports = { 7 | PROTOCOL: '://', 8 | COLON: ':', 9 | AT: '@', 10 | SLASH: '/', 11 | parse: function (url) { 12 | // first parse auth/host/port 13 | var parsed = this._parse(url); 14 | 15 | // then handle path (quick & dirty way) 16 | ['host', 'hostname', 'port'].forEach(function (part) { 17 | if (strCount(parsed[part], this.SLASH) > 0) { 18 | var pair = parsed[part].split(this.SLASH); 19 | parsed[part] = pair.shift(); 20 | parsed.path = this.SLASH + pair.join(this.SLASH); 21 | } 22 | }, this); 23 | 24 | return parsed; 25 | }, 26 | _parse: function (url) { 27 | var parsed = { 28 | protocol: null, // string 29 | auth: null, // string 30 | hostname: null, // string 31 | host: null, // string 32 | port: null, // string 33 | href: url, // string 34 | path: null 35 | }; 36 | 37 | // check protocol 38 | var protocolIdx = url.indexOf(this.PROTOCOL); 39 | if (protocolIdx !== -1) { 40 | parsed.protocol = url.substring(0, protocolIdx + 1); 41 | protocolIdx += this.PROTOCOL.length; 42 | // remove the protocol part from the url 43 | url = url.substring(protocolIdx); 44 | } 45 | 46 | var atCount = strCount(url, this.AT); 47 | var colonCount = strCount(url, this.COLON); 48 | var atIsPresent = atCount > 0; 49 | var colonIsPresent = colonCount > 0; 50 | 51 | if (!atIsPresent && !colonIsPresent) { 52 | parsed.host = url; 53 | parsed.hostname = url; 54 | // parse is done, there are no port and auth 55 | return parsed; 56 | } 57 | 58 | if (colonCount === 1 && !atIsPresent) { // it can only be the port number 59 | extractPortAndHostnameFromHost(parsed, url); 60 | return parsed; 61 | } 62 | 63 | var parts = url.split(this.AT); 64 | var host = parts.pop(); 65 | extractPortAndHostnameFromHost(parsed, host); 66 | parsed.auth = parts.join(this.AT); 67 | return parsed; 68 | } 69 | }; 70 | 71 | 72 | function strCount(str, substr) { 73 | if (str === null || substr === null) { 74 | return 0; 75 | } 76 | str = String(str); 77 | substr = String(substr); 78 | 79 | var count = 0, 80 | pos = 0, 81 | length = substr.length; 82 | 83 | while (true) { 84 | pos = str.indexOf(substr, pos); 85 | if (pos === -1) { 86 | break; 87 | } 88 | count++; 89 | pos += length; 90 | } 91 | 92 | return count; 93 | } 94 | 95 | function extractPortAndHostnameFromHost(parsed, host) { 96 | var portIdx = host.indexOf(Url.COLON); 97 | parsed.host = host; 98 | 99 | if (portIdx === -1) { 100 | parsed.hostname = host; 101 | // no colon is present inside host 102 | return; 103 | } 104 | parsed.port = host.substring(portIdx + Url.COLON.length); 105 | parsed.hostname = host.substring(0, portIdx); 106 | } 107 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tolerant", 3 | "version": "1.2.0", 4 | "description": "Overly tolerant url parser specialized in parsing protocol, auth (even invalid ones), host and port url parts.", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "mocha" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git@github.com:FGRibreau/node-tolerant-url-parser.git" 15 | }, 16 | "keywords": [ 17 | "url", 18 | "parsing" 19 | ], 20 | "author": "Francois-Guillaume Ribreau (http://fgribreau.com/)", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/FGRibreau/node-tolerant-url-parser/issues" 24 | }, 25 | "devDependencies": { 26 | "chai": "^2.2.0", 27 | "mocha": "~1.20.1" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /scripts/changelog: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # gem install github_changelog_generator 3 | github_changelog_generator -u fgribreau -p node-tolerant-url-parser 4 | -------------------------------------------------------------------------------- /scripts/ci/start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | 3 | wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.21.0/install.sh | bash 4 | source ~/.nvm/nvm.sh 5 | 6 | nvm install 7 | nvm use 8 | 9 | npm install 10 | 11 | node -v 12 | npm -v 13 | 14 | npm install 15 | 16 | set -e 17 | 18 | # Any subsequent commands which fail will cause the shell script to exit immediately 19 | setopt extended_glob; 20 | 21 | npm test 22 | 23 | npm install check-build -g 24 | check-build 25 | -------------------------------------------------------------------------------- /test/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var tolerantUrl = require('../'); 3 | var t = require('chai').assert; 4 | 5 | describe('.parse', function () { 6 | 7 | it('should produce documentation #lazy', function () { 8 | var parsed = tolerantUrl.parse('protocol://user:auth@domain.com:port/path'); 9 | // JSON.stringify(parsed, null, 2); 10 | t.deepEqual(parsed, { 11 | 'protocol': 'protocol:', 12 | 'auth': 'user:auth', 13 | 'hostname': 'domain.com', 14 | 'host': 'domain.com:port', 15 | 'port': 'port', 16 | 'href': 'protocol://user:auth@domain.com:port/path', 17 | 'path': '/path' 18 | }); 19 | }); 20 | 21 | it('should be able to parse sometime weird urls', function (f) { 22 | [{ // just domain without protocol 23 | input: 'my.own.domain.name.com', 24 | output: { 25 | protocol: null, 26 | auth: null, 27 | hostname: 'my.own.domain.name.com', 28 | port: null, 29 | host: 'my.own.domain.name.com', 30 | path: null 31 | } 32 | }, 33 | 34 | { // just domain 35 | input: 'redis://pub-redis-12000.us-east-0-0.0.ec1.garantiadata.com', 36 | output: { 37 | protocol: 'redis:', 38 | auth: null, 39 | hostname: 'pub-redis-12000.us-east-0-0.0.ec1.garantiadata.com', 40 | port: null, 41 | host: 'pub-redis-12000.us-east-0-0.0.ec1.garantiadata.com', 42 | path: null 43 | } 44 | }, { // just domain with port 45 | input: 'redis://redsmin.ok.com:12000/aa/aaa', 46 | output: { 47 | protocol: 'redis:', 48 | auth: null, 49 | hostname: 'redsmin.ok.com', 50 | port: '12000', 51 | host: 'redsmin.ok.com:12000', 52 | path: '/aa/aaa' 53 | } 54 | }, { // full (easy) 55 | input: 'redis://user:password@plop.redsmin.com:12000', 56 | output: { 57 | protocol: 'redis:', 58 | auth: 'user:password', 59 | hostname: 'plop.redsmin.com', 60 | port: '12000', 61 | host: 'plop.redsmin.com:12000', 62 | path: null 63 | } 64 | }, { // weird auth + domain 65 | input: 'redis://z4fsoVXGIt:53c1NDkoi41fFmzdHJ/2ojyZtcTCPZgRo=@redsmin.com/aaa', 66 | output: { 67 | protocol: 'redis:', 68 | auth: 'z4fsoVXGIt:53c1NDkoi41fFmzdHJ/2ojyZtcTCPZgRo=', 69 | hostname: 'redsmin.com', 70 | port: null, 71 | host: 'redsmin.com', 72 | path: '/aaa' 73 | } 74 | }, { // weird auth + domain + port 75 | input: 'redis://z4fsoVXGIt53c1NDkoi41fFmzdHJ/2ojyZtcTCPZgRo=@redsmin.com:6379', 76 | output: { 77 | protocol: 'redis:', 78 | auth: 'z4fsoVXGIt53c1NDkoi41fFmzdHJ/2ojyZtcTCPZgRo=', 79 | hostname: 'redsmin.com', 80 | port: '6379', 81 | host: 'redsmin.com:6379', 82 | path: null 83 | } 84 | }, { // weird auth (multi @) + domain + port 85 | input: 'redis://user:z4fsoVXGIt5@3c1NDkoi41fFmzdHJ/2ojyZtcTCPZgRo=@redsmin.com:6379', 86 | output: { 87 | protocol: 'redis:', 88 | auth: 'user:z4fsoVXGIt5@3c1NDkoi41fFmzdHJ/2ojyZtcTCPZgRo=', 89 | hostname: 'redsmin.com', 90 | port: '6379', 91 | host: 'redsmin.com:6379', 92 | path: null 93 | } 94 | }, { // weird auth (multi ://) + domain + port 95 | input: 'redis://user:z4fsoVXGI://t5@3c1NDkoi41fFmzdHJ/2ojyZtcTCPZgRo=@redsmin.com:6379', 96 | output: { 97 | protocol: 'redis:', 98 | auth: 'user:z4fsoVXGI://t5@3c1NDkoi41fFmzdHJ/2ojyZtcTCPZgRo=', 99 | hostname: 'redsmin.com', 100 | port: '6379', 101 | host: 'redsmin.com:6379', 102 | path: null 103 | } 104 | }, { // really really weird auth + domain + port 105 | input: 'redis://user:F,-9fsR;K{E4cM{o-&xS%ma6NbPoPTT*M_YJ.Kdp,p8qT,NDg*Q9%wy6h-OGgEU]?sYg?Ef,|2shOkwgYkz.NPNDu]T4%:,>_76U}7U;\'TSv7K*+k!HZR?0TQ2+]X.9DMs,s[rSZi?c.\'&>M7h89SpElr[vtL.Gdfe;!L|>&!wZ\'CuPT\'6,F62_ox,?L+gae5aUO<<%A\'28\'4hS77TrGDPK#1lrBo}*F:*pcd0w_NY##>0K:2#soE[,nJn,9\'&>-({84AHRvApS49iWTDmCJ?h(+-B6VYrZz:Ij\'9J_}w9uP:24YHV@QgKKt/7vm](3t#5:v:7dP]6MQrC@SHw|@r{{7(!*Y_YJ.Kdp,p8qT,NDg*Q9%wy6h-OGgEU]?sYg?Ef,|2shOkwgYkz.NPNDu]T4%:,>_76U}7U;\'TSv7K*+k!HZR?0TQ2+]X.9DMs,s[rSZi?c.\'&>M7h89SpElr[vtL.Gdfe;!L|>&!wZ\'CuPT\'6,F62_ox,?L+gae5aUO<<%A\'28\'4hS77TrGDPK#1lrBo}*F:*pcd0w_NY##>0K:2#soE[,nJn,9\'&>-({84AHRvApS49iWTDmCJ?h(+-B6VYrZz:Ij\'9J_}w9uP:24YHV@QgKKt/7vm](3t#5:v:7dP]6MQrC@SHw|@r{{7(!*Y