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 152 // Encode context-specific delimiters in path and query, but do not touch 153 // other non-delimiter chars like `%`. 154 // <https://github.com/nodejs/node-v0.x-archive/issues/4082> 155 156 // `#`,`?` in path 157 '/path/to/%%23%3F+=&.txt?foo=theA1#bar': { 158 href: '/path/to/%%23%3F+=&.txt?foo=theA1#bar', 159 pathname: '/path/to/%#?+=&.txt', 160 query: { 161 foo: 'theA1' 162 }, 163 hash: '#bar' 164 }, 165 166 // `#`,`?` in path + `#` in query 167 '/path/to/%%23%3F+=&.txt?foo=the%231#bar': { 168 href: '/path/to/%%23%3F+=&.txt?foo=the%231#bar', 169 pathname: '/path/to/%#?+=&.txt', 170 query: { 171 foo: 'the#1' 172 }, 173 hash: '#bar' 174 }, 175 176 // `#` in path end + `#` in query 177 '/path/to/%%23?foo=the%231#bar': { 178 href: '/path/to/%%23?foo=the%231#bar', 179 pathname: '/path/to/%#', 180 query: { 181 foo: 'the#1' 182 }, 183 hash: '#bar' 184 }, 185 186 // `?` and `#` in path and search 187 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag': { 188 href: 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag', 189 protocol: 'http:', 190 hostname: 'ex.com', 191 hash: '#frag', 192 search: '?abc=the#1?&foo=bar', 193 pathname: '/foo?100%m#r', 194 }, 195 196 // `?` and `#` in search only 197 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag': { 198 href: 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag', 199 protocol: 'http:', 200 hostname: 'ex.com', 201 hash: '#frag', 202 search: '?abc=the#1?&foo=bar', 203 pathname: '/fooA100%mBr', 204 }, 205 206 // Multiple `#` in search 207 'http://example.com/?foo=bar%231%232%233&abc=%234%23%235#frag': { 208 href: 'http://example.com/?foo=bar%231%232%233&abc=%234%23%235#frag', 209 protocol: 'http:', 210 slashes: true, 211 host: 'example.com', 212 hostname: 'example.com', 213 hash: '#frag', 214 search: '?foo=bar#1#2#3&abc=#4##5', 215 query: {}, 216 pathname: '/' 217 }, 218 219 // More than 255 characters in hostname which exceeds the limit 220 [`http://${'a'.repeat(255)}.com/node`]: { 221 href: 'http:///node', 222 protocol: 'http:', 223 slashes: true, 224 host: '', 225 hostname: '', 226 pathname: '/node', 227 path: '/node' 228 }, 229 230 // Greater than or equal to 63 characters after `.` in hostname 231 [`http://www.${'z'.repeat(63)}example.com/node`]: { 232 href: `http://www.${'z'.repeat(63)}example.com/node`, 233 protocol: 'http:', 234 slashes: true, 235 host: `www.${'z'.repeat(63)}example.com`, 236 hostname: `www.${'z'.repeat(63)}example.com`, 237 pathname: '/node', 238 path: '/node' 239 }, 240 241 // https://github.com/nodejs/node/issues/3361 242 'file:///home/user': { 243 href: 'file:///home/user', 244 protocol: 'file', 245 pathname: '/home/user', 246 path: '/home/user' 247 }, 248 249 // surrogate in auth 250 'http://%F0%9F%98%80@www.example.com/': { 251 href: 'http://%F0%9F%98%80@www.example.com/', 252 protocol: 'http:', 253 auth: '\uD83D\uDE00', 254 hostname: 'www.example.com', 255 pathname: '/' 256 } 257}; 258for (const u in formatTests) { 259 const expect = formatTests[u].href; 260 delete formatTests[u].href; 261 const actual = url.format(u); 262 const actualObj = url.format(formatTests[u]); 263 assert.strictEqual(actual, expect, 264 `wonky format(${u}) == ${expect}\nactual:${actual}`); 265 assert.strictEqual(actualObj, expect, 266 `wonky format(${JSON.stringify(formatTests[u])}) == ${ 267 expect}\nactual: ${actualObj}`); 268} 269