fix: consume device request bodies before queue mutations
Claim and cancel could complete before reading valid JSON, causing Jetty to close the persistent connection before a subsequent status event. Consume the bounded body after authentication. A split-body HTTP regression fails before this change; full isolated UI-profile verification passes 66 tests and Checkstyle. Co-authored-by: Codex (GPT-6) <noreply@openai.com> Signed-off-by: James Maes <james@kof22.com>
This commit is contained in:
4 files changed
+57
-2
No files matched your search
@@ -21,10 +21,13 @@
|
||||
package com.kingsrook.qbits.printing;
|
||||
|
||||
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.MessageDigest;
|
||||
@@ -36,6 +39,7 @@ import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
@@ -122,6 +126,41 @@ class PrintingContractTest
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** Claim waits for its bounded JSON body before committing the response.
|
||||
***************************************************************************/
|
||||
@Test
|
||||
void claimConsumesSplitRequestBodyBeforeResponding() throws Exception
|
||||
{
|
||||
PrintingService service = new PrintingService(new DriverDataSource("jdbc:h2:mem:split-body-" + UUID.randomUUID() + ";DB_CLOSE_DELAY=-1", "sa", ""), "contract-tenant");
|
||||
service.initialize();
|
||||
String code = service.createEnrollment("default", "Synthetic device").getString("enrollmentCode");
|
||||
String token = service.enroll(fixture("enroll.request.json").put("enrollmentCode", code)).getString("deviceToken");
|
||||
PrintingRoutes routes = new PrintingRoutes(service, context -> false);
|
||||
Javalin app = Javalin.create(routes::acceptJavalinConfig).start("127.0.0.1", 0);
|
||||
try(Socket socket = new Socket("127.0.0.1", app.port()))
|
||||
{
|
||||
socket.setSoTimeout(250);
|
||||
String headers = "POST " + PrintingRoutes.BASE + "/device/jobs/claim HTTP/1.1\r\nHost: 127.0.0.1:" + app.port()
|
||||
+ "\r\nAuthorization: Bearer " + token + "\r\nContent-Type: application/json\r\nContent-Length: 2\r\nConnection: close\r\n\r\n{";
|
||||
socket.getOutputStream().write(headers.getBytes(StandardCharsets.US_ASCII));
|
||||
socket.getOutputStream().flush();
|
||||
assertThrows(SocketTimeoutException.class, () -> socket.getInputStream().read());
|
||||
socket.setSoTimeout(5000);
|
||||
socket.getOutputStream().write('}');
|
||||
socket.getOutputStream().flush();
|
||||
String response = new String(socket.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
|
||||
assertTrue(response.startsWith("HTTP/1.1 200"));
|
||||
assertTrue(response.contains("\"job\":null"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
app.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** Load the same fixture consumed by the Windows protocol tests.
|
||||
***************************************************************************/
|
||||
|
||||
Reference in new issue
Block a user