Skip to content

Commit 1e693a9

Browse files
committed
HttpServerRequest supports query parameters.
1 parent b1b8836 commit 1e693a9

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServerOperations.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.nio.file.Files;
2222
import java.nio.file.Path;
2323
import java.time.ZonedDateTime;
24+
import java.util.Collections;
2425
import java.util.HashSet;
2526
import java.util.List;
2627
import java.util.Locale;
@@ -59,6 +60,7 @@
5960
import io.netty.handler.codec.http.HttpUtil;
6061
import io.netty.handler.codec.http.HttpVersion;
6162
import io.netty.handler.codec.http.LastHttpContent;
63+
import io.netty.handler.codec.http.QueryStringDecoder;
6264
import io.netty.handler.codec.http.TooLongHttpHeaderException;
6365
import io.netty.handler.codec.http.TooLongHttpLineException;
6466
import io.netty.handler.codec.http.cookie.Cookie;
@@ -121,6 +123,7 @@ class HttpServerOperations extends HttpOperations<HttpServerRequest, HttpServerR
121123
final String scheme;
122124
final ZonedDateTime timestamp;
123125

126+
Map<String, List<String>> queryParamsMap;
124127
BiPredicate<HttpServerRequest, HttpServerResponse> compressionPredicate;
125128
Function<? super String, Map<String, String>> paramsResolver;
126129
String path;
@@ -459,6 +462,19 @@ public HttpHeaders requestHeaders() {
459462
throw new IllegalStateException("request not parsed");
460463
}
461464

465+
@Override
466+
public Map<String, List<String>> queryParams() {
467+
if (queryParamsMap == null) {
468+
queryParamsMap = Collections.unmodifiableMap(parseQueryParams(this.nettyRequest));
469+
}
470+
return queryParamsMap;
471+
}
472+
473+
private Map<String, List<String>> parseQueryParams(HttpRequest request) {
474+
QueryStringDecoder decoder = new QueryStringDecoder(request.uri());
475+
return decoder.parameters();
476+
}
477+
462478
@Override
463479
public String scheme() {
464480
if (connectionInfo != null) {

reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServerRequest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.net.InetSocketAddress;
1919
import java.time.ZonedDateTime;
20+
import java.util.List;
2021
import java.util.Map;
2122
import java.util.function.Consumer;
2223
import java.util.function.Function;
@@ -143,6 +144,13 @@ default Flux<HttpContent> receiveContent() {
143144
*/
144145
HttpHeaders requestHeaders();
145146

147+
/**
148+
* return parsed and decoded query parameter name value pairs
149+
*
150+
* @return query parameters {@link Map&lt;String,List&lt;String&gt;&gt;}
151+
*/
152+
Map<String, List<String>> queryParams();
153+
146154
/**
147155
* Returns the inbound protocol and version.
148156
*

reactor-netty-http/src/test/java/reactor/netty/http/server/HttpServerTests.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2689,6 +2689,58 @@ void testUseComparatorOrderRoutes() {
26892689
.verifyComplete();
26902690
}
26912691

2692+
@Test
2693+
void testRouteQuery() {
2694+
HttpServerRoutes serverRoutes = HttpServerRoutes.newRoutes()
2695+
.get("/yes/value",
2696+
(request, response) -> {
2697+
StringBuilder sbuf = new StringBuilder();
2698+
request.queryParams().forEach((key, list) -> {
2699+
2700+
for(String value : list) {
2701+
sbuf.append(key);
2702+
sbuf.append('=');
2703+
sbuf.append(value);
2704+
sbuf.append('&');
2705+
}
2706+
sbuf.deleteCharAt(sbuf.length()-1);
2707+
});
2708+
return response.sendString(Mono.just("/yes/value?" + sbuf));
2709+
}).route(r -> true, (req, resp) -> {
2710+
return resp.sendString(Mono.just("/default"));
2711+
});
2712+
2713+
try {
2714+
disposableServer = HttpServer
2715+
.create()
2716+
.handle(serverRoutes)
2717+
.bindNow();
2718+
2719+
// verify HttpServerRequest has query parameters as the incoming request has query parameters
2720+
StepVerifier
2721+
.create(createClient(disposableServer.port())
2722+
.get()
2723+
.uri("/yes/value?id=a&id=b")
2724+
.responseSingle((response, mono) -> mono.asString()))
2725+
.expectNext("/yes/value?id=a&id=b")
2726+
.verifyComplete();
2727+
2728+
// verify HttpServerRequest does not have query parameters if the http request does not have query
2729+
// parameters
2730+
StepVerifier
2731+
.create(createClient(disposableServer.port())
2732+
.get()
2733+
.uri("/yes/value")
2734+
.responseSingle((response, mono) -> mono.asString()))
2735+
.expectNext("/yes/value?")
2736+
.verifyComplete();
2737+
} finally {
2738+
if (disposableServer != null) {
2739+
disposableServer.disposeNow();
2740+
}
2741+
}
2742+
}
2743+
26922744
@Test
26932745
void testOverrideRouteOrder() {
26942746
HttpServerRoutes serverRoutes = HttpServerRoutes.newRoutes()

0 commit comments

Comments
 (0)