mirror of
https://github.com/AsamK/signal-cli
synced 2025-09-02 12:30:39 +00:00
Switch http server to use command handler
This commit is contained in:
parent
11179c672f
commit
7111cad402
2 changed files with 35 additions and 44 deletions
|
@ -4,20 +4,19 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.sun.net.httpserver.HttpExchange;
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
import com.sun.net.httpserver.HttpServer;
|
import com.sun.net.httpserver.HttpServer;
|
||||||
|
|
||||||
|
import org.asamk.signal.commands.Commands;
|
||||||
|
import org.asamk.signal.jsonrpc.JsonRpcReader;
|
||||||
import org.asamk.signal.jsonrpc.JsonRpcResponse;
|
import org.asamk.signal.jsonrpc.JsonRpcResponse;
|
||||||
import org.asamk.signal.jsonrpc.SignalJsonRpcDispatcherHandler;
|
import org.asamk.signal.jsonrpc.JsonRpcSender;
|
||||||
|
import org.asamk.signal.jsonrpc.SignalJsonRpcCommandHandler;
|
||||||
import org.asamk.signal.manager.Manager;
|
import org.asamk.signal.manager.Manager;
|
||||||
import org.asamk.signal.manager.MultiAccountManager;
|
import org.asamk.signal.manager.MultiAccountManager;
|
||||||
import org.asamk.signal.output.JsonWriter;
|
|
||||||
import org.asamk.signal.util.IOUtils;
|
|
||||||
import org.asamk.signal.util.Util;
|
import org.asamk.signal.util.Util;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
public class HttpServerHandler {
|
public class HttpServerHandler {
|
||||||
|
@ -53,53 +52,40 @@ public class HttpServerHandler {
|
||||||
final var server = HttpServer.create(new InetSocketAddress(port), 0);
|
final var server = HttpServer.create(new InetSocketAddress(port), 0);
|
||||||
server.setExecutor(Executors.newFixedThreadPool(10));
|
server.setExecutor(Executors.newFixedThreadPool(10));
|
||||||
|
|
||||||
server.createContext("/json-rpc", httpExchange -> {
|
server.createContext("/api/v1/rpc", httpExchange -> {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!"POST".equals(httpExchange.getRequestMethod())) {
|
if (!"POST".equals(httpExchange.getRequestMethod())) {
|
||||||
throw new HttpServerException(405, "Method not supported.");
|
throw new HttpServerException(405, "Method not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a custom writer which receives our response
|
final SignalJsonRpcCommandHandler commandHandler;
|
||||||
final var valueHolder = new Object[] { null };
|
|
||||||
final JsonWriter jsonWriter = (Object o) -> valueHolder[0] = o;
|
|
||||||
|
|
||||||
// This queue is used to deliver our request and then deliver a null
|
|
||||||
// value which terminates the reading process
|
|
||||||
final var stringRequest = IOUtils.readAll(httpExchange.getRequestBody(), StandardCharsets.UTF_8);
|
|
||||||
final var queue = new LinkedList<String>();
|
|
||||||
queue.addLast(stringRequest);
|
|
||||||
queue.addLast(null);
|
|
||||||
|
|
||||||
// Create dispatcher and handle connection
|
|
||||||
// Right now we are creating a new one for every request. This may not be
|
|
||||||
// totally efficient, but it handles possible issues that would arise with
|
|
||||||
// multithreading.
|
|
||||||
final var dispatcher = new SignalJsonRpcDispatcherHandler(
|
|
||||||
jsonWriter,
|
|
||||||
queue::removeFirst,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
dispatcher.handleConnection(c);
|
commandHandler = new SignalJsonRpcCommandHandler(c, Commands::getCommand);
|
||||||
} else {
|
} else {
|
||||||
dispatcher.handleConnection(m);
|
commandHandler = new SignalJsonRpcCommandHandler(m, Commands::getCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract and process the response
|
final Object[] result = {null};
|
||||||
final var response = valueHolder[0] != null ? valueHolder[0] : JsonRpcResponse.forSuccess(null, null);
|
final var jsonRpcSender = new JsonRpcSender(s -> {
|
||||||
|
if (result[0] != null) {
|
||||||
if (response instanceof JsonRpcResponse jsonRpcResponse) {
|
throw new AssertionError("There should only be a single JSON-RPC response");
|
||||||
if (jsonRpcResponse.getError() == null) {
|
|
||||||
sendResponse(200, jsonRpcResponse, httpExchange);
|
|
||||||
} else {
|
|
||||||
sendResponse(500, jsonRpcResponse, httpExchange);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result[0] = s;
|
||||||
|
});
|
||||||
|
|
||||||
|
final var jsonRpcReader = new JsonRpcReader(jsonRpcSender, httpExchange.getRequestBody());
|
||||||
|
jsonRpcReader.readMessages((method, params) -> commandHandler.handleRequest(objectMapper, method, params),
|
||||||
|
response -> logger.debug("Received unexpected response for id {}", response.getId()));
|
||||||
|
|
||||||
|
if (result[0] !=null) {
|
||||||
|
sendResponse(200, result[0], httpExchange);
|
||||||
} else {
|
} else {
|
||||||
logger.error("Invalid response object was received." + response);
|
sendResponse(201, null, httpExchange);
|
||||||
throw new HttpServerException(500, "An internal server error has occurred.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (HttpServerException aEx) {
|
catch (HttpServerException aEx) {
|
||||||
logger.error("Failed to process request.", aEx);
|
logger.error("Failed to process request.", aEx);
|
||||||
|
@ -109,7 +95,7 @@ public class HttpServerHandler {
|
||||||
}
|
}
|
||||||
catch (Throwable aEx) {
|
catch (Throwable aEx) {
|
||||||
logger.error("Failed to process request.", aEx);
|
logger.error("Failed to process request.", aEx);
|
||||||
sendResponse(500, JsonRpcResponse.forError(
|
sendResponse(200, JsonRpcResponse.forError(
|
||||||
new JsonRpcResponse.Error(JsonRpcResponse.Error.INTERNAL_ERROR,
|
new JsonRpcResponse.Error(JsonRpcResponse.Error.INTERNAL_ERROR,
|
||||||
"An internal server error has occurred.", null), null), httpExchange);
|
"An internal server error has occurred.", null), null), httpExchange);
|
||||||
}
|
}
|
||||||
|
@ -123,10 +109,15 @@ public class HttpServerHandler {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendResponse(int status, JsonRpcResponse response, HttpExchange httpExchange) throws IOException {
|
private void sendResponse(int status, Object response, HttpExchange httpExchange) throws IOException {
|
||||||
final var byteResponse = objectMapper.writeValueAsBytes(response);
|
if (response != null) {
|
||||||
httpExchange.sendResponseHeaders(status, byteResponse.length);
|
final var byteResponse = objectMapper.writeValueAsBytes(response);
|
||||||
httpExchange.getResponseBody().write(byteResponse);
|
httpExchange.sendResponseHeaders(status, byteResponse.length);
|
||||||
|
httpExchange.getResponseBody().write(byteResponse);
|
||||||
|
} else {
|
||||||
|
httpExchange.sendResponseHeaders(status, 0);
|
||||||
|
}
|
||||||
|
|
||||||
httpExchange.getResponseBody().close();
|
httpExchange.getResponseBody().close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class SignalJsonRpcCommandHandler {
|
||||||
this.commandProvider = commandProvider;
|
this.commandProvider = commandProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonNode handleRequest(
|
public JsonNode handleRequest(
|
||||||
final ObjectMapper objectMapper, final String method, ContainerNode<?> params
|
final ObjectMapper objectMapper, final String method, ContainerNode<?> params
|
||||||
) throws JsonRpcException {
|
) throws JsonRpcException {
|
||||||
var command = getCommand(method);
|
var command = getCommand(method);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue