8000 Send the response headers HttpServerUtil is given by lorexoff · Pull Request #52363 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ public class HttpServerUtil {
public static void sendResponse(HttpExchange exchange, int statusCode, Map<String, List<String>> headers, byte[] bodyBytes) {

try {
long length = bodyBytes != null ? bodyBytes.length : 0;
exchange.sendResponseHeaders(statusCode, length);
long length = bodyBytes != null ? bodyBytes.length : -1;
// Before sendResponseHeaders, which transmits the header block: anything added to the
// response headers afterwards never reaches the client.
if (headers != null) {
Headers responseHeaders = exchange.getResponseHeaders();
for (var entry : headers.entrySet()) {
responseHeaders.put(entry.getKey(), entry.getValue());
}
}
exchange.sendResponseHeaders(statusCode, length);
Comment thread
ahus1 marked this conversation as resolved.
Resolved

if (bodyBytes != null) {
try (var os = exchange.getResponseBody()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright 2026 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.keycloak.testframework.util;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.List;
import java.util.Map;

import com.sun.net.httpserver.HttpServer;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

/**
* Checks with a real client that a response built by {@link HttpServerUtil} arrives as described.
* <p>
* The headers are the part worth pinning: they used to be added to the exchange after
* {@code sendResponseHeaders} had already transmitted the header block, so they never reached the
* client. Nothing failed, because the only caller did not assert on them — which is why this is a
* test and not a comment.
*/
public class HttpServerUtilTest {

private HttpServer server;
private String baseUrl;

@BeforeEach
public void startServer() throws IOException {
server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
server.start();
baseUrl = "http://127.0.0.1:" + server.getAddress().getPort();
}

@AfterEach
public void stopServer() {
server.stop(0);
}

@Test
public void sendsTheHeadersItWasGiven() throws Exception {
server.createContext("/headers", exchange -> HttpServerUtil.sendResponse(exchange, 200,
Map.of("X-Custom", List.of("value")), "{}"));

HttpResponse<String> response = get("/headers");

assertThat(response.statusCode(), is(200));
assertThat(response.headers().firstValue("X-Custom").orElse(null), is("value"));
assertThat(response.body(), is("{}"));
}

@Test
public void sendsAResponseWithNeitherHeadersNorBody() throws Exception {
server.createContext("/empty", exchange -> HttpServerUtil.sendResponse(exchange, 204, null));

HttpResponse<String> response = get("/empty");

assertThat(response.statusCode(), is(204));
assertThat(response.body(), is(""));
assertThat("no-body response must not use chunked encoding",
response.headers().firstValue("Transfer-encoding").isPresent(), is(false));
}

private HttpResponse<String> get(String path) throws Exception {
return HttpClient.newHttpClient().send(HttpRequest.newBuilder(URI.create(baseUrl + path)).build(),
HttpResponse.BodyHandlers.ofString());
}
}
Loading
0