Skip to content

Commit bb6c3cb

Browse files
authored
Merge pull request #672 from captainju/handle_query_parameters
Handle basic query parameters in connection URI
2 parents 8252793 + 4ffb6ea commit bb6c3cb

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
@@ -348,6 +348,11 @@ public void setUri(URI uri)
348348

349349
setVirtualHost(uriDecode(uri.getPath().substring(1)));
350350
}
351+
352+
String rawQuery = uri.getRawQuery();
353+
if (rawQuery != null && rawQuery.length() > 0) {
354+
setQuery(rawQuery);
355+
}
351356
}
352357

353358
/**
@@ -377,6 +382,65 @@ private static String uriDecode(String s) {
377382
}
378383
}
379384

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