|
|
@ -1,6 +1,7 @@ |
|
|
|
/* © SRSoftware 2024 */ |
|
|
|
/* © SRSoftware 2024 */ |
|
|
|
package de.srsoftware.oidc.api; |
|
|
|
package de.srsoftware.oidc.api; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import static java.net.HttpURLConnection.HTTP_OK; |
|
|
|
import static java.nio.charset.StandardCharsets.UTF_8; |
|
|
|
import static java.nio.charset.StandardCharsets.UTF_8; |
|
|
|
|
|
|
|
|
|
|
|
import com.sun.net.httpserver.HttpExchange; |
|
|
|
import com.sun.net.httpserver.HttpExchange; |
|
|
@ -15,56 +16,103 @@ import org.json.JSONObject; |
|
|
|
|
|
|
|
|
|
|
|
public abstract class PathHandler implements HttpHandler { |
|
|
|
public abstract class PathHandler implements HttpHandler { |
|
|
|
public static final String CONTENT_TYPE = "Content-Type"; |
|
|
|
public static final String CONTENT_TYPE = "Content-Type"; |
|
|
|
|
|
|
|
public static final String GET = "GET"; |
|
|
|
public static final String JSON = "application/json"; |
|
|
|
public static final String JSON = "application/json"; |
|
|
|
public static final String POST = "POST"; |
|
|
|
public static final String POST = "POST"; |
|
|
|
|
|
|
|
|
|
|
|
private String path; |
|
|
|
private String[] paths; |
|
|
|
|
|
|
|
|
|
|
|
public class Bond { |
|
|
|
public class Bond { |
|
|
|
Bond(String p) { |
|
|
|
Bond(String[] paths) { |
|
|
|
path = p; |
|
|
|
PathHandler.this.paths = paths; |
|
|
|
} |
|
|
|
} |
|
|
|
public HttpServer on(HttpServer server) { |
|
|
|
public HttpServer on(HttpServer server) { |
|
|
|
server.createContext(path, PathHandler.this); |
|
|
|
for (var path : paths) server.createContext(path, PathHandler.this); |
|
|
|
return server; |
|
|
|
return server; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public Bond bindPath(String path) { |
|
|
|
public Bond bindPath(String... path) { |
|
|
|
return new Bond(path); |
|
|
|
return new Bond(path); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public String relativePath(HttpExchange ex) { |
|
|
|
public boolean doGet(String path, HttpExchange ex) throws IOException { |
|
|
|
var path = ex.getRequestURI().toString(); |
|
|
|
return false; |
|
|
|
if (path.startsWith(this.path)) path = path.substring(this.path.length()); |
|
|
|
|
|
|
|
if (path.startsWith("/")) path = path.substring(1); |
|
|
|
|
|
|
|
return path; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public boolean doPost(String path, HttpExchange ex) throws IOException { |
|
|
|
/******* begin of static methods *************/ |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
public static String body(HttpExchange ex) throws IOException { |
|
|
|
|
|
|
|
return new String(ex.getRequestBody().readAllBytes(), UTF_8); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static Optional<String> getAuthToken(HttpExchange ex) { |
|
|
|
@Override |
|
|
|
return getHeader(ex, "Authorization"); |
|
|
|
public void handle(HttpExchange ex) throws IOException { |
|
|
|
|
|
|
|
String path = relativePath(ex); |
|
|
|
|
|
|
|
String method = ex.getRequestMethod(); |
|
|
|
|
|
|
|
System.out.printf("%s %s\n", method, path); |
|
|
|
|
|
|
|
boolean dummy = switch (method) { |
|
|
|
|
|
|
|
case POST -> doPost(path,ex); |
|
|
|
|
|
|
|
case GET -> doGet(path,ex); |
|
|
|
|
|
|
|
default -> false; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
ex.getResponseBody().close(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static Optional<String> getHeader(HttpExchange ex, String key) { |
|
|
|
public String relativePath(HttpExchange ex) { |
|
|
|
return Optional.ofNullable(ex.getRequestHeaders().get(key)).map(List::stream).map(Stream::findFirst).orElse(Optional.empty()); |
|
|
|
var requestPath = ex.getRequestURI().toString(); |
|
|
|
} |
|
|
|
for (var path : paths){ |
|
|
|
|
|
|
|
if (requestPath.startsWith(path)) { |
|
|
|
|
|
|
|
requestPath = requestPath.substring(path.length()); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!requestPath.startsWith("/")) requestPath = "/" + requestPath; |
|
|
|
|
|
|
|
var pos = requestPath.indexOf("?"); |
|
|
|
|
|
|
|
if (pos >= 0) requestPath = requestPath.substring(0, pos); |
|
|
|
|
|
|
|
return requestPath; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static JSONObject json(HttpExchange ex) throws IOException { |
|
|
|
/******* begin of static methods *************/ |
|
|
|
return new JSONObject(body(ex)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static Optional<String> language(HttpExchange ex) { |
|
|
|
public static String body(HttpExchange ex) throws IOException { |
|
|
|
return getHeader(ex, "Accept-Language").map(s -> Arrays.stream(s.split(","))).map(Stream::findFirst).orElse(Optional.empty()); |
|
|
|
return new String(ex.getRequestBody().readAllBytes(), UTF_8); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static void sendEmptyResponse(int statusCode, HttpExchange ex) throws IOException { |
|
|
|
public static Optional<String> getAuthToken(HttpExchange ex) { |
|
|
|
ex.sendResponseHeaders(statusCode, 0); |
|
|
|
return getHeader(ex, "Authorization"); |
|
|
|
ex.getResponseBody().close(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static Optional<String> getHeader(HttpExchange ex, String key) { |
|
|
|
|
|
|
|
return Optional.ofNullable(ex.getRequestHeaders().get(key)).map(List::stream).map(Stream::findFirst).orElse(Optional.empty()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static boolean isPost(String method) { |
|
|
|
|
|
|
|
return POST.equals(method); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static JSONObject json(HttpExchange ex) throws IOException { |
|
|
|
|
|
|
|
return new JSONObject(body(ex)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static Optional<String> language(HttpExchange ex) { |
|
|
|
|
|
|
|
return getHeader(ex, "Accept-Language").map(s -> Arrays.stream(s.split(","))).map(Stream::findFirst).orElse(Optional.empty()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static String prefix(HttpExchange ex) { |
|
|
|
|
|
|
|
return "http://%s".formatted(ex.getRequestHeaders().getFirst("Host")); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static boolean sendEmptyResponse(int statusCode, HttpExchange ex) throws IOException { |
|
|
|
|
|
|
|
ex.sendResponseHeaders(statusCode, 0); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static boolean sendContent(HttpExchange ex, byte[] bytes) throws IOException { |
|
|
|
|
|
|
|
ex.sendResponseHeaders(HTTP_OK, bytes.length); |
|
|
|
|
|
|
|
ex.getResponseBody().write(bytes); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static boolean sendContent(HttpExchange ex, Object o) throws IOException { |
|
|
|
|
|
|
|
return sendContent(ex, o.toString().getBytes(UTF_8)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|