Skip to content

Commit 7401a4b

Browse files
Julien Blondeauacogoluegnes
Julien Blondeau
authored andcommitted
Handle basic query parameters in connection URI
(cherry picked from commit 4ffb6ea)
1 parent 33c1092 commit 7401a4b

File tree

2 files changed

+136
-17
lines changed

2 files changed

+136
-17
lines changed

src/main/java/com/rabbitmq/client/ConnectionFactory.java

+64
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,11 @@ public void setUri(URI uri)
352352

353353
setVirtualHost(uriDecode(uri.getPath().substring(1)));
354354
}
355+
356+
String rawQuery = uri.getRawQuery();
357+
if (rawQuery != null && rawQuery.length() > 0) {
358+
setQuery(rawQuery);
359+
}
355360
}
356361

357362
/**
@@ -381,6 +386,65 @@ private static String uriDecode(String s) {
381386
}
382387
}
383388

389+
/**
390+
* Convenience method for setting some fields from query parameters
391+
* Will handle only a subset of the query parameters supported by the
392+
* official erlang client
393+
* https://www.rabbitmq.com/uri-query-parameters.html
394+
* @param rawQuery is the string containing the raw query parameters part from a URI
395+
*/
396+
private void setQuery(String rawQuery) {
397+
Map<String, String> parameters = new HashMap<>();
398+
399+
// parsing the query parameters
400+
try {
401+
for (String param : rawQuery.split("&")) {
402+
String[] pair = param.split("=");
403+
String key = URLDecoder.decode(pair[0], "US-ASCII");
404+
String value = null;
405+
if (pair.length > 1) {
406+
value = URLDecoder.decode(pair[1], "US-ASCII");
407+
}
408+
parameters.put(key, value);
409+
}
410+
} catch (IOException e) {
411+
throw new RuntimeException("Cannot parse the query parameters", e);
412+
}
413+
414+
// heartbeat
415+
String heartbeat = parameters.get("heartbeat");
416+
if (heartbeat != null) {
417+
try {
418+
int heartbeatInt = Integer.parseInt(heartbeat);
419+
setRequestedHeartbeat(heartbeatInt);
420+
} catch (NumberFormatException e) {
421+
throw new IllegalArgumentException("Requested heartbeat must an integer");
422+
}
423+
}
424+
425+
// connection_timeout
426+
String connectionTimeout = parameters.get("connection_timeout");
427+
if (connectionTimeout != null) {
428+
try {
429+
int connectionTimeoutInt = Integer.parseInt(connectionTimeout);
430+
setConnectionTimeout(connectionTimeoutInt);
431+
} catch (NumberFormatException e) {
432+
throw new IllegalArgumentException("TCP connection timeout must an integer");
433+
}
434+
}
435+
436+
// channel_max
437+
String channelMax = parameters.get("channel_max");
438+
if (channelMax != null) {
439+
try {
440+
int channelMaxInt = Integer.parseInt(channelMax);
441+
setRequestedChannelMax(channelMaxInt);
442+
} catch (NumberFormatException e) {
443+
throw new IllegalArgumentException("Requested channel max must an integer");
444+
}
445+
}
446+
}
447+
384448
/**
385449
* Retrieve the requested maximum channel number
386450
* @return the initially requested maximum channel number; zero for unlimited

src/test/java/com/rabbitmq/client/test/AmqpUriTest.java

+72-17
Original file line numberDiff line numberDiff line change
@@ -32,35 +32,63 @@ public class AmqpUriTest extends BrokerTestCase
3232
{
3333
/* From the spec (subset of the tests) */
3434
parseSuccess("amqp://user:pass@host:10000/vhost",
35-
"user", "pass", "host", 10000, "vhost");
35+
"user", "pass", "host", 10000, "vhost", false);
3636
parseSuccess("aMQps://user%61:%61pass@host:10000/v%2fhost",
37-
"usera", "apass", "host", 10000, "v/host");
38-
parseSuccess("amqp://host", "guest", "guest", "host", 5672, "/");
37+
"usera", "apass", "host", 10000, "v/host", true);
38+
parseSuccess("amqp://host", "guest", "guest", "host", 5672, "/", false);
3939
parseSuccess("amqp:///vhost",
40-
"guest", "guest", "localhost", 5672, "vhost");
41-
parseSuccess("amqp://host/", "guest", "guest", "host", 5672, "");
42-
parseSuccess("amqp://host/%2f", "guest", "guest", "host", 5672, "/");
43-
parseSuccess("amqp://[::1]", "guest", "guest", "[::1]", 5672, "/");
40+
"guest", "guest", "localhost", 5672, "vhost", false);
41+
parseSuccess("amqp://host/", "guest", "guest", "host", 5672, "", false);
42+
parseSuccess("amqp://host/%2f", "guest", "guest", "host", 5672, "/", false);
43+
parseSuccess("amqp://[::1]", "guest", "guest", "[::1]", 5672, "/", false);
4444

4545
/* Various other success cases */
46-
parseSuccess("amqp://host:100", "guest", "guest", "host", 100, "/");
47-
parseSuccess("amqp://[::1]:100", "guest", "guest", "[::1]", 100, "/");
46+
parseSuccess("amqp://host:100", "guest", "guest", "host", 100, "/", false);
47+
parseSuccess("amqp://[::1]:100", "guest", "guest", "[::1]", 100, "/", false);
4848

4949
parseSuccess("amqp://host/blah",
50-
"guest", "guest", "host", 5672, "blah");
50+
"guest", "guest", "host", 5672, "blah", false);
5151
parseSuccess("amqp://host:100/blah",
52-
"guest", "guest", "host", 100, "blah");
52+
"guest", "guest", "host", 100, "blah", false);
5353
parseSuccess("amqp://[::1]/blah",
54-
"guest", "guest", "[::1]", 5672, "blah");
54+
"guest", "guest", "[::1]", 5672, "blah", false);
5555
parseSuccess("amqp://[::1]:100/blah",
56-
"guest", "guest", "[::1]", 100, "blah");
56+
"guest", "guest", "[::1]", 100, "blah", false);
5757

5858
parseSuccess("amqp://user:pass@host",
59-
"user", "pass", "host", 5672, "/");
59+
"user", "pass", "host", 5672, "/", false);
6060
parseSuccess("amqp://user:pass@[::1]",
61-
"user", "pass", "[::1]", 5672, "/");
61+
"user", "pass", "[::1]", 5672, "/", false);
6262
parseSuccess("amqp://user:pass@[::1]:100",
63-
"user", "pass", "[::1]", 100, "/");
63+
"user", "pass", "[::1]", 100, "/", false);
64+
65+
/* using query parameters */
66+
parseSuccess("amqp://user:pass@host:10000/vhost?",
67+
"user", "pass", "host", 10000, "vhost", false);
68+
parseSuccess("amqp://user:pass@host:10000/vhost?&",
69+
"user", "pass", "host", 10000, "vhost", false);
70+
parseSuccess("amqp://user:pass@host:10000/vhost?unknown_parameter",
71+
"user", "pass", "host", 10000, "vhost", false);
72+
parseSuccess("amqp://user:pass@host:10000/vhost?unknown_parameter=value",
73+
"user", "pass", "host", 10000, "vhost", false);
74+
parseSuccess("amqp://user:pass@host:10000/vhost?unknown%2fparameter=value",
75+
"user", "pass", "host", 10000, "vhost", false);
76+
77+
parseSuccess("amqp://user:pass@host:10000/vhost?heartbeat=342",
78+
"user", "pass", "host", 10000, "vhost", false,
79+
342, null, null);
80+
parseSuccess("amqp://user:pass@host:10000/vhost?connection_timeout=442",
81+
"user", "pass", "host", 10000, "vhost", false,
82+
null, 442, null);
83+
parseSuccess("amqp://user:pass@host:10000/vhost?channel_max=542",
84+
"user", "pass", "host", 10000, "vhost", false,
85+
null, null, 542);
86+
parseSuccess("amqp://user:pass@host:10000/vhost?heartbeat=342&connection_timeout=442&channel_max=542",
87+
"user", "pass", "host", 10000, "vhost", false,
88+
342, 442, 542);
89+
parseSuccess("amqp://user:pass@host:10000/vhost?heartbeat=342&connection_timeout=442&channel_max=542&a=b",
90+
"user", "pass", "host", 10000, "vhost", false,
91+
342, 442, 542);
6492

6593
/* Various failure cases */
6694
parseFail("https://www.rabbitmq.com");
@@ -71,10 +99,26 @@ public class AmqpUriTest extends BrokerTestCase
7199
parseFail("amqp://foo%1");
72100
parseFail("amqp://foo%1x");
73101
parseFail("amqp://foo%xy");
102+
103+
parseFail("amqp://user:pass@host:10000/vhost?heartbeat=not_an_integer");
104+
parseFail("amqp://user:pass@host:10000/vhost?heartbeat=-1");
105+
parseFail("amqp://user:pass@host:10000/vhost?connection_timeout=not_an_integer");
106+
parseFail("amqp://user:pass@host:10000/vhost?connection_timeout=-1");
107+
parseFail("amqp://user:pass@host:10000/vhost?channel_max=not_an_integer");
108+
parseFail("amqp://user:pass@host:10000/vhost?channel_max=-1");
109+
parseFail("amqp://user:pass@host:10000/vhost?heartbeat=342?connection_timeout=442");
74110
}
75111

76112
private void parseSuccess(String uri, String user, String password,
77-
String host, int port, String vhost)
113+
String host, int port, String vhost, boolean secured)
114+
throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException
115+
{
116+
parseSuccess(uri, user, password, host, port, vhost, secured, null, null, null);
117+
}
118+
119+
private void parseSuccess(String uri, String user, String password,
120+
String host, int port, String vhost, boolean secured,
121+
Integer heartbeat, Integer connectionTimeout, Integer channelMax)
78122
throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException
79123
{
80124
ConnectionFactory cf = TestUtils.connectionFactory();
@@ -85,6 +129,17 @@ private void parseSuccess(String uri, String user, String password,
85129
assertEquals(host, cf.getHost());
86130
assertEquals(port, cf.getPort());
87131
assertEquals(vhost, cf.getVirtualHost());
132+
assertEquals(secured, cf.isSSL());
133+
134+
if(heartbeat != null) {
135+
assertEquals(heartbeat.intValue(), cf.getRequestedHeartbeat());
136+
}
137+
if(connectionTimeout != null) {
138+
assertEquals(connectionTimeout.intValue(), cf.getConnectionTimeout());
139+
}
140+
if(channelMax != null) {
141+
assertEquals(channelMax.intValue(), cf.getRequestedChannelMax());
142+
}
88143
}
89144

90145
private void parseFail(String uri) {

0 commit comments

Comments
 (0)