From a06eb168e770196f04b4762d20a19a552bbb5599 Mon Sep 17 00:00:00 2001 From: jeffcheasey88 Date: Fri, 8 Sep 2023 14:34:44 +0200 Subject: [PATCH] Swagger --- src/dev/peerat/backend/Main.java | 9 +- .../backend/bonus/extract/RouteExtracter.java | 127 +++++++++++++++--- src/dev/peerat/backend/routes/Swagger.java | 33 +++++ 3 files changed, 143 insertions(+), 26 deletions(-) create mode 100644 src/dev/peerat/backend/routes/Swagger.java diff --git a/src/dev/peerat/backend/Main.java b/src/dev/peerat/backend/Main.java index b794251..c98b5de 100644 --- a/src/dev/peerat/backend/Main.java +++ b/src/dev/peerat/backend/Main.java @@ -6,6 +6,7 @@ import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; +import dev.peerat.backend.bonus.extract.RouteExtracter; import dev.peerat.backend.model.Completion; import dev.peerat.backend.model.Group; import dev.peerat.backend.model.PeerAtUser; @@ -19,6 +20,7 @@ import dev.peerat.backend.routes.PlayerDetails; import dev.peerat.backend.routes.PuzzleElement; import dev.peerat.backend.routes.PuzzleResponse; import dev.peerat.backend.routes.Result; +import dev.peerat.backend.routes.Swagger; import dev.peerat.backend.routes.admins.DynamicLogs; import dev.peerat.backend.routes.groups.GroupCreate; import dev.peerat.backend.routes.groups.GroupJoin; @@ -80,9 +82,6 @@ public class Main{ initRoutes(router, repo, config); -// RouteExtracter extracter = new RouteExtracter(router); -// extracter.extract(); - if(config.useSsl()) router.configureSSL(config.getSslKeystore(), config.getSslKeystorePasswd()); router.listen(config.getTcpPort(), config.useSsl()); } @@ -117,7 +116,9 @@ public class Main{ register(new GroupCreate(repo, groupLock, config.getGroupJoinMinutes())). register(new GroupList(repo)). register(new GroupJoin(repo, config.getGroupJoinMinutes(), config.getGroupQuitMinutes(), leaderboard)). - register(new GroupQuit(repo, config.getGroupJoinMinutes(), leaderboard)); + register(new GroupQuit(repo, config.getGroupJoinMinutes(), leaderboard)) + + .register(new Swagger(new RouteExtracter(router),config.getTokenIssuer())); // Bot bot = new Bot(config, repo, groupLock); // bot.start(); diff --git a/src/dev/peerat/backend/bonus/extract/RouteExtracter.java b/src/dev/peerat/backend/bonus/extract/RouteExtracter.java index 4598d5d..9caf3d0 100644 --- a/src/dev/peerat/backend/bonus/extract/RouteExtracter.java +++ b/src/dev/peerat/backend/bonus/extract/RouteExtracter.java @@ -2,48 +2,131 @@ package dev.peerat.backend.bonus.extract; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.Map; -import java.util.Map.Entry; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import dev.peerat.backend.model.PeerAtUser; import dev.peerat.framework.RequestType; import dev.peerat.framework.Response; import dev.peerat.framework.Route; +import dev.peerat.framework.RouteMapper; import dev.peerat.framework.Router; -//A noter que le but est d'extraire des informations sans modifier le code source, -//comme les tests unitaire, ici je veux générer un élément textuel qui me donnera l'état des routes, -//je ne vais donc pas modifier la classe router pour donner un accès au route. public class RouteExtracter { - private Router router; + private Router router; - public RouteExtracter(Router router){ + public RouteExtracter(Router router){ this.router = router; } public void extract() throws Exception{ - Field field = Router.class.getDeclaredField("responses"); - field.setAccessible(true); - Map> responses = (Map>) field.get(this.router); - for(Entry> types : responses.entrySet()){ - for(Entry routes : types.getValue().entrySet()){ - System.out.println("["+types.getKey()+"] ("+routes.getValue().needLogin()+") "+routes.getValue().path()); + RouteMapper[] mappers = getField(Router.class, router, "mappers"); + for(RequestType type : RequestType.values()){ + RouteMapper mapper = mappers[type.ordinal()]; + Response[] responses = getField(RouteMapper.class, mapper, "responses"); + Route[] routes = getField(RouteMapper.class, mapper, "routes"); + synchronized (responses){ + for(int i = 0; i < responses.length; i++){ + Route route = routes[i]; + System.out.println("["+type+"] ("+route.needLogin()+") "+route.path()); + } } } } public void extractDoc() throws Exception{ - Field field = Router.class.getDeclaredField("responses"); - field.setAccessible(true); - Map> responses = (Map>) field.get(this.router); - for(Map route : responses.values()){ - for(Response response : route.keySet()){ - Method method = response.getClass().getDeclaredMethod("exec", - Response.class.getDeclaredMethods()[0].getParameterTypes()); - for(RouteDoc doc : method.getDeclaredAnnotationsByType(RouteDoc.class)){ - System.out.println(doc.path()+((doc.path().isEmpty() ? "":"\n"))+" ["+doc.responseCode()+"] "+doc.responseDescription()); + RouteMapper[] mappers = getField(Router.class, router, "mappers"); + for(RequestType type : RequestType.values()){ + RouteMapper mapper = mappers[type.ordinal()]; + Response[] responses = getField(RouteMapper.class, mapper, "responses"); + synchronized (responses){ + for(int i = 0; i < responses.length; i++){ + Response response = responses[i]; + Method method = response.getClass().getDeclaredMethod("exec", + Response.class.getDeclaredMethods()[0].getParameterTypes()); + for(RouteDoc doc : method.getDeclaredAnnotationsByType(RouteDoc.class)){ + System.out.println(doc.path()+((doc.path().isEmpty() ? "":"\n"))+" ["+doc.responseCode()+"] "+doc.responseDescription()); + } } } } } + + public JSONObject swagger(String host) throws Exception{ + JSONObject result = new JSONObject(); + result.put("swagger","2.0"); + JSONObject info = new JSONObject(); + info.put("title", "Peer-at-code backend api routes"); + info.put("description", "Using Peer-at Code Framework"); + result.put("info", info); + result.put("host", host); + result.put("basePath","/"); + + List routes = new ArrayList<>(); + RouteMapper[] mappers = getField(Router.class, router, "mappers"); + for(RequestType type : RequestType.values()){ + RouteMapper mapper = mappers[type.ordinal()]; + Response[] responses = getField(RouteMapper.class, mapper, "responses"); + synchronized (responses){ + routes.addAll(Arrays.asList(responses)); + } + } + + Set packages = new HashSet<>(); + for(Response response : routes){ + String name = response.getClass().getPackage().getName(); + name = name.substring(name.lastIndexOf('.')+1, name.length()); + packages.add(name); + } + JSONArray tags = new JSONArray(); + for(String tag : packages){ + JSONObject current = new JSONObject(); + current.put("name", tag); + tags.add(current); + } + result.put("tags", tags); + JSONArray schemes = new JSONArray(); + schemes.add("https"); + result.put("schemes", schemes); + + JSONObject paths = new JSONObject(); + + for(Response response : routes){ + Method method = response.getClass().getDeclaredMethod("exec", + Response.class.getDeclaredMethods()[0].getParameterTypes()); + Route route = method.getDeclaredAnnotation(Route.class); + RouteDoc[] docs = method.getDeclaredAnnotationsByType(RouteDoc.class); + if(docs.length < 1) continue; + RouteDoc base = docs[0]; + JSONObject current = new JSONObject(); + JSONObject data = new JSONObject(); + JSONArray tag = new JSONArray(); + String pack = response.getClass().getPackage().getName(); + pack = pack.substring(pack.lastIndexOf('.')+1, pack.length()); + tag.add(pack); + data.put("tags", tag); + + + current.put(route.type().toString().toLowerCase(), data); + + paths.put(base.path(), current); + } + + result.put("paths", paths); + + return result; + } + + private E getField(Class clazz, Object instance, String name) throws Exception{ + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + return (E) field.get(instance); + } } diff --git a/src/dev/peerat/backend/routes/Swagger.java b/src/dev/peerat/backend/routes/Swagger.java new file mode 100644 index 0000000..f7f1b7a --- /dev/null +++ b/src/dev/peerat/backend/routes/Swagger.java @@ -0,0 +1,33 @@ +package dev.peerat.backend.routes; + +import java.util.regex.Matcher; + +import dev.peerat.backend.bonus.extract.RouteExtracter; +import dev.peerat.framework.Context; +import dev.peerat.framework.HttpReader; +import dev.peerat.framework.HttpWriter; +import dev.peerat.framework.Response; +import dev.peerat.framework.Route; + +public class Swagger implements Response{ + + private String json; + + public Swagger(RouteExtracter extracter, String host){ + try{ + this.json = extracter.swagger(host).toJSONString(); + }catch(Exception e){ + e.printStackTrace(); + json = "{}"; + } + } + + @Route(path = "^/swagger$") + public void exec(Matcher matcher, Context context, HttpReader reader, HttpWriter writer) throws Exception { + context.response(200); + writer.write(json); + } + + + +}