package io.gitlab.jfronny.inceptum.util; import io.gitlab.jfronny.inceptum.Inceptum; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Type; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; public class HttpUtils { private static final HttpClient CLIENT = HttpClient.newHttpClient(); private enum Method { GET, POST } public static class Request { private HttpRequest.Builder builder; private Method method; public Request(Method method, String url) { try { this.builder = HttpRequest.newBuilder().uri(new URI(url)).header("User-Agent", "Meteor Client"); this.method = method; } catch (URISyntaxException e) { Inceptum.LOGGER.error("Could not create request", e); } } public Request bearer(String token) { builder.header("Authorization", "Bearer " + token); return this; } public Request header(String name, String value) { builder.header(name, value); return this; } public Request bodyString(String string) { builder.header("Content-Type", "text/plain"); builder.method(method.name(), HttpRequest.BodyPublishers.ofString(string)); method = null; return this; } public Request bodyForm(String string) { builder.header("Content-Type", "application/x-www-form-urlencoded"); builder.method(method.name(), HttpRequest.BodyPublishers.ofString(string)); method = null; return this; } public Request bodyForm(Map entries) { /*StringBuilder content = new StringBuilder(); for (Map.Entry entry : entries.entrySet()) { if (content.length() > 0) content.append('&'); content.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8)) .append('=') .append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8)); } return bodyForm(content.toString());*/ return bodyForm(entries.entrySet() .stream() .map(entry -> URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8) + '=' + URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8)) .collect(Collectors.joining("&"))); } public Request bodyJson(String string) { builder.header("Content-Type", "application/json"); builder.method(method.name(), HttpRequest.BodyPublishers.ofString(string)); method = null; return this; } public Request bodyJson(Object object) { builder.header("Content-Type", "application/json"); builder.method(method.name(), HttpRequest.BodyPublishers.ofString(Inceptum.GSON.toJson(object))); method = null; return this; } private T _send(String accept, HttpResponse.BodyHandler responseBodyHandler) { builder.header("Accept", accept); if (method != null) builder.method(method.name(), HttpRequest.BodyPublishers.noBody()); try { var res = CLIENT.send(builder.build(), responseBodyHandler); if (res.statusCode() == 200) return res.body(); Inceptum.LOGGER.error("Unexpected return method: " + res.statusCode()); Inceptum.LOGGER.error(getString(res.body())); return null; } catch (IOException | InterruptedException e) { Inceptum.LOGGER.error("Could not send request", e); return null; } } public void send() { _send("*/*", HttpResponse.BodyHandlers.discarding()); } public InputStream sendInputStream() { return _send("*/*", HttpResponse.BodyHandlers.ofInputStream()); } public String sendString() { return _send("*/*", HttpResponse.BodyHandlers.ofString()); } public Stream sendLines() { return _send("*/*", HttpResponse.BodyHandlers.ofLines()); } public T sendJson(Type type) { InputStream in = _send("application/json", HttpResponse.BodyHandlers.ofInputStream()); return in == null ? null : Inceptum.GSON.fromJson(new InputStreamReader(in), type); } private String getString(Object a) throws IOException { if (a instanceof InputStream s) return new String(s.readAllBytes()); if (a instanceof String s) return s; if (a instanceof Stream s) return ((Stream)s).collect(Collectors.joining()); return ""; } } public static Request get(String url) { return new Request(Method.GET, url); } public static Request post(String url) { return new Request(Method.POST, url); } }