diff --git a/src/main/java/io/cryostat/agent/remote/RecordingsContext.java b/src/main/java/io/cryostat/agent/remote/RecordingsContext.java index a59f2060..fbd7b0ca 100644 --- a/src/main/java/io/cryostat/agent/remote/RecordingsContext.java +++ b/src/main/java/io/cryostat/agent/remote/RecordingsContext.java @@ -15,6 +15,7 @@ */ package io.cryostat.agent.remote; +import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -60,9 +61,9 @@ class RecordingsContext implements RemoteContext { - private static final String PATH = "/recordings"; + private static final String PATH = "/recordings/"; private static final Pattern PATH_ID_PATTERN = - Pattern.compile("^" + PATH + "/(\\d+)$", Pattern.MULTILINE); + Pattern.compile("^" + PATH + "(\\d+)$", Pattern.MULTILINE); private final Logger log = LoggerFactory.getLogger(getClass()); private final SmallRyeConfig config; @@ -94,15 +95,14 @@ public void handle(HttpExchange exchange) throws IOException { if (!ensureMethodAccepted(exchange)) { return; } - int id = Integer.MIN_VALUE; + long id = Long.MIN_VALUE; switch (mtd) { case "GET": id = extractId(exchange); - if (id == Integer.MIN_VALUE) { + if (id == Long.MIN_VALUE) { handleGetList(exchange); } else { - exchange.sendResponseHeaders( - HttpStatus.SC_NOT_IMPLEMENTED, BODY_LENGTH_NONE); + handleGetRecording(exchange, id); } break; case "POST": @@ -135,12 +135,12 @@ public void handle(HttpExchange exchange) throws IOException { } } - private static int extractId(HttpExchange exchange) throws IOException { + private static long extractId(HttpExchange exchange) throws IOException { Matcher m = PATH_ID_PATTERN.matcher(exchange.getRequestURI().getPath()); if (!m.find()) { - return Integer.MIN_VALUE; + return Long.MIN_VALUE; } - return Integer.parseInt(m.group(1)); + return Long.parseLong(m.group(1)); } private void handleGetList(HttpExchange exchange) { @@ -153,6 +153,46 @@ private void handleGetList(HttpExchange exchange) { } } + private void handleGetRecording(HttpExchange exchange, long id) { + FlightRecorder.getFlightRecorder().getRecordings().stream() + .filter(r -> r.getId() == id) + .findFirst() + .ifPresentOrElse( + r -> { + Recording copy = r.copy(true); + try (InputStream stream = copy.getStream(null, null); + BufferedInputStream bis = new BufferedInputStream(stream); + OutputStream response = exchange.getResponseBody()) { + if (stream == null) { + exchange.sendResponseHeaders( + HttpStatus.SC_NO_CONTENT, BODY_LENGTH_NONE); + } else { + exchange.sendResponseHeaders( + HttpStatus.SC_OK, BODY_LENGTH_UNKNOWN); + bis.transferTo(response); + } + } catch (IOException ioe) { + log.error("I/O error", ioe); + try { + exchange.sendResponseHeaders( + HttpStatus.SC_INTERNAL_SERVER_ERROR, BODY_LENGTH_NONE); + } catch (IOException ioe2) { + log.error("Failed to write response", ioe2); + } + } finally { + copy.close(); + } + }, + () -> { + try { + exchange.sendResponseHeaders( + HttpStatus.SC_NOT_FOUND, BODY_LENGTH_NONE); + } catch (IOException e) { + log.error("Failed to write response", e); + } + }); + } + private void handleStart(HttpExchange exchange) throws IOException { try (InputStream body = exchange.getRequestBody()) { StartRecordingRequest req = mapper.readValue(body, StartRecordingRequest.class); @@ -177,7 +217,7 @@ private void handleStart(HttpExchange exchange) throws IOException { } } - private void handleStop(HttpExchange exchange, int id) throws IOException { + private void handleStop(HttpExchange exchange, long id) throws IOException { invokeOnRecording( exchange, id, @@ -195,7 +235,7 @@ private void handleStop(HttpExchange exchange, int id) throws IOException { }); } - private void handleDelete(HttpExchange exchange, int id) throws IOException { + private void handleDelete(HttpExchange exchange, long id) throws IOException { invokeOnRecording( exchange, id,