From f5c293792ad697475d29073069c05063d7218c0b Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Thu, 31 Aug 2023 14:18:42 +0200 Subject: [PATCH] HTTP parameters support --- .../httpserver/ServletHttpExchange.java | 17 ++++- .../src/org/argeo/cms/http/HttpHeader.java | 1 + .../cms/http/server/HttpServerUtils.java | 75 +++++++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/org.argeo.cms.ee/src/org/argeo/cms/servlet/httpserver/ServletHttpExchange.java b/org.argeo.cms.ee/src/org/argeo/cms/servlet/httpserver/ServletHttpExchange.java index f5e9c0394..85553f01c 100644 --- a/org.argeo.cms.ee/src/org/argeo/cms/servlet/httpserver/ServletHttpExchange.java +++ b/org.argeo.cms.ee/src/org/argeo/cms/servlet/httpserver/ServletHttpExchange.java @@ -5,9 +5,14 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.URI; +import java.net.URLEncoder; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; +import java.util.Map; +import java.util.StringJoiner; import javax.net.ssl.SSLSession; import javax.servlet.http.HttpServletRequest; @@ -72,7 +77,17 @@ class ServletHttpExchange extends HttpsExchange { @Override public URI getRequestURI() { - return URI.create(httpServletRequest.getRequestURI()); + // TODO properly deal with charset? + Charset encoding = StandardCharsets.UTF_8; + Map parameters = httpServletRequest.getParameterMap(); + StringJoiner sb = new StringJoiner("&"); + for (String key : parameters.keySet()) { + for (String value : parameters.get(key)) { + String pair = URLEncoder.encode(key, encoding) + '=' + URLEncoder.encode(value, encoding); + sb.add(pair); + } + } + return URI.create(httpServletRequest.getRequestURI() + (sb.length() != 0 ? '?' + sb.toString() : "")); } @Override diff --git a/org.argeo.cms/src/org/argeo/cms/http/HttpHeader.java b/org.argeo.cms/src/org/argeo/cms/http/HttpHeader.java index ef7385d1d..91ca1f2af 100644 --- a/org.argeo.cms/src/org/argeo/cms/http/HttpHeader.java +++ b/org.argeo.cms/src/org/argeo/cms/http/HttpHeader.java @@ -6,6 +6,7 @@ public enum HttpHeader { WWW_AUTHENTICATE("WWW-Authenticate"), // ALLOW("Allow"), // VIA("Via"), // + CONTENT_TYPE("Content-Type"), // // WebDav DAV("DAV"), // diff --git a/org.argeo.cms/src/org/argeo/cms/http/server/HttpServerUtils.java b/org.argeo.cms/src/org/argeo/cms/http/server/HttpServerUtils.java index ab033f0ce..a170507e5 100644 --- a/org.argeo.cms/src/org/argeo/cms/http/server/HttpServerUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/http/server/HttpServerUtils.java @@ -1,8 +1,25 @@ package org.argeo.cms.http.server; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UncheckedIOException; import java.net.URI; +import java.net.URLDecoder; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Objects; +import org.argeo.api.acr.ContentRepository; +import org.argeo.api.acr.ContentSession; +import org.argeo.cms.auth.RemoteAuthUtils; +import org.argeo.cms.http.HttpMethod; +import org.argeo.cms.internal.http.RemoteAuthHttpExchange; + import com.sun.net.httpserver.HttpContext; import com.sun.net.httpserver.HttpExchange; @@ -39,6 +56,64 @@ public class HttpServerUtils { return extractPathWithingContext(httpContext, uri.getPath(), true); } + /** Returns content session consistent with this HTTP context. */ + public static ContentSession getContentSession(ContentRepository contentRepository, HttpExchange exchange) { + ContentSession session = RemoteAuthUtils.doAs(() -> contentRepository.get(), + new RemoteAuthHttpExchange(exchange)); + return session; + } + + /* + * QUERY PARAMETERS + */ + /** Returns the HTTP parameters form an {@link HttpExchange}. */ + public static Map> parseParameters(HttpExchange exchange) { + // TODO check encoding? + Charset encoding = StandardCharsets.UTF_8; + + Map> parameters = new HashMap<>(); + URI requestedUri = exchange.getRequestURI(); + String query = requestedUri.getRawQuery(); + parseQuery(query, parameters, encoding); + + // TODO do we really want to support POST? + if (HttpMethod.POST.name().equalsIgnoreCase(exchange.getRequestMethod())) { + String postQuery; + try { + // We do not close the stream on purpose, since the body still needs to be read + BufferedReader br = new BufferedReader(new InputStreamReader(exchange.getRequestBody(), encoding)); + postQuery = br.readLine(); + } catch (IOException e) { + throw new UncheckedIOException("Cannot read exchange body", e); + } + parseQuery(postQuery, parameters, encoding); + } + return parameters; + } + + private static void parseQuery(String query, Map> parameters, Charset encoding) { + if (query == null) + return; + String pairs[] = query.split("[&]"); + for (String pair : pairs) { + String param[] = pair.split("[=]"); + + String key = null; + String value = null; + if (param.length > 0) { + key = URLDecoder.decode(param[0], encoding); + } + + if (param.length > 1) { + value = URLDecoder.decode(param[1], encoding); + } + + if (!parameters.containsKey(key)) + parameters.put(key, new ArrayList<>()); + parameters.get(key).add(value); + } + } + /** singleton */ private HttpServerUtils() { -- 2.30.2