diff --git a/src/dev/asdf00/lib/httpserver/HttpServerApi.java b/src/dev/asdf00/lib/httpserver/HttpServerApi.java index 5ad2631..d21910d 100644 --- a/src/dev/asdf00/lib/httpserver/HttpServerApi.java +++ b/src/dev/asdf00/lib/httpserver/HttpServerApi.java @@ -30,7 +30,7 @@ public class HttpServerApi { throw new HttpHandlingException(404); } - public static HttpServer create(int port, String rootLocation, Class apiDefinition, Executor exec) throws IOException { + public static HttpServer create(int port, String rootLocation, Executor exec, Class... apiDefinitions) throws IOException { HttpServer server = HttpServer.create(new InetSocketAddress( port), 0); server.setExecutor(exec); @@ -38,66 +38,68 @@ public class HttpServerApi { HashMap[] endpoints = new HashMap[3]; HashSet locations = new HashSet<>(); for (int i = 0; i < endpoints.length; endpoints[i++] = new HashMap<>()); - endpointLoop: - for (Method endpoint : apiDefinition.getDeclaredMethods()) { - HttpEndpoint spec = endpoint.getAnnotation(HttpEndpoint.class); - if (spec == null || spec.type() == INVALID) { - continue; - } - if (!endpoint.getReturnType().equals(Response.class)) { - System.err.printf("invalid return type %s!\nskipping %s ...\n", endpoint.getReturnType().getSimpleName(), endpoint.getName()); - continue; - } - - RequestType type = spec.type(); - String location = spec.location(); - HashMap epMap = endpoints[type.id]; - if (epMap.containsKey(location)) { - System.err.printf("HttpEndpoint for type %s and location \"%s\" is defined multiple times!\nskipping %s ...\n", - type.name(), location, endpoint.getName()); - continue; - } - - Parameter[] params = endpoint.getParameters(); - if (params.length < 1 || !HttpExchange.class.equals(params[0].getType())) { - System.err.printf("HttpEndpoint must have HttpExchange as first parameter!\nskipping %s ...\n", - endpoint.getReturnType().getSimpleName(), endpoint.getName()); - continue; - } - params = Arrays.stream(params).skip(1).toArray(Parameter[]::new); - - Class[] pTypes = Arrays.stream(params).map(p -> p.getType()).toArray(Class[]::new); - String[] pNames = new String[params.length]; - String[] stringVals = new String[params.length]; - for (int i = 0; i < params.length; i++) { - QParam name = params[i].getAnnotation(QParam.class); - if (name == null) { - System.err.printf("missing QParam annotation!\nskipping %s ...\n", endpoint.getName()); - continue endpointLoop; + for (var apiDefinition : apiDefinitions) { + endpointLoop: + for (Method endpoint : apiDefinition.getDeclaredMethods()) { + HttpEndpoint spec = endpoint.getAnnotation(HttpEndpoint.class); + if (spec == null || spec.type() == INVALID) { + continue; } - pNames[i] = name.name(); - stringVals[i] = name.empty(); - } - Object[] pDefaults = new Object[pTypes.length]; - try { - for (int i = 0; i < pTypes.length; i++) { - pDefaults[i] = parseValue(pTypes[i], stringVals[i]); + if (!endpoint.getReturnType().equals(Response.class)) { + System.err.printf("invalid return type %s!\nskipping %s ...\n", endpoint.getReturnType().getSimpleName(), endpoint.getName()); + continue; } - } catch (IllegalArgumentException e) { - System.err.printf("encountered error setting up HttpEndpoint (%s)!\nskipping %s ...\n", e.getMessage(), endpoint.getName()); - continue; - } - Authorizer auth; - try { - auth = spec.auth().getConstructor().newInstance(); - } catch (ReflectiveOperationException e) { - System.err.printf("encountered error setting up HttpEndpoint (%s)!\nskipping %s ...\n", e.getMessage(), endpoint.getName()); - continue; - } + RequestType type = spec.type(); + String location = spec.location(); + HashMap epMap = endpoints[type.id]; + if (epMap.containsKey(location)) { + System.err.printf("HttpEndpoint for type %s and location \"%s\" is defined multiple times!\nskipping %s ...\n", + type.name(), location, endpoint.getName()); + continue; + } - epMap.put(location, new EndpointContainer(endpoint, auth, pTypes, pNames, pDefaults)); - locations.add(location); + Parameter[] params = endpoint.getParameters(); + if (params.length < 1 || !HttpExchange.class.equals(params[0].getType())) { + System.err.printf("HttpEndpoint must have HttpExchange as first parameter!\nskipping %s ...\n", + endpoint.getReturnType().getSimpleName(), endpoint.getName()); + continue; + } + params = Arrays.stream(params).skip(1).toArray(Parameter[]::new); + + Class[] pTypes = Arrays.stream(params).map(p -> p.getType()).toArray(Class[]::new); + String[] pNames = new String[params.length]; + String[] stringVals = new String[params.length]; + for (int i = 0; i < params.length; i++) { + QParam name = params[i].getAnnotation(QParam.class); + if (name == null) { + System.err.printf("missing QParam annotation!\nskipping %s ...\n", endpoint.getName()); + continue endpointLoop; + } + pNames[i] = name.name(); + stringVals[i] = name.empty(); + } + Object[] pDefaults = new Object[pTypes.length]; + try { + for (int i = 0; i < pTypes.length; i++) { + pDefaults[i] = parseValue(pTypes[i], stringVals[i]); + } + } catch (IllegalArgumentException e) { + System.err.printf("encountered error setting up HttpEndpoint (%s)!\nskipping %s ...\n", e.getMessage(), endpoint.getName()); + continue; + } + + Authorizer auth; + try { + auth = spec.auth().getConstructor().newInstance(); + } catch (ReflectiveOperationException e) { + System.err.printf("encountered error setting up HttpEndpoint (%s)!\nskipping %s ...\n", e.getMessage(), endpoint.getName()); + continue; + } + + epMap.put(location, new EndpointContainer(endpoint, auth, pTypes, pNames, pDefaults)); + locations.add(location); + } } // create appropriate contexts and headers diff --git a/src/dev/asdf00/lib/httpserver/HttpServerApiUtils.java b/src/dev/asdf00/lib/httpserver/HttpServerApiUtils.java index efbee82..dbf0457 100644 --- a/src/dev/asdf00/lib/httpserver/HttpServerApiUtils.java +++ b/src/dev/asdf00/lib/httpserver/HttpServerApiUtils.java @@ -5,10 +5,13 @@ import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpPrincipal; import dev.asdf00.lib.httpserver.exceptions.HttpHandlingException; -import java.io.*; +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; import java.net.URI; import java.nio.file.InvalidPathException; import java.nio.file.Path; +import java.util.List; import java.util.Map; import java.util.stream.Stream; @@ -83,4 +86,18 @@ public class HttpServerApiUtils { } throw new IllegalArgumentException(type.getSimpleName() + " is not a primitive"); } + + public static String readCookie(String key, List cookies) { + String value = null; + outer: + for (var cookie : cookies) { + for (String s : cookie.split("; ")) { + if (s.startsWith(key + "=")) { + value = s.substring(key.length() + 1); + break outer; + } + } + } + return value; + } } diff --git a/src/dev/asdf00/lib/httpserver/internal/HttpHandlerImpl.java b/src/dev/asdf00/lib/httpserver/internal/HttpHandlerImpl.java index 4ea82dc..a8bf230 100644 --- a/src/dev/asdf00/lib/httpserver/internal/HttpHandlerImpl.java +++ b/src/dev/asdf00/lib/httpserver/internal/HttpHandlerImpl.java @@ -2,8 +2,8 @@ package dev.asdf00.lib.httpserver.internal; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; -import dev.asdf00.lib.httpserver.HttpServerApiUtils; import dev.asdf00.lib.httpserver.exceptions.HttpHandlingException; +import dev.asdf00.lib.httpserver.utils.ContentType; import dev.asdf00.lib.httpserver.utils.RequestType; import dev.asdf00.lib.httpserver.utils.Response; @@ -28,7 +28,7 @@ public class HttpHandlerImpl implements HttpHandler { EndpointContainer target = endpointContainer[type.id]; if (!target.auth.isAuthenticated(exchange)) { - throw new HttpHandlingException(402); + throw new HttpHandlingException(498); } String query = exchange.getRequestURI().getQuery(); @@ -47,9 +47,8 @@ public class HttpHandlerImpl implements HttpHandler { } else if (e instanceof IndexOutOfBoundsException) { errorCode = 400; } - Response r = new Response(exchange).status(errorCode).contentType(Response.ContentType.HTML); - r.append(String.format("

ERROR %s

\n", errorCode)); - r.append(String.format("

something fucky is a foot!\n%s

", e.getMessage())); + Response r = new Response(exchange).status(errorCode).contentType(ContentType.HTML); + r.append(String.format("

\n

 

Error message:

\n

\n%s\n

", errorCode, e.getMessage())); r.send(); } } diff --git a/src/dev/asdf00/lib/httpserver/utils/ContentType.java b/src/dev/asdf00/lib/httpserver/utils/ContentType.java new file mode 100644 index 0000000..d949adf --- /dev/null +++ b/src/dev/asdf00/lib/httpserver/utils/ContentType.java @@ -0,0 +1,12 @@ +package dev.asdf00.lib.httpserver.utils; + +public enum ContentType { + PLAIN("text/plain"), + HTML("text/html"), + JS("application/javascript"), + JSON("application/json"); + public final String type; + ContentType(String type) { + this.type = type; + } +} diff --git a/src/dev/asdf00/lib/httpserver/utils/Response.java b/src/dev/asdf00/lib/httpserver/utils/Response.java index df884cc..6b2bdc4 100644 --- a/src/dev/asdf00/lib/httpserver/utils/Response.java +++ b/src/dev/asdf00/lib/httpserver/utils/Response.java @@ -9,15 +9,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; public class Response { - public enum ContentType { - PLAIN("text/plain"), - HTML("text/html"), - JS("text/javascript"); - private final String type; - ContentType(String type) { - this.type = type; - } - } + private int statusCode = 500; private ContentType cType = ContentType.PLAIN; @@ -39,6 +31,11 @@ public class Response { return this; } + public Response append(String format, Object... params) { + response.append(String.format(format, params)); + return this; + } + public Response append(String line) { response.append(line); return this; diff --git a/src/module-info.java b/src/module-info.java new file mode 100644 index 0000000..4da305e --- /dev/null +++ b/src/module-info.java @@ -0,0 +1,7 @@ +module asdf00.lib.httpserver { + requires jdk.httpserver; + exports dev.asdf00.lib.httpserver; + exports dev.asdf00.lib.httpserver.annotations; + exports dev.asdf00.lib.httpserver.exceptions; + exports dev.asdf00.lib.httpserver.utils; +} \ No newline at end of file