124 lines
5.0 KiB
Java
124 lines
5.0 KiB
Java
package eu.starsong.ghidra.util;
|
|
|
|
import com.google.gson.Gson;
|
|
import com.google.gson.JsonElement;
|
|
import com.google.gson.JsonObject;
|
|
import com.sun.net.httpserver.HttpExchange;
|
|
import eu.starsong.ghidra.api.ResponseBuilder; // Use the ResponseBuilder
|
|
import ghidra.util.Msg;
|
|
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
public class HttpUtil {
|
|
|
|
private static final Gson gson = new Gson();
|
|
|
|
/**
|
|
* Sends a JSON response with the given status code.
|
|
* Uses the ResponseBuilder internally.
|
|
*/
|
|
public static void sendJsonResponse(HttpExchange exchange, JsonObject jsonObj, int statusCode, int port) throws IOException {
|
|
try {
|
|
String json = gson.toJson(jsonObj);
|
|
byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
|
|
|
|
exchange.getResponseHeaders().set("Content-Type", "application/json; charset=utf-8");
|
|
// Consider adding CORS headers if needed:
|
|
// exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*");
|
|
|
|
long responseLength = (statusCode == 204) ? -1 : bytes.length;
|
|
exchange.sendResponseHeaders(statusCode, responseLength);
|
|
|
|
if (responseLength != -1) {
|
|
try (OutputStream os = exchange.getResponseBody()) {
|
|
os.write(bytes);
|
|
}
|
|
} else {
|
|
exchange.getResponseBody().close(); // Important for 204
|
|
}
|
|
} catch (Exception e) {
|
|
Msg.error(HttpUtil.class, "Error sending JSON response: " + e.getMessage(), e);
|
|
// Avoid sending another error response here to prevent potential loops
|
|
if (!exchange.getResponseHeaders().containsKey("Content-Type")) {
|
|
byte[] errorBytes = ("Internal Server Error: " + e.getMessage()).getBytes(StandardCharsets.UTF_8);
|
|
exchange.getResponseHeaders().set("Content-Type", "text/plain; charset=utf-8");
|
|
exchange.sendResponseHeaders(500, errorBytes.length);
|
|
try (OutputStream os = exchange.getResponseBody()) {
|
|
os.write(errorBytes);
|
|
} catch (IOException writeErr) {
|
|
Msg.error(HttpUtil.class, "Failed to send even plain text error response", writeErr);
|
|
}
|
|
}
|
|
throw new IOException("Failed to send JSON response", e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sends a standardized error response using ResponseBuilder.
|
|
*/
|
|
public static void sendErrorResponse(HttpExchange exchange, int statusCode, String message, String errorCode, int port) throws IOException {
|
|
ResponseBuilder builder = new ResponseBuilder(exchange, port)
|
|
.success(false)
|
|
.error(message, errorCode);
|
|
sendJsonResponse(exchange, builder.build(), statusCode, port);
|
|
}
|
|
|
|
/**
|
|
* Parses query parameters from the URL.
|
|
*/
|
|
public static Map<String, String> parseQueryParams(HttpExchange exchange) {
|
|
Map<String, String> result = new HashMap<>();
|
|
String query = exchange.getRequestURI().getQuery();
|
|
if (query != null) {
|
|
String[] pairs = query.split("&");
|
|
for (String p : pairs) {
|
|
String[] kv = p.split("=");
|
|
if (kv.length == 2) {
|
|
try {
|
|
result.put(kv[0], java.net.URLDecoder.decode(kv[1], StandardCharsets.UTF_8));
|
|
} catch (Exception e) {
|
|
Msg.warn(HttpUtil.class, "Failed to decode query parameter: " + kv[0]);
|
|
result.put(kv[0], kv[1]);
|
|
}
|
|
} else if (kv.length == 1 && !kv[0].isEmpty()) {
|
|
result.put(kv[0], "");
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Parses POST body parameters strictly as JSON.
|
|
*/
|
|
public static Map<String, String> parseJsonPostParams(HttpExchange exchange) throws IOException {
|
|
byte[] body = exchange.getRequestBody().readAllBytes();
|
|
String bodyStr = new String(body, StandardCharsets.UTF_8);
|
|
Map<String, String> params = new HashMap<>();
|
|
|
|
try {
|
|
JsonObject json = gson.fromJson(bodyStr, JsonObject.class);
|
|
if (json == null) {
|
|
return params;
|
|
}
|
|
for (Map.Entry<String, JsonElement> entry : json.entrySet()) {
|
|
String key = entry.getKey();
|
|
JsonElement value = entry.getValue();
|
|
if (value.isJsonPrimitive()) {
|
|
params.put(key, value.getAsString());
|
|
} else {
|
|
params.put(key, value.toString()); // Stringify non-primitives
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
Msg.error(HttpUtil.class, "Failed to parse JSON request body: " + bodyStr, e);
|
|
throw new IOException("Invalid JSON request body: " + e.getMessage(), e);
|
|
}
|
|
return params;
|
|
}
|
|
}
|