1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/base/proxy_string_util.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "build/buildflag.h"
11 #include "net/base/proxy_chain.h"
12 #include "net/base/proxy_server.h"
13 #include "net/net_buildflags.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace net {
17 namespace {
18
19 // Test the creation of ProxyServer using ProxyUriToProxyServer, which parses
20 // inputs of the form [<scheme>"://"]<host>[":"<port>]. Verify that each part
21 // was labelled correctly, and the accessors all give the right data.
TEST(ProxySpecificationUtilTest,ProxyUriToProxyServer)22 TEST(ProxySpecificationUtilTest, ProxyUriToProxyServer) {
23 const struct {
24 const char* const input_uri;
25 const char* const expected_uri;
26 ProxyServer::Scheme expected_scheme;
27 const char* const expected_host;
28 int expected_port;
29 const char* const expected_pac_string;
30 } tests[] = {
31 // HTTP proxy URIs:
32 {"foopy:10", // No scheme.
33 "foopy:10", ProxyServer::SCHEME_HTTP, "foopy", 10, "PROXY foopy:10"},
34 {"http://foopy", // No port.
35 "foopy:80", ProxyServer::SCHEME_HTTP, "foopy", 80, "PROXY foopy:80"},
36 {"http://foopy:10", "foopy:10", ProxyServer::SCHEME_HTTP, "foopy", 10,
37 "PROXY foopy:10"},
38
39 // IPv6 HTTP proxy URIs:
40 {"[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:10", // No scheme.
41 "[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:10", ProxyServer::SCHEME_HTTP,
42 "fedc:ba98:7654:3210:fedc:ba98:7654:3210", 10,
43 "PROXY [fedc:ba98:7654:3210:fedc:ba98:7654:3210]:10"},
44 {"http://[3ffe:2a00:100:7031::1]", // No port.
45 "[3ffe:2a00:100:7031::1]:80", ProxyServer::SCHEME_HTTP,
46 "3ffe:2a00:100:7031::1", 80, "PROXY [3ffe:2a00:100:7031::1]:80"},
47
48 // SOCKS4 proxy URIs:
49 {"socks4://foopy", // No port.
50 "socks4://foopy:1080", ProxyServer::SCHEME_SOCKS4, "foopy", 1080,
51 "SOCKS foopy:1080"},
52 {"socks4://foopy:10", "socks4://foopy:10", ProxyServer::SCHEME_SOCKS4,
53 "foopy", 10, "SOCKS foopy:10"},
54
55 // SOCKS5 proxy URIs:
56 {"socks5://foopy", // No port.
57 "socks5://foopy:1080", ProxyServer::SCHEME_SOCKS5, "foopy", 1080,
58 "SOCKS5 foopy:1080"},
59 {"socks5://foopy:10", "socks5://foopy:10", ProxyServer::SCHEME_SOCKS5,
60 "foopy", 10, "SOCKS5 foopy:10"},
61
62 // SOCKS proxy URIs (should default to SOCKS5)
63 {"socks://foopy", // No port.
64 "socks5://foopy:1080", ProxyServer::SCHEME_SOCKS5, "foopy", 1080,
65 "SOCKS5 foopy:1080"},
66 {"socks://foopy:10", "socks5://foopy:10", ProxyServer::SCHEME_SOCKS5,
67 "foopy", 10, "SOCKS5 foopy:10"},
68
69 // HTTPS proxy URIs:
70 {"https://foopy", // No port
71 "https://foopy:443", ProxyServer::SCHEME_HTTPS, "foopy", 443,
72 "HTTPS foopy:443"},
73 {"https://foopy:10", // Non-standard port
74 "https://foopy:10", ProxyServer::SCHEME_HTTPS, "foopy", 10,
75 "HTTPS foopy:10"},
76 {"https://1.2.3.4:10", // IP Address
77 "https://1.2.3.4:10", ProxyServer::SCHEME_HTTPS, "1.2.3.4", 10,
78 "HTTPS 1.2.3.4:10"},
79
80 #if BUILDFLAG(ENABLE_QUIC_PROXY_SUPPORT)
81 // QUIC proxy URIs:
82 {"quic://foopy", // no port
83 "quic://foopy:443", ProxyServer::SCHEME_QUIC, "foopy", 443,
84 "QUIC foopy:443"},
85 {"quic://foopy:80", "quic://foopy:80", ProxyServer::SCHEME_QUIC, "foopy",
86 80, "QUIC foopy:80"},
87 #endif // BUILDFLAG(ENABLE_QUIC_PROXY_SUPPORT)
88
89 // Hostname canonicalization:
90 {"[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10", // No scheme.
91 "[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:10", ProxyServer::SCHEME_HTTP,
92 "fedc:ba98:7654:3210:fedc:ba98:7654:3210", 10,
93 "PROXY [fedc:ba98:7654:3210:fedc:ba98:7654:3210]:10"},
94 {"http://[::192.9.5.5]", "[::c009:505]:80", ProxyServer::SCHEME_HTTP,
95 "::c009:505", 80, "PROXY [::c009:505]:80"},
96 {"http://[::FFFF:129.144.52.38]:80", "[::ffff:8190:3426]:80",
97 ProxyServer::SCHEME_HTTP, "::ffff:8190:3426", 80,
98 "PROXY [::ffff:8190:3426]:80"},
99 {"http://f\u00fcpy:85", "xn--fpy-hoa:85", ProxyServer::SCHEME_HTTP,
100 "xn--fpy-hoa", 85, "PROXY xn--fpy-hoa:85"},
101 {"https://0xA.020.3.4:443", "https://10.16.3.4:443",
102 ProxyServer::SCHEME_HTTPS, "10.16.3.4", 443, "HTTPS 10.16.3.4:443"},
103 {"http://FoO.tEsT:80", "foo.test:80", ProxyServer::SCHEME_HTTP,
104 "foo.test", 80, "PROXY foo.test:80"},
105 };
106
107 for (const auto& test : tests) {
108 ProxyServer uri = ProxyUriToProxyServer(
109 test.input_uri, ProxyServer::SCHEME_HTTP, /*is_quic_allowed=*/true);
110 EXPECT_TRUE(uri.is_valid());
111 EXPECT_EQ(test.expected_uri, ProxyServerToProxyUri(uri));
112 EXPECT_EQ(test.expected_scheme, uri.scheme());
113 EXPECT_EQ(test.expected_host, uri.host_port_pair().host());
114 EXPECT_EQ(test.expected_port, uri.host_port_pair().port());
115 EXPECT_EQ(test.expected_pac_string, ProxyServerToPacResultElement(uri));
116 }
117 }
118
119 #if BUILDFLAG(ENABLE_QUIC_PROXY_SUPPORT)
120 // In a build where the quic proxy support build flag is enabled, if the
121 // boolean for allowing quic proxy support is false, it will be considered in an
122 // invalid scheme as QUIC should not be parsed.
TEST(ProxySpecificationUtilTest,ProxyUriToProxyServerBuildFlagEnabledQuicDisallowedIsInvalid)123 TEST(ProxySpecificationUtilTest,
124 ProxyUriToProxyServerBuildFlagEnabledQuicDisallowedIsInvalid) {
125 ProxyServer proxy_server = ProxyUriToProxyServer(
126 "quic://foopy:443", ProxyServer::SCHEME_HTTP, /*is_quic_allowed=*/false);
127 EXPECT_FALSE(proxy_server.is_valid());
128 EXPECT_EQ(ProxyServer::SCHEME_INVALID, proxy_server.scheme());
129 }
130 #else
131 // In a build where the quic proxy support build flag is disabled, if the
132 // boolean for allowing quic proxy support is true, it will be considered in an
133 // invalid scheme as QUIC is not allowed in this type of build.
TEST(ProxySpecificationUtilTest,ProxyUriToProxyServerBuildFlagDisabledQuicAllowedIsInvalid)134 TEST(ProxySpecificationUtilTest,
135 ProxyUriToProxyServerBuildFlagDisabledQuicAllowedIsInvalid) {
136 ProxyServer proxy_server = ProxyUriToProxyServer(
137 "quic://foopy:443", ProxyServer::SCHEME_HTTP, /*is_quic_allowed=*/true);
138 EXPECT_FALSE(proxy_server.is_valid());
139 EXPECT_EQ(ProxyServer::SCHEME_INVALID, proxy_server.scheme());
140 }
141 #endif // BUILDFLAG(ENABLE_QUIC_PROXY_SUPPORT)
142
143 // Test parsing of the special URI form "direct://".
TEST(ProxySpecificationUtilTest,DirectProxyUriToProxyChain)144 TEST(ProxySpecificationUtilTest, DirectProxyUriToProxyChain) {
145 const char* const uris[] = {
146 "direct://",
147 "DIRECT://",
148 "DiReCt://",
149 };
150
151 for (const char* uri : uris) {
152 ProxyChain valid_uri = ProxyUriToProxyChain(uri, ProxyServer::SCHEME_HTTP);
153 EXPECT_TRUE(valid_uri.IsValid());
154 EXPECT_TRUE(valid_uri.is_direct());
155 }
156
157 // Direct is not allowed a host/port.
158 ProxyChain invalid_uri =
159 ProxyUriToProxyChain("direct://xyz", ProxyServer::SCHEME_HTTP);
160 EXPECT_FALSE(invalid_uri.IsValid());
161 EXPECT_FALSE(invalid_uri.is_direct());
162 }
163
164 // A multi-proxy string containing URIs is not acceptable input for the
165 // ProxyUriToProxyChain function and should return an invalid `ProxyChain()`.
TEST(ProxySpecificationUtilTest,ProxyUriToProxyChainWithBracketsInvalid)166 TEST(ProxySpecificationUtilTest, ProxyUriToProxyChainWithBracketsInvalid) {
167 // Release builds should return an invalid proxy chain for multi-proxy chains.
168 const char* const invalid_multi_proxy_uris[] = {
169 "[]",
170 "[direct://]",
171 "[https://foopy]",
172 "[https://foopy https://hoopy]",
173 };
174
175 for (const char* uri : invalid_multi_proxy_uris) {
176 ProxyChain multi_proxy_uri =
177 ProxyUriToProxyChain(uri, ProxyServer::SCHEME_HTTP);
178 EXPECT_FALSE(multi_proxy_uri.IsValid());
179 EXPECT_FALSE(multi_proxy_uri.is_direct());
180 }
181 }
182
183 // Test parsing some invalid inputs.
TEST(ProxySpecificationUtilTest,InvalidProxyUriToProxyServer)184 TEST(ProxySpecificationUtilTest, InvalidProxyUriToProxyServer) {
185 const char* const tests[] = {
186 "",
187 " ",
188 "dddf:", // not a valid port
189 "dddd:d", // not a valid port
190 "http://", // not a valid host/port.
191 "direct://", // direct is not a valid proxy server.
192 "http:/", // ambiguous, but will fail because of bad port.
193 "http:", // ambiguous, but will fail because of bad port.
194 "foopy.111", // Interpreted as invalid IPv4 address.
195 "foo.test/" // Paths disallowed.
196 "foo.test:123/" // Paths disallowed.
197 "foo.test/foo" // Paths disallowed.
198 };
199
200 for (const char* test : tests) {
201 SCOPED_TRACE(test);
202 ProxyServer uri = ProxyUriToProxyServer(test, ProxyServer::SCHEME_HTTP);
203 EXPECT_FALSE(uri.is_valid());
204 EXPECT_FALSE(uri.is_http());
205 EXPECT_FALSE(uri.is_socks());
206 }
207 }
208
209 // Test that LWS (SP | HT) is disregarded from the ends.
TEST(ProxySpecificationUtilTest,WhitespaceProxyUriToProxyServer)210 TEST(ProxySpecificationUtilTest, WhitespaceProxyUriToProxyServer) {
211 const char* const tests[] = {
212 " foopy:80",
213 "foopy:80 \t",
214 " \tfoopy:80 ",
215 };
216
217 for (const char* test : tests) {
218 ProxyServer uri = ProxyUriToProxyServer(test, ProxyServer::SCHEME_HTTP);
219 EXPECT_EQ("foopy:80", ProxyServerToProxyUri(uri));
220 }
221 }
222
223 // Test parsing a ProxyServer from a PAC representation.
TEST(ProxySpecificationUtilTest,PacResultElementToProxyServer)224 TEST(ProxySpecificationUtilTest, PacResultElementToProxyServer) {
225 const struct {
226 const char* const input_pac;
227 const char* const expected_uri;
228 } tests[] = {
229 {
230 "PROXY foopy:10",
231 "foopy:10",
232 },
233 {
234 " PROXY foopy:10 ",
235 "foopy:10",
236 },
237 {
238 "pRoXy foopy:10",
239 "foopy:10",
240 },
241 {
242 "PROXY foopy", // No port.
243 "foopy:80",
244 },
245 {
246 "socks foopy",
247 "socks4://foopy:1080",
248 },
249 {
250 "socks4 foopy",
251 "socks4://foopy:1080",
252 },
253 {
254 "socks5 foopy",
255 "socks5://foopy:1080",
256 },
257 {
258 "socks5 foopy:11",
259 "socks5://foopy:11",
260 },
261 {
262 "https foopy",
263 "https://foopy:443",
264 },
265 {
266 "https foopy:10",
267 "https://foopy:10",
268 },
269 {"PROXY [FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10",
270 "[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:10"},
271 {"PROXY f\u00fcpy:85", "xn--fpy-hoa:85"},
272 };
273
274 for (const auto& test : tests) {
275 SCOPED_TRACE(test.input_pac);
276 ProxyServer server = PacResultElementToProxyServer(test.input_pac);
277 EXPECT_TRUE(server.is_valid());
278 EXPECT_EQ(test.expected_uri, ProxyServerToProxyUri(server));
279
280 ProxyChain chain = PacResultElementToProxyChain(test.input_pac);
281 EXPECT_TRUE(chain.IsValid());
282 if (!chain.is_direct()) {
283 EXPECT_EQ(test.expected_uri, ProxyServerToProxyUri(chain.First()));
284 }
285 }
286 }
287
288 // Test parsing a ProxyServer from an invalid PAC representation.
TEST(ProxySpecificationUtilTest,InvalidPacResultElementToProxyServer)289 TEST(ProxySpecificationUtilTest, InvalidPacResultElementToProxyServer) {
290 const char* const tests[] = {
291 "PROXY", // missing host/port.
292 "HTTPS", // missing host/port.
293 "SOCKS", // missing host/port.
294 "DIRECT foopy:10", // direct cannot have host/port.
295 "INVALIDSCHEME", // unrecognized scheme.
296 "INVALIDSCHEME foopy:10", // unrecognized scheme.
297 "HTTP foopy:10", // http scheme should be "PROXY"
298 };
299
300 for (const char* test : tests) {
301 SCOPED_TRACE(test);
302 ProxyServer server = PacResultElementToProxyServer(test);
303 EXPECT_FALSE(server.is_valid());
304
305 ProxyChain chain = PacResultElementToProxyChain(test);
306 EXPECT_FALSE(chain.IsValid());
307 }
308 }
309
310 #if BUILDFLAG(ENABLE_BRACKETED_PROXY_URIS)
311 // A multi-proxy chain that contains any mention of direct will be considered an
312 // invalid `ProxyChain()`.
TEST(ProxySpecificationUtilTest,MultiProxyUrisToProxyChainMultiProxyDirectIsInvalid)313 TEST(ProxySpecificationUtilTest,
314 MultiProxyUrisToProxyChainMultiProxyDirectIsInvalid) {
315 const char* const invalid_multi_proxy_uris[] = {
316 "[direct://xyz]", // direct with ports
317 "[direct:// direct://]", // Two directs in chain
318 "[direct:// https://foopy]", // direct first in chain
319 "[https://foopy direct://]", // direct later in chain
320 };
321
322 for (const char* uri : invalid_multi_proxy_uris) {
323 ProxyChain multi_proxy_uri =
324 MultiProxyUrisToProxyChain(uri, ProxyServer::SCHEME_HTTPS);
325 EXPECT_FALSE(multi_proxy_uri.IsValid());
326 EXPECT_FALSE(multi_proxy_uri.is_direct());
327 }
328 }
329
330 // A input containing a single uri of direct will be valid.
TEST(ProxySpecificationUtilTest,MultiProxyUrisToProxyChainSingleDirectIsValid)331 TEST(ProxySpecificationUtilTest,
332 MultiProxyUrisToProxyChainSingleDirectIsValid) {
333 const char* const valid_direct_uris[] = {
334 "direct://", // non-bracketed direct
335 "[direct://]", // bracketed direct
336 };
337
338 for (const char* uri : valid_direct_uris) {
339 ProxyChain multi_proxy_uri =
340 MultiProxyUrisToProxyChain(uri, ProxyServer::SCHEME_HTTPS);
341 EXPECT_TRUE(multi_proxy_uri.IsValid());
342 EXPECT_TRUE(multi_proxy_uri.is_direct());
343 }
344 }
345
TEST(ProxySpecificationUtilTest,MultiProxyUrisToProxyChainValid)346 TEST(ProxySpecificationUtilTest, MultiProxyUrisToProxyChainValid) {
347 const struct {
348 const char* const input_uri;
349 const std::vector<std::string> expected_uris;
350 ProxyServer::Scheme expected_scheme;
351 } tests[] = {
352 // 1 Proxy (w/ and w/o brackets):
353 {"[https://foopy:443]", {"https://foopy:443"}, ProxyServer::SCHEME_HTTPS},
354 {"https://foopy:443", {"https://foopy:443"}, ProxyServer::SCHEME_HTTPS},
355
356 // 2 Proxies:
357 {"[https://foopy:443 https://hoopy:443]",
358 {"https://foopy:443", "https://hoopy:443"},
359 ProxyServer::SCHEME_HTTPS},
360
361 // Extra padding in uris string ignored:
362 {" [https://foopy:443 https://hoopy:443] ",
363 {"https://foopy:443", "https://hoopy:443"},
364 ProxyServer::SCHEME_HTTPS},
365 {"[\thttps://foopy:443 https://hoopy:443\t ] ",
366 {"https://foopy:443", "https://hoopy:443"},
367 ProxyServer::SCHEME_HTTPS},
368 {" \t[ https://foopy:443 https://hoopy:443\t ]",
369 {"https://foopy:443", "https://hoopy:443"},
370 ProxyServer::SCHEME_HTTPS},
371 {"[https://foopy:443 https://hoopy:443]",
372 {"https://foopy:443", "https://hoopy:443"},
373 ProxyServer::SCHEME_HTTPS}, // Delimiter is two spaces.
374 {"[https://foopy \thttps://hoopy]",
375 {"https://foopy:443", "https://hoopy:443"},
376 ProxyServer::SCHEME_HTTPS}, // Delimiter is followed by tab.
377
378 // 3 Proxies:
379 {"[https://foopy:443 https://hoopy:443 https://loopy:443]",
380 {"https://foopy:443", "https://hoopy:443", "https://loopy:443"},
381 ProxyServer::SCHEME_HTTPS},
382 };
383
384 for (const auto& test : tests) {
385 ProxyChain proxy_chain =
386 MultiProxyUrisToProxyChain(test.input_uri, test.expected_scheme);
387
388 EXPECT_TRUE(proxy_chain.IsValid());
389 EXPECT_EQ(proxy_chain.length(), test.expected_uris.size());
390
391 std::vector<ProxyServer> proxies = proxy_chain.proxy_servers();
392 for (size_t i = 0; i < proxies.size(); i++) {
393 const ProxyServer& proxy = proxies[i];
394 EXPECT_TRUE(proxy.is_valid());
395 EXPECT_EQ(test.expected_uris[i], ProxyServerToProxyUri(proxy));
396 }
397 }
398 }
399
400 #if BUILDFLAG(ENABLE_QUIC_PROXY_SUPPORT)
401 // Quic proxy schemes are parsed properly
TEST(ProxySpecificationUtilTest,MultiProxyUrisToProxyChainValidQuic)402 TEST(ProxySpecificationUtilTest, MultiProxyUrisToProxyChainValidQuic) {
403 const struct {
404 const char* const input_uri;
405 const std::vector<std::string> expected_uris;
406 ProxyServer::Scheme default_scheme;
407 const std::vector<ProxyServer::Scheme> expected_schemes;
408 } tests[] = {
409 // single quic proxy scheme (unbracketed)
410 {"quic://foopy", // missing port number
411 {"quic://foopy:443"},
412 ProxyServer::SCHEME_HTTP,
413 {ProxyServer::SCHEME_QUIC}},
414 {"quic://foopy:80",
415 {"quic://foopy:80"},
416 ProxyServer::SCHEME_HTTP,
417 {ProxyServer::SCHEME_QUIC}},
418
419 // single quic proxy scheme (bracketed)
420 {"[quic://foopy:80]",
421 {"quic://foopy:80"},
422 ProxyServer::SCHEME_HTTP,
423 {ProxyServer::SCHEME_QUIC}},
424
425 // multi-proxy chain
426 // 2 quic schemes in a row
427 {"[quic://foopy:80 quic://loopy:80]",
428 {"quic://foopy:80", "quic://loopy:80"},
429 ProxyServer::SCHEME_HTTP,
430 {ProxyServer::SCHEME_QUIC, ProxyServer::SCHEME_QUIC}},
431 // Quic scheme followed by HTTPS in a row
432 {"[quic://foopy:80 https://loopy:80]",
433 {"quic://foopy:80", "https://loopy:80"},
434 ProxyServer::SCHEME_HTTP,
435 {ProxyServer::SCHEME_QUIC, ProxyServer::SCHEME_HTTPS}},
436 };
437
438 for (const auto& test : tests) {
439 ProxyChain proxy_chain = MultiProxyUrisToProxyChain(
440 test.input_uri, test.default_scheme, /*is_quic_allowed=*/true);
441
442 EXPECT_TRUE(proxy_chain.IsValid());
443 EXPECT_EQ(proxy_chain.length(), test.expected_uris.size());
444
445 std::vector<ProxyServer> proxies = proxy_chain.proxy_servers();
446 for (size_t i = 0; i < proxies.size(); i++) {
447 const ProxyServer& proxy = proxies[i];
448 EXPECT_TRUE(proxy.is_valid());
449 EXPECT_EQ(test.expected_uris[i], ProxyServerToProxyUri(proxy));
450 EXPECT_EQ(test.expected_schemes[i], proxy.scheme());
451 }
452 }
453 }
454
455 // If a multi-proxy chain contains a quic scheme proxy, it must only be followed
456 // by another quic or https proxy. This ensures this logic still applies.
TEST(ProxySpecificationUtilTest,MultiProxyUrisToProxyChainInvalidQuicCombo)457 TEST(ProxySpecificationUtilTest, MultiProxyUrisToProxyChainInvalidQuicCombo) {
458 ProxyChain proxy_chain = MultiProxyUrisToProxyChain(
459 "[https://loopy:80 quic://foopy:80]", ProxyServer::SCHEME_HTTP);
460
461 EXPECT_FALSE(proxy_chain.IsValid());
462 }
463
464 #endif // BUILDFLAG(ENABLE_QUIC_PROXY_SUPPORT)
465
466 // If the input URIs is invalid, an invalid `ProxyChain()` will be returned.
TEST(ProxySpecificationUtilTest,MultiProxyUrisToProxyChainInvalidFormatReturnsInvalidProxyChain)467 TEST(ProxySpecificationUtilTest,
468 MultiProxyUrisToProxyChainInvalidFormatReturnsInvalidProxyChain) {
469 const char* const invalid_multi_proxy_uris[] = {
470 "", // Empty string
471 " ", // String with only spaces
472 "[]", // No proxies within brackets
473 "https://foopy https://hoopy", // Missing brackets
474 "[https://foopy https://hoopy", // Missing bracket
475 "https://foopy https://hoopy]", // Missing bracket
476 "https://foopy \t https://hoopy" // Missing brackets and bad delimiter
477 };
478
479 for (const char* uri : invalid_multi_proxy_uris) {
480 ProxyChain multi_proxy_uri =
481 MultiProxyUrisToProxyChain(uri, ProxyServer::SCHEME_HTTPS);
482 EXPECT_FALSE(multi_proxy_uri.IsValid());
483 EXPECT_FALSE(multi_proxy_uri.is_direct());
484 }
485 }
486 #endif // BUILDFLAG(ENABLE_BRACKETED_PROXY_URIS)
487 } // namespace
488 } // namespace net
489