1'use strict'; 2require('../common'); 3const assert = require('assert'); 4const url = require('url'); 5 6// Formatting tests to verify that it'll format slightly wonky content to a 7// valid URL. 8const formatTests = { 9 'http://example.com?': { 10 href: 'http://example.com/?', 11 protocol: 'http:', 12 slashes: true, 13 host: 'example.com', 14 hostname: 'example.com', 15 search: '?', 16 query: {}, 17 pathname: '/' 18 }, 19 'http://example.com?foo=bar#frag': { 20 href: 'http://example.com/?foo=bar#frag', 21 protocol: 'http:', 22 host: 'example.com', 23 hostname: 'example.com', 24 hash: '#frag', 25 search: '?foo=bar', 26 query: 'foo=bar', 27 pathname: '/' 28 }, 29 'http://example.com?foo=@bar#frag': { 30 href: 'http://example.com/?foo=@bar#frag', 31 protocol: 'http:', 32 host: 'example.com', 33 hostname: 'example.com', 34 hash: '#frag', 35 search: '?foo=@bar', 36 query: 'foo=@bar', 37 pathname: '/' 38 }, 39 'http://example.com?foo=/bar/#frag': { 40 href: 'http://example.com/?foo=/bar/#frag', 41 protocol: 'http:', 42 host: 'example.com', 43 hostname: 'example.com', 44 hash: '#frag', 45 search: '?foo=/bar/', 46 query: 'foo=/bar/', 47 pathname: '/' 48 }, 49 'http://example.com?foo=?bar/#frag': { 50 href: 'http://example.com/?foo=?bar/#frag', 51 protocol: 'http:', 52 host: 'example.com', 53 hostname: 'example.com', 54 hash: '#frag', 55 search: '?foo=?bar/', 56 query: 'foo=?bar/', 57 pathname: '/' 58 }, 59 'http://example.com#frag=?bar/#frag': { 60 href: 'http://example.com/#frag=?bar/#frag', 61 protocol: 'http:', 62 host: 'example.com', 63 hostname: 'example.com', 64 hash: '#frag=?bar/#frag', 65 pathname: '/' 66 }, 67 'http://google.com" onload="alert(42)/': { 68 href: 'http://google.com/%22%20onload=%22alert(42)/', 69 protocol: 'http:', 70 host: 'google.com', 71 pathname: '/%22%20onload=%22alert(42)/' 72 }, 73 'http://a.com/a/b/c?s#h': { 74 href: 'http://a.com/a/b/c?s#h', 75 protocol: 'http', 76 host: 'a.com', 77 pathname: 'a/b/c', 78 hash: 'h', 79 search: 's' 80 }, 81 'xmpp:isaacschlueter@jabber.org': { 82 href: 'xmpp:isaacschlueter@jabber.org', 83 protocol: 'xmpp:', 84 host: 'jabber.org', 85 auth: 'isaacschlueter', 86 hostname: 'jabber.org' 87 }, 88 'http://atpass:foo%40bar@127.0.0.1/': { 89 href: 'http://atpass:foo%40bar@127.0.0.1/', 90 auth: 'atpass:foo@bar', 91 hostname: '127.0.0.1', 92 protocol: 'http:', 93 pathname: '/' 94 }, 95 'http://atslash%2F%40:%2F%40@foo/': { 96 href: 'http://atslash%2F%40:%2F%40@foo/', 97 auth: 'atslash/@:/@', 98 hostname: 'foo', 99 protocol: 'http:', 100 pathname: '/' 101 }, 102 'svn+ssh://foo/bar': { 103 href: 'svn+ssh://foo/bar', 104 hostname: 'foo', 105 protocol: 'svn+ssh:', 106 pathname: '/bar', 107 slashes: true 108 }, 109 'dash-test://foo/bar': { 110 href: 'dash-test://foo/bar', 111 hostname: 'foo', 112 protocol: 'dash-test:', 113 pathname: '/bar', 114 slashes: true 115 }, 116 'dash-test:foo/bar': { 117 href: 'dash-test:foo/bar', 118 hostname: 'foo', 119 protocol: 'dash-test:', 120 pathname: '/bar' 121 }, 122 'dot.test://foo/bar': { 123 href: 'dot.test://foo/bar', 124 hostname: 'foo', 125 protocol: 'dot.test:', 126 pathname: '/bar', 127 slashes: true 128 }, 129 'dot.test:foo/bar': { 130 href: 'dot.test:foo/bar', 131 hostname: 'foo', 132 protocol: 'dot.test:', 133 pathname: '/bar' 134 }, 135 // IPv6 support 136 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature': { 137 href: 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature', 138 protocol: 'coap:', 139 auth: 'u:p', 140 hostname: '::1', 141 port: '61616', 142 pathname: '/.well-known/r', 143 search: 'n=Temperature' 144 }, 145 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton': { 146 href: 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton', 147 protocol: 'coap', 148 host: '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616', 149 pathname: '/s/stopButton' 150 }, 151 'http://[::]/': { 152 href: 'http://[::]/', 153 protocol: 'http:', 154 hostname: '[::]', 155 pathname: '/' 156 }, 157 158 // Encode context-specific delimiters in path and query, but do not touch 159 // other non-delimiter chars like `%`. 160 // <https://github.com/nodejs/node-v0.x-archive/issues/4082> 161 162 // `#`,`?` in path 163 '/path/to/%%23%3F+=&.txt?foo=theA1#bar': { 164 href: '/path/to/%%23%3F+=&.txt?foo=theA1#bar', 165 pathname: '/path/to/%#?+=&.txt', 166 query: { 167 foo: 'theA1' 168 }, 169 hash: '#bar' 170 }, 171 172 // `#`,`?` in path + `#` in query 173 '/path/to/%%23%3F+=&.txt?foo=the%231#bar': { 174 href: '/path/to/%%23%3F+=&.txt?foo=the%231#bar', 175 pathname: '/path/to/%#?+=&.txt', 176 query: { 177 foo: 'the#1' 178 }, 179 hash: '#bar' 180 }, 181 182 // `#` in path end + `#` in query 183 '/path/to/%%23?foo=the%231#bar': { 184 href: '/path/to/%%23?foo=the%231#bar', 185 pathname: '/path/to/%#', 186 query: { 187 foo: 'the#1' 188 }, 189 hash: '#bar' 190 }, 191 192 // `?` and `#` in path and search 193 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag': { 194 href: 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag', 195 protocol: 'http:', 196 hostname: 'ex.com', 197 hash: '#frag', 198 search: '?abc=the#1?&foo=bar', 199 pathname: '/foo?100%m#r', 200 }, 201 202 // `?` and `#` in search only 203 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag': { 204 href: 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag', 205 protocol: 'http:', 206 hostname: 'ex.com', 207 hash: '#frag', 208 search: '?abc=the#1?&foo=bar', 209 pathname: '/fooA100%mBr', 210 }, 211 212 // Multiple `#` in search 213 'http://example.com/?foo=bar%231%232%233&abc=%234%23%235#frag': { 214 href: 'http://example.com/?foo=bar%231%232%233&abc=%234%23%235#frag', 215 protocol: 'http:', 216 slashes: true, 217 host: 'example.com', 218 hostname: 'example.com', 219 hash: '#frag', 220 search: '?foo=bar#1#2#3&abc=#4##5', 221 query: {}, 222 pathname: '/' 223 }, 224 225 // More than 255 characters in hostname which exceeds the limit 226 [`http://${'a'.repeat(255)}.com/node`]: { 227 href: 'http:///node', 228 protocol: 'http:', 229 slashes: true, 230 host: '', 231 hostname: '', 232 pathname: '/node', 233 path: '/node' 234 }, 235 236 // Greater than or equal to 63 characters after `.` in hostname 237 [`http://www.${'z'.repeat(63)}example.com/node`]: { 238 href: `http://www.${'z'.repeat(63)}example.com/node`, 239 protocol: 'http:', 240 slashes: true, 241 host: `www.${'z'.repeat(63)}example.com`, 242 hostname: `www.${'z'.repeat(63)}example.com`, 243 pathname: '/node', 244 path: '/node' 245 }, 246 247 // https://github.com/nodejs/node/issues/3361 248 'file:///home/user': { 249 href: 'file:///home/user', 250 protocol: 'file', 251 pathname: '/home/user', 252 path: '/home/user' 253 }, 254 255 // surrogate in auth 256 'http://%F0%9F%98%80@www.example.com/': { 257 href: 'http://%F0%9F%98%80@www.example.com/', 258 protocol: 'http:', 259 auth: '\uD83D\uDE00', 260 hostname: 'www.example.com', 261 pathname: '/' 262 } 263}; 264for (const u in formatTests) { 265 const expect = formatTests[u].href; 266 delete formatTests[u].href; 267 const actual = url.format(u); 268 const actualObj = url.format(formatTests[u]); 269 assert.strictEqual(actual, expect, 270 `wonky format(${u}) == ${expect}\nactual:${actual}`); 271 assert.strictEqual(actualObj, expect, 272 `wonky format(${JSON.stringify(formatTests[u])}) == ${ 273 expect}\nactual: ${actualObj}`); 274} 275