388 lines
13 KiB
Java
388 lines
13 KiB
Java
import java.net.URI;
|
|
import java.net.http.HttpClient;
|
|
import java.net.http.HttpRequest;
|
|
import java.net.http.HttpResponse;
|
|
import java.net.CookieManager;
|
|
import java.net.HttpCookie;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.HashMap;
|
|
import java.util.ArrayList;
|
|
import java.util.regex.Pattern;
|
|
import java.util.regex.Matcher;
|
|
|
|
public class ClientLib {
|
|
private final String baseUrl;
|
|
private final HttpClient httpClient;
|
|
private final CookieManager cookieManager;
|
|
|
|
private String userId;
|
|
private String username;
|
|
private String authToken;
|
|
|
|
public ClientLib(String serviceUrl) {
|
|
this.baseUrl = serviceUrl.endsWith("/") ? serviceUrl.substring(0, serviceUrl.length() - 1) : serviceUrl;
|
|
this.cookieManager = new CookieManager();
|
|
this.httpClient = HttpClient.newBuilder()
|
|
.cookieHandler(cookieManager)
|
|
.build();
|
|
}
|
|
|
|
public Map<String, Object> registerUser(String username, String password) throws Exception {
|
|
String body = "{\"username\":\"" + jsonEscape(username) + "\",\"password\":\"" + jsonEscape(password) + "\"}";
|
|
|
|
String response = post("/api/account/signup", body);
|
|
Map<String, Object> result = parseJsonObject(response);
|
|
|
|
if (result.containsKey("success") && Boolean.TRUE.equals(result.get("success"))) {
|
|
this.username = (String) result.get("username");
|
|
Object userIdObj = result.get("userId");
|
|
this.userId = String.valueOf(userIdObj);
|
|
extractCookies();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public Map<String, Object> login(String username, String password) throws Exception {
|
|
String body = "{\"username\":\"" + jsonEscape(username) + "\",\"password\":\"" + jsonEscape(password) + "\"}";
|
|
|
|
String response = post("/api/account/login", body);
|
|
Map<String, Object> result = parseJsonObject(response);
|
|
|
|
if (result.containsKey("success") && Boolean.TRUE.equals(result.get("success"))) {
|
|
this.username = (String) result.get("username");
|
|
Object userIdObj = result.get("userId");
|
|
this.userId = String.valueOf(userIdObj);
|
|
extractCookies();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public Map<String, Object> getCurrentUser() throws Exception {
|
|
String response = get("/api/account/me");
|
|
return parseJsonObject(response);
|
|
}
|
|
|
|
public Map<String, Object> logout() throws Exception {
|
|
String response = post("/api/account/logout", "{}");
|
|
Map<String, Object> result = parseJsonObject(response);
|
|
|
|
this.userId = null;
|
|
this.username = null;
|
|
this.authToken = null;
|
|
|
|
return result;
|
|
}
|
|
|
|
public Map<String, Object> createForm(Map<String, Object> schema) throws Exception {
|
|
String schemaJson = mapToJson(schema);
|
|
String body = "{\"schema\":" + schemaJson + "}";
|
|
|
|
String response = post("/api/form/new", body);
|
|
return parseJsonObject(response);
|
|
}
|
|
|
|
public Map<String, Object> getForm(String formId) throws Exception {
|
|
String response = get("/api/form/" + formId);
|
|
return parseJsonObject(response);
|
|
}
|
|
|
|
public Map<String, Object> updateForm(String formId, Map<String, Object> schema) throws Exception {
|
|
String schemaJson = mapToJson(schema);
|
|
String body = "{\"schema\":" + schemaJson + "}";
|
|
|
|
String response = put("/api/form/" + formId, body);
|
|
return parseJsonObject(response);
|
|
}
|
|
|
|
public Map<String, Object> submitFormResponse(String formId, Map<String, Object> payload) throws Exception {
|
|
String payloadJson = mapToJson(payload);
|
|
|
|
String response = post("/api/form/" + formId + "/submit", payloadJson);
|
|
return parseJsonObject(response);
|
|
}
|
|
|
|
public List<Map<String, Object>> getMyForms() throws Exception {
|
|
String response = get("/api/form/my-forms");
|
|
return parseJsonArray(response);
|
|
}
|
|
|
|
public List<String> getFormResults(String formId) throws Exception {
|
|
String response = get("/api/form/" + formId + "/results");
|
|
return parseStringArray(response);
|
|
}
|
|
|
|
private String get(String endpoint) throws Exception {
|
|
HttpRequest request = HttpRequest.newBuilder()
|
|
.uri(URI.create(baseUrl + endpoint))
|
|
.GET()
|
|
.build();
|
|
|
|
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
|
return response.body();
|
|
}
|
|
|
|
private String post(String endpoint, String jsonBody) throws Exception {
|
|
HttpRequest request = HttpRequest.newBuilder()
|
|
.uri(URI.create(baseUrl + endpoint))
|
|
.header("Content-Type", "application/json")
|
|
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
|
|
.build();
|
|
|
|
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
|
return response.body();
|
|
}
|
|
|
|
private String put(String endpoint, String jsonBody) throws Exception {
|
|
HttpRequest request = HttpRequest.newBuilder()
|
|
.uri(URI.create(baseUrl + endpoint))
|
|
.header("Content-Type", "application/json")
|
|
.PUT(HttpRequest.BodyPublishers.ofString(jsonBody))
|
|
.build();
|
|
|
|
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
|
return response.body();
|
|
}
|
|
|
|
private void extractCookies() {
|
|
List<HttpCookie> cookies = cookieManager.getCookieStore().getCookies();
|
|
for (HttpCookie cookie : cookies) {
|
|
switch (cookie.getName()) {
|
|
case "uid":
|
|
this.userId = cookie.getValue();
|
|
break;
|
|
case "u":
|
|
this.username = cookie.getValue();
|
|
break;
|
|
case "auth":
|
|
this.authToken = cookie.getValue();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public String getUserId() {
|
|
return userId;
|
|
}
|
|
|
|
public String getUsername() {
|
|
return username;
|
|
}
|
|
|
|
public String getAuthToken() {
|
|
return authToken;
|
|
}
|
|
|
|
public String getBaseUrl() {
|
|
return baseUrl;
|
|
}
|
|
|
|
public boolean isAuthenticated() {
|
|
return username != null && authToken != null && userId != null;
|
|
}
|
|
|
|
public void setSessionCookies(String userId, String username, String authToken) {
|
|
this.userId = userId;
|
|
this.username = username;
|
|
this.authToken = authToken;
|
|
|
|
try {
|
|
URI uri = new URI(baseUrl);
|
|
HttpCookie uidCookie = new HttpCookie("uid", userId);
|
|
uidCookie.setPath("/");
|
|
uidCookie.setDomain(uri.getHost());
|
|
|
|
HttpCookie uCookie = new HttpCookie("u", username);
|
|
uCookie.setPath("/");
|
|
uCookie.setDomain(uri.getHost());
|
|
|
|
HttpCookie authCookie = new HttpCookie("auth", authToken);
|
|
authCookie.setPath("/");
|
|
authCookie.setDomain(uri.getHost());
|
|
|
|
cookieManager.getCookieStore().add(uri, uidCookie);
|
|
cookieManager.getCookieStore().add(uri, uCookie);
|
|
cookieManager.getCookieStore().add(uri, authCookie);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
private String jsonEscape(String str) {
|
|
return str.replace("\\", "\\\\")
|
|
.replace("\"", "\\\"")
|
|
.replace("\n", "\\n")
|
|
.replace("\r", "\\r")
|
|
.replace("\t", "\\t");
|
|
}
|
|
|
|
private String mapToJson(Map<String, Object> map) {
|
|
StringBuilder sb = new StringBuilder("{");
|
|
boolean first = true;
|
|
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
|
if (!first) sb.append(",");
|
|
first = false;
|
|
sb.append("\"").append(jsonEscape(entry.getKey())).append("\":");
|
|
sb.append(valueToJson(entry.getValue()));
|
|
}
|
|
sb.append("}");
|
|
return sb.toString();
|
|
}
|
|
|
|
private String valueToJson(Object value) {
|
|
if (value == null) {
|
|
return "null";
|
|
} else if (value instanceof String) {
|
|
return "\"" + jsonEscape((String) value) + "\"";
|
|
} else if (value instanceof Number || value instanceof Boolean) {
|
|
return value.toString();
|
|
} else if (value instanceof Map) {
|
|
return mapToJson((Map<String, Object>) value);
|
|
} else if (value instanceof List) {
|
|
StringBuilder sb = new StringBuilder("[");
|
|
boolean first = true;
|
|
for (Object item : (List<?>) value) {
|
|
if (!first) sb.append(",");
|
|
first = false;
|
|
sb.append(valueToJson(item));
|
|
}
|
|
sb.append("]");
|
|
return sb.toString();
|
|
} else {
|
|
return "\"" + jsonEscape(value.toString()) + "\"";
|
|
}
|
|
}
|
|
|
|
private Map<String, Object> parseJsonObject(String json) {
|
|
Map<String, Object> result = new HashMap<>();
|
|
json = json.trim();
|
|
|
|
if (!json.startsWith("{") || !json.endsWith("}")) {
|
|
return result;
|
|
}
|
|
|
|
json = json.substring(1, json.length() - 1).trim();
|
|
|
|
Pattern pattern = Pattern.compile("\"([^\"]+)\"\\s*:\\s*([^,}]+|\\{[^}]*\\}|\\[[^\\]]*\\]|\"[^\"]*\")");
|
|
Matcher matcher = pattern.matcher(json);
|
|
|
|
while (matcher.find()) {
|
|
String key = matcher.group(1);
|
|
String value = matcher.group(2).trim();
|
|
result.put(key, parseValue(value));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private List<Map<String, Object>> parseJsonArray(String json) {
|
|
List<Map<String, Object>> result = new ArrayList<>();
|
|
json = json.trim();
|
|
|
|
if (!json.startsWith("[") || !json.endsWith("]")) {
|
|
return result;
|
|
}
|
|
|
|
json = json.substring(1, json.length() - 1).trim();
|
|
|
|
if (json.isEmpty()) {
|
|
return result;
|
|
}
|
|
|
|
int depth = 0;
|
|
StringBuilder current = new StringBuilder();
|
|
for (char c : json.toCharArray()) {
|
|
if (c == '{') depth++;
|
|
else if (c == '}') depth--;
|
|
|
|
if (c == ',' && depth == 0) {
|
|
result.add(parseJsonObject(current.toString()));
|
|
current = new StringBuilder();
|
|
} else {
|
|
current.append(c);
|
|
}
|
|
}
|
|
|
|
if (current.length() > 0) {
|
|
result.add(parseJsonObject(current.toString()));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private List<String> parseStringArray(String json) {
|
|
List<String> result = new ArrayList<>();
|
|
json = json.trim();
|
|
|
|
if (!json.startsWith("[") || !json.endsWith("]")) {
|
|
return result;
|
|
}
|
|
|
|
json = json.substring(1, json.length() - 1).trim();
|
|
|
|
if (json.isEmpty()) {
|
|
return result;
|
|
}
|
|
|
|
int depth = 0;
|
|
boolean inString = false;
|
|
StringBuilder current = new StringBuilder();
|
|
|
|
for (int i = 0; i < json.length(); i++) {
|
|
char c = json.charAt(i);
|
|
|
|
if (c == '"' && (i == 0 || json.charAt(i - 1) != '\\')) {
|
|
inString = !inString;
|
|
}
|
|
|
|
if (!inString) {
|
|
if (c == '{' || c == '[') depth++;
|
|
else if (c == '}' || c == ']') depth--;
|
|
}
|
|
|
|
if (c == ',' && depth == 0 && !inString) {
|
|
String item = current.toString().trim();
|
|
if (item.startsWith("\"") && item.endsWith("\"")) {
|
|
item = item.substring(1, item.length() - 1);
|
|
}
|
|
result.add(item);
|
|
current = new StringBuilder();
|
|
} else {
|
|
current.append(c);
|
|
}
|
|
}
|
|
|
|
if (current.length() > 0) {
|
|
String item = current.toString().trim();
|
|
if (item.startsWith("\"") && item.endsWith("\"")) {
|
|
item = item.substring(1, item.length() - 1);
|
|
}
|
|
result.add(item);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private Object parseValue(String value) {
|
|
value = value.trim();
|
|
|
|
if (value.equals("null")) {
|
|
return null;
|
|
} else if (value.equals("true")) {
|
|
return Boolean.TRUE;
|
|
} else if (value.equals("false")) {
|
|
return Boolean.FALSE;
|
|
} else if (value.startsWith("\"") && value.endsWith("\"")) {
|
|
return value.substring(1, value.length() - 1);
|
|
} else if (value.matches("-?\\d+")) {
|
|
return Long.parseLong(value);
|
|
} else if (value.matches("-?\\d+\\.\\d+")) {
|
|
return Double.parseDouble(value);
|
|
} else {
|
|
return value;
|
|
}
|
|
}
|
|
}
|