<div dir="ltr">My first thought is that if you are computing the string maybe you'd want to look at the request. Or set a header for content type.<br><br>I'm not going to push hard until valhalla is at least in preview (+ we've already talked it to death) but a <font face="monospace">Body</font><font face="arial, sans-serif"> abstraction would probably solve your use-case more robustly than yet another method there.</font><br><br><font face="monospace">exchange -> exchange.sendResponse(200, Body.of("example"));</font><br style="font-family:monospace"></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Mon, Apr 28, 2025 at 5:28 AM Pavel Rappo <<a href="mailto:pavel.rappo@gmail.com">pavel.rappo@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I'm using HttpServer to implement an HTTP probe [^1] that provides<br>
application state at the time of probing. I find that convenience<br>
handlers provided by HttpHandlers are insufficient for my use case. I<br>
also find that implementing a custom HttpHandler is tricky without the<br>
help of documentation.<br>
<br>
Perhaps my use case is typical enough so that HttpHandlers could<br>
provide a new convenience handler. That handler would send a<br>
dynamically supplied string, rather than a static string. If you also<br>
find it useful, I'd appreciate it if we could discuss it. Before I<br>
create a JBS issue, please have a look at this crude patch to see if<br>
it makes sense to you in principle. Thanks.<br>
<br>
[^1]: <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/" rel="noreferrer" target="_blank">https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/</a><br>
<br>
diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpHandlers.java<br>
b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpHandlers.java<br>
index 03642033914..987de0ede5d 100644<br>
--- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpHandlers.java<br>
+++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpHandlers.java<br>
@@ -25,9 +25,11 @@<br>
<br>
 package com.sun.net.httpserver;<br>
<br>
+import java.io.OutputStream;<br>
 import java.nio.charset.StandardCharsets;<br>
 import java.util.Objects;<br>
 import java.util.function.Predicate;<br>
+import java.util.function.Supplier;<br>
<br>
 /**<br>
  * Implementations of {@link com.sun.net.httpserver.HttpHandler HttpHandler}<br>
@@ -140,28 +142,60 @@ public static HttpHandler<br>
handleOrElse(Predicate<Request> handlerTest,<br>
      * @throws NullPointerException     if headers or body are null<br>
      */<br>
     public static HttpHandler of(int statusCode, Headers headers,<br>
String body) {<br>
+        Objects.requireNonNull(body);<br>
+        return of(statusCode, headers, () -> body);<br>
+    }<br>
+<br>
+    /**<br>
+     * Returns an {@code HttpHandler} that sends a response<br>
comprising the given<br>
+     * {@code statusCode}, {@code headers}, and {@code body}.<br>
+     *<br>
+     * <p> This method creates a handler that reads and discards the request<br>
+     * body before it sets the response state and sends the response.<br>
+     *<br>
+     * <p> {@code headers} are the effective headers of the response. The<br>
+     * response <i>body bytes</i> are a {@code UTF-8} encoded byte sequence of<br>
+     * a string, which is supplied by {@code bodySupplier}<br>
immediately after the request body is read. The response headers<br>
+     * {@linkplain HttpExchange#sendResponseHeaders(int, long) are sent} with<br>
+     * the given {@code statusCode} and the body bytes' length (or {@code -1}<br>
+     * if the body is empty). The body bytes are then sent as response body,<br>
+     * unless the body is empty, in which case no response body is sent.<br>
+     *<br>
+     * @param statusCode a response status code<br>
+     * @param headers a headers<br>
+     * @param bodySupplier a supplier for the response body string<br>
+     * @return a handler<br>
+     * @throws IllegalArgumentException if statusCode is not a positive 3-digit<br>
+     *                                  integer, as per rfc2616, section 6.1.1<br>
+     * @throws NullPointerException     if headers or body are null<br>
+     */<br>
+    public static HttpHandler of(int statusCode, Headers headers,<br>
Supplier<String> bodySupplier) {<br>
         if (statusCode < 100 || statusCode > 999)<br>
             throw new IllegalArgumentException("statusCode must be 3-digit: "<br>
                     + statusCode);<br>
         Objects.requireNonNull(headers);<br>
-        Objects.requireNonNull(body);<br>
+        Objects.requireNonNull(bodySupplier);<br>
<br>
         final var headersCopy = Headers.of(headers);<br>
-        final var bytes = body.getBytes(StandardCharsets.UTF_8);<br>
<br>
         return exchange -> {<br>
             try (exchange) {<br>
-                exchange.getRequestBody().readAllBytes();<br>
+<br>
exchange.getRequestBody().transferTo(OutputStream.nullOutputStream());<br>
// discard<br>
                 exchange.getResponseHeaders().putAll(headersCopy);<br>
-                if (exchange.getRequestMethod().equals("HEAD")) {<br>
-<br>
exchange.getResponseHeaders().set("Content-Length",<br>
Integer.toString(bytes.length));<br>
-                    exchange.sendResponseHeaders(statusCode, -1);<br>
-                }<br>
-                else if (bytes.length == 0) {<br>
-                    exchange.sendResponseHeaders(statusCode, -1);<br>
+                var body = bodySupplier.get();<br>
+                if (body == null) {<br>
+                    exchange.sendResponseHeaders(500, -1); //<br>
Internal Server Error<br>
                 } else {<br>
-                    exchange.sendResponseHeaders(statusCode, bytes.length);<br>
-                    exchange.getResponseBody().write(bytes);<br>
+                    final var bytes = body.getBytes(StandardCharsets.UTF_8);<br>
+                    if (exchange.getRequestMethod().equals("HEAD")) {<br>
+<br>
exchange.getResponseHeaders().set("Content-Length",<br>
Integer.toString(bytes.length));<br>
+                        exchange.sendResponseHeaders(statusCode, -1);<br>
+                    } else if (bytes.length == 0) {<br>
+                        exchange.sendResponseHeaders(statusCode, -1);<br>
+                    } else {<br>
+                        exchange.sendResponseHeaders(statusCode, bytes.length);<br>
+                        exchange.getResponseBody().write(bytes);<br>
+                    }<br>
                 }<br>
             }<br>
         };<br>
diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/HttpHandlersTest.java<br>
b/test/jdk/com/sun/net/httpserver/simpleserver/HttpHandlersTest.java<br>
index 85d271e44fa..d64fa03740f 100644<br>
--- a/test/jdk/com/sun/net/httpserver/simpleserver/HttpHandlersTest.java<br>
+++ b/test/jdk/com/sun/net/httpserver/simpleserver/HttpHandlersTest.java<br>
@@ -81,7 +81,7 @@ public void testNull() {<br>
         final var headers = new Headers();<br>
         final var body = "";<br>
         assertThrows(NPE, () -> HttpHandlers.of(200, null, body));<br>
-        assertThrows(NPE, () -> HttpHandlers.of(200, headers, null));<br>
+        assertThrows(NPE, () -> HttpHandlers.of(200, headers, (String) null));<br>
     }<br>
<br>
     @Test<br>
</blockquote></div>