22
33import com .retailsvc .http .internal .DefaultResponseBuilder ;
44import com .sun .net .httpserver .HttpExchange ;
5+ import java .net .URLDecoder ;
6+ import java .nio .charset .StandardCharsets ;
7+ import java .util .LinkedHashMap ;
58import java .util .Map ;
69
710/**
@@ -16,6 +19,7 @@ public final class Request {
1619 private final String operationId ;
1720 private final Map <String , String > pathParameters ;
1821 private final Map <String , TypeMapper > bodyMappers ;
22+ private Map <String , String > queryParamCache ;
1923 private boolean responseSent ;
2024
2125 public Request (
@@ -53,6 +57,49 @@ public String header(String name) {
5357 return exchange .getRequestHeaders ().getFirst (name );
5458 }
5559
60+ /**
61+ * Raw (percent-encoded) query string from the request URI, or {@code null} if the URI has no
62+ * query component.
63+ */
64+ public String rawQuery () {
65+ return exchange .getRequestURI ().getRawQuery ();
66+ }
67+
68+ /**
69+ * Decoded query parameters keyed by name. Empty if the URI has no query. For repeated keys, the
70+ * first occurrence wins. Values are URL-decoded with UTF-8.
71+ */
72+ public Map <String , String > queryParams () {
73+ if (queryParamCache == null ) {
74+ queryParamCache = parseQuery (rawQuery ());
75+ }
76+ return queryParamCache ;
77+ }
78+
79+ /** First decoded value for {@code name}, or {@code null} if absent. */
80+ public String queryParam (String name ) {
81+ return queryParams ().get (name );
82+ }
83+
84+ private static Map <String , String > parseQuery (String query ) {
85+ if (query == null || query .isBlank ()) {
86+ return Map .of ();
87+ }
88+ Map <String , String > out = new LinkedHashMap <>();
89+ for (String pair : query .split ("&" )) {
90+ if (pair .isEmpty ()) {
91+ continue ;
92+ }
93+ int eq = pair .indexOf ('=' );
94+ String rawKey = eq < 0 ? pair : pair .substring (0 , eq );
95+ String rawValue = eq < 0 ? "" : pair .substring (eq + 1 );
96+ out .putIfAbsent (
97+ URLDecoder .decode (rawKey , StandardCharsets .UTF_8 ),
98+ URLDecoder .decode (rawValue , StandardCharsets .UTF_8 ));
99+ }
100+ return out ;
101+ }
102+
56103 public ResponseBuilder respond (int status ) {
57104 if (responseSent ) {
58105 throw new IllegalStateException ("Response already sent" );
0 commit comments