Route Documentation

This commit is contained in:
jeffcheasey88 2023-04-18 14:58:58 +02:00
parent 7858752406
commit 3d07623443
19 changed files with 108 additions and 1 deletions

View file

@ -11,6 +11,7 @@ import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLServerSocketFactory;
import be.jeffcheasey88.peeratcode.bonus.discord.Bot; import be.jeffcheasey88.peeratcode.bonus.discord.Bot;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteExtracter;
import be.jeffcheasey88.peeratcode.framework.Client; import be.jeffcheasey88.peeratcode.framework.Client;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpUtil; import be.jeffcheasey88.peeratcode.framework.HttpUtil;
@ -66,7 +67,7 @@ public class Main{
initRoutes(router, config); initRoutes(router, config);
// RouteExtracter extracter = new RouteExtracter(router); // RouteExtracter extracter = new RouteExtracter(router);
// extracter.extract(); // extracter.extractDoc();
startWebServer(config, router); startWebServer(config, router);
} }

View file

@ -0,0 +1,17 @@
package be.jeffcheasey88.peeratcode.bonus.extract;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Repeatable(RouteDocs.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RouteDoc {
String path() default "";
int responseCode();
String responseDescription();
}

View file

@ -0,0 +1,12 @@
package be.jeffcheasey88.peeratcode.bonus.extract;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RouteDocs {
RouteDoc[] value();
}

View file

@ -1,6 +1,7 @@
package be.jeffcheasey88.peeratcode.bonus.extract; package be.jeffcheasey88.peeratcode.bonus.extract;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -30,4 +31,19 @@ public class RouteExtracter {
} }
} }
} }
public void extractDoc() throws Exception{
Field field = Router.class.getDeclaredField("responses");
field.setAccessible(true);
Map<RequestType, Map<Response, Route>> responses = (Map<RequestType, Map<Response, Route>>) field.get(this.router);
for(Map<Response, Route> 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());
}
}
}
}
} }

View file

@ -5,6 +5,7 @@ import java.util.regex.Matcher;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteDoc;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpUtil; import be.jeffcheasey88.peeratcode.framework.HttpUtil;
import be.jeffcheasey88.peeratcode.framework.HttpWriter; import be.jeffcheasey88.peeratcode.framework.HttpWriter;
@ -21,6 +22,9 @@ public class BadgeDetails implements Response {
public BadgeDetails(DatabaseRepository databaseRepo) { public BadgeDetails(DatabaseRepository databaseRepo) {
this.databaseRepo = databaseRepo; this.databaseRepo = databaseRepo;
} }
@RouteDoc(path = "/badge/<id>", responseCode = 200, responseDescription = "JSON contenant les informations du badge")
@RouteDoc(responseCode = 400, responseDescription = "Aucun id donner")
@Route(path = "^\\/badge\\/([0-9]+)$", needLogin = true) @Route(path = "^\\/badge\\/([0-9]+)$", needLogin = true)
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception {

View file

@ -5,6 +5,7 @@ import java.util.regex.Matcher;
import org.json.simple.JSONArray; import org.json.simple.JSONArray;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteDoc;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpUtil; import be.jeffcheasey88.peeratcode.framework.HttpUtil;
import be.jeffcheasey88.peeratcode.framework.HttpWriter; import be.jeffcheasey88.peeratcode.framework.HttpWriter;
@ -23,6 +24,9 @@ public class ChapterElement implements Response {
this.databaseRepo = databaseRepo; this.databaseRepo = databaseRepo;
} }
@RouteDoc(path = "/chapter/<id>", responseCode = 200, responseDescription = "JSON contenant les informations du chapitre demander")
@RouteDoc(responseCode = 400, responseDescription = "Aucun id donner")
@Route(path = "^\\/chapter\\/([0-9]+)$", needLogin = true) @Route(path = "^\\/chapter\\/([0-9]+)$", needLogin = true)
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception{ public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception{
Chapter chapter = databaseRepo.getChapter(Integer.parseInt(matcher.group(1))); Chapter chapter = databaseRepo.getChapter(Integer.parseInt(matcher.group(1)));

View file

@ -6,6 +6,7 @@ import java.util.regex.Matcher;
import org.json.simple.JSONArray; import org.json.simple.JSONArray;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteDoc;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpUtil; import be.jeffcheasey88.peeratcode.framework.HttpUtil;
import be.jeffcheasey88.peeratcode.framework.HttpWriter; import be.jeffcheasey88.peeratcode.framework.HttpWriter;
@ -22,6 +23,9 @@ public class ChapterList implements Response {
public ChapterList(DatabaseRepository databaseRepo) { public ChapterList(DatabaseRepository databaseRepo) {
this.databaseRepo = databaseRepo; this.databaseRepo = databaseRepo;
} }
@RouteDoc(path = "/chapters", responseCode = 200, responseDescription = "JSON contenant les informations des chapitres")
@RouteDoc(responseCode = 400, responseDescription = "Aucun chapitre trouver")
@Route(path = "^\\/chapters$", needLogin = true) @Route(path = "^\\/chapters$", needLogin = true)
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception {

View file

@ -2,6 +2,7 @@ package be.jeffcheasey88.peeratcode.routes;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteDoc;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpWriter; import be.jeffcheasey88.peeratcode.framework.HttpWriter;
import be.jeffcheasey88.peeratcode.framework.Locker; import be.jeffcheasey88.peeratcode.framework.Locker;
@ -24,6 +25,8 @@ public class DynamicLeaderboard extends Leaderboard{
return this.locker; return this.locker;
} }
@RouteDoc(path = "/rleaderboard/{id}", responseCode = 101, responseDescription = "WebSocket")
@Route(path = "^\\/rleaderboard\\/?(\\d+)?$", websocket = true) @Route(path = "^\\/rleaderboard\\/?(\\d+)?$", websocket = true)
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception{ public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception{
Key key = new Key(); Key key = new Key();

View file

@ -7,6 +7,7 @@ import java.util.regex.Matcher;
import org.json.simple.JSONArray; import org.json.simple.JSONArray;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteDoc;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpUtil; import be.jeffcheasey88.peeratcode.framework.HttpUtil;
import be.jeffcheasey88.peeratcode.framework.HttpWriter; import be.jeffcheasey88.peeratcode.framework.HttpWriter;
@ -25,6 +26,8 @@ public class Leaderboard implements Response {
public Leaderboard(DatabaseRepository databaseRepo) { public Leaderboard(DatabaseRepository databaseRepo) {
this.databaseRepo = databaseRepo; this.databaseRepo = databaseRepo;
} }
@RouteDoc(path = "/leaderboard/{id}", responseCode = 200, responseDescription = "JSON contenant le leaderboard")
@Route(path = "^\\/leaderboard\\/?(\\d+)?$") @Route(path = "^\\/leaderboard\\/?(\\d+)?$")
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception {

View file

@ -6,6 +6,7 @@ import java.util.regex.Matcher;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteDoc;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpUtil; import be.jeffcheasey88.peeratcode.framework.HttpUtil;
import be.jeffcheasey88.peeratcode.framework.HttpWriter; import be.jeffcheasey88.peeratcode.framework.HttpWriter;
@ -24,6 +25,10 @@ public class Login implements Response {
this.databaseRepo = databaseRepo; this.databaseRepo = databaseRepo;
this.router = router; this.router = router;
} }
@RouteDoc(path = "/login", responseCode = 200, responseDescription = "L'utilisateur est inscrit")
@RouteDoc(responseCode = 403, responseDescription = "L'utilisateur est connecté")
@RouteDoc(responseCode = 400, responseDescription = "Aucune données fournie / données invalide")
@Route(path = "^\\/login$", type = POST) @Route(path = "^\\/login$", type = POST)
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception {

View file

@ -5,6 +5,7 @@ import java.util.regex.Matcher;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteDoc;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpUtil; import be.jeffcheasey88.peeratcode.framework.HttpUtil;
import be.jeffcheasey88.peeratcode.framework.HttpWriter; import be.jeffcheasey88.peeratcode.framework.HttpWriter;
@ -21,6 +22,9 @@ public class PlayerDetails implements Response {
public PlayerDetails(DatabaseRepository databaseRepo) { public PlayerDetails(DatabaseRepository databaseRepo) {
this.databaseRepo = databaseRepo; this.databaseRepo = databaseRepo;
} }
@RouteDoc(path = "/player/{id}", responseCode = 200, responseDescription = "JSON contenant les informations de l'utilisateur")
@RouteDoc(responseCode = 400, responseDescription = "Utilisateur introuvable dans la base de donnée")
@Route(path = "^\\/player\\/?(.+)?$", needLogin = true) @Route(path = "^\\/player\\/?(.+)?$", needLogin = true)
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception {

View file

@ -4,6 +4,7 @@ import java.util.regex.Matcher;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteDoc;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpUtil; import be.jeffcheasey88.peeratcode.framework.HttpUtil;
import be.jeffcheasey88.peeratcode.framework.HttpWriter; import be.jeffcheasey88.peeratcode.framework.HttpWriter;
@ -21,6 +22,9 @@ public class PuzzleElement implements Response {
public PuzzleElement(DatabaseRepository databaseRepo) { public PuzzleElement(DatabaseRepository databaseRepo) {
this.databaseRepo = databaseRepo; this.databaseRepo = databaseRepo;
} }
@RouteDoc(path = "/puzzle/<id>", responseCode = 200, responseDescription = "JSON contenant les informations du puzzle")
@RouteDoc(responseCode = 400, responseDescription = "puzzle introuvable dans la base de donnée")
@Route(path = "^\\/puzzle\\/([0-9]+)$", needLogin = true) @Route(path = "^\\/puzzle\\/([0-9]+)$", needLogin = true)
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception {

View file

@ -11,6 +11,7 @@ import java.util.regex.Matcher;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteDoc;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpUtil; import be.jeffcheasey88.peeratcode.framework.HttpUtil;
import be.jeffcheasey88.peeratcode.framework.HttpWriter; import be.jeffcheasey88.peeratcode.framework.HttpWriter;
@ -34,6 +35,11 @@ public class PuzzleResponse implements Response {
usersFilesPath = initUsersFilesPath; usersFilesPath = initUsersFilesPath;
this.leaderboard = locker; this.leaderboard = locker;
} }
@RouteDoc(path = "/puzzleResponse/<id>", responseCode = 200, responseDescription = "Bonne réponse, json contenant les points + tries")
@RouteDoc(responseCode = 400, responseDescription = "Pas de réponse")
@RouteDoc(responseCode = 403, responseDescription = "Déjà répondu")
@RouteDoc(responseCode = 406, responseDescription = "Mauvaise réponse")
@Route(path = "^\\/puzzleResponse\\/([0-9]+)$", type = POST, needLogin = true) @Route(path = "^\\/puzzleResponse\\/([0-9]+)$", type = POST, needLogin = true)
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception{ public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception{

View file

@ -9,6 +9,7 @@ import java.util.regex.Matcher;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteDoc;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpUtil; import be.jeffcheasey88.peeratcode.framework.HttpUtil;
import be.jeffcheasey88.peeratcode.framework.HttpWriter; import be.jeffcheasey88.peeratcode.framework.HttpWriter;
@ -29,6 +30,10 @@ public class Register implements Response {
this.router = router; this.router = router;
usersFilesPath = initUsersFilesPath; usersFilesPath = initUsersFilesPath;
} }
@RouteDoc(path = "/register", responseCode = 200, responseDescription = "L'utilisateur est inscrit")
@RouteDoc(responseCode = 403, responseDescription = "L'utilisateur est connecté")
@RouteDoc(responseCode = 400, responseDescription = "Aucune données fournie / données invalide")
@Route(path = "^\\/register$", type = POST) @Route(path = "^\\/register$", type = POST)
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception{ public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception{

View file

@ -2,6 +2,7 @@ package be.jeffcheasey88.peeratcode.routes;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteDoc;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpUtil; import be.jeffcheasey88.peeratcode.framework.HttpUtil;
import be.jeffcheasey88.peeratcode.framework.HttpWriter; import be.jeffcheasey88.peeratcode.framework.HttpWriter;
@ -17,6 +18,9 @@ public class Result implements Response {
public Result(DatabaseRepository repo) { public Result(DatabaseRepository repo) {
this.repo = repo; this.repo = repo;
} }
@RouteDoc(path = "/result/<id>", responseCode = 200, responseDescription = "Le score")
@RouteDoc(responseCode = 425, responseDescription = "Puzzle pas compléter")
@Route(path = "^\\/result\\/(\\d+)$", needLogin = true) @Route(path = "^\\/result\\/(\\d+)$", needLogin = true)
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception {

View file

@ -6,6 +6,7 @@ import java.util.regex.Matcher;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteDoc;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpUtil; import be.jeffcheasey88.peeratcode.framework.HttpUtil;
import be.jeffcheasey88.peeratcode.framework.HttpWriter; import be.jeffcheasey88.peeratcode.framework.HttpWriter;
@ -27,6 +28,9 @@ public class GroupCreate implements Response {
this.locker = locker; this.locker = locker;
} }
@RouteDoc(path = "/groupCreate", responseCode = 200, responseDescription = "Le groupe à été crée")
@RouteDoc(responseCode = 403, responseDescription = "L'utilisateur est déjà dans le groupe / ne peux pas le rejoindre")
@Route(path = "^\\/groupCreate$", type = POST, needLogin = true) @Route(path = "^\\/groupCreate$", type = POST, needLogin = true)
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception{ public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception{
Group group = new Group((JSONObject) HttpUtil.readJson(reader)); Group group = new Group((JSONObject) HttpUtil.readJson(reader));

View file

@ -6,6 +6,7 @@ import java.util.regex.Matcher;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteDoc;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpUtil; import be.jeffcheasey88.peeratcode.framework.HttpUtil;
import be.jeffcheasey88.peeratcode.framework.HttpWriter; import be.jeffcheasey88.peeratcode.framework.HttpWriter;
@ -23,6 +24,9 @@ public class GroupJoin implements Response{
this.repo = repo; this.repo = repo;
} }
@RouteDoc(path = "/groupJoin", responseCode = 200, responseDescription = "L'utilisateur à rejoind le groupe")
@RouteDoc(responseCode = 403, responseDescription = "L'utilisateur est déjà dedans / ne peux pas le rejoindre")
@Route(path = "^\\/groupJoin$", type = POST, needLogin = true) @Route(path = "^\\/groupJoin$", type = POST, needLogin = true)
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception{ public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception{
Group group = new Group((JSONObject) HttpUtil.readJson(reader)); Group group = new Group((JSONObject) HttpUtil.readJson(reader));

View file

@ -4,6 +4,7 @@ import java.util.regex.Matcher;
import org.json.simple.JSONArray; import org.json.simple.JSONArray;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteDoc;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpUtil; import be.jeffcheasey88.peeratcode.framework.HttpUtil;
import be.jeffcheasey88.peeratcode.framework.HttpWriter; import be.jeffcheasey88.peeratcode.framework.HttpWriter;
@ -20,6 +21,8 @@ public class GroupList implements Response {
public GroupList(DatabaseRepository repo) { public GroupList(DatabaseRepository repo) {
this.repo = repo; this.repo = repo;
} }
@RouteDoc(path = "/groups", responseCode = 200, responseDescription = "JSON avec la liste des groups")
@Route(path = "^\\/groups$", needLogin = true) @Route(path = "^\\/groups$", needLogin = true)
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception {

View file

@ -6,6 +6,7 @@ import java.util.regex.Matcher;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import be.jeffcheasey88.peeratcode.bonus.extract.RouteDoc;
import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpReader;
import be.jeffcheasey88.peeratcode.framework.HttpUtil; import be.jeffcheasey88.peeratcode.framework.HttpUtil;
import be.jeffcheasey88.peeratcode.framework.HttpWriter; import be.jeffcheasey88.peeratcode.framework.HttpWriter;
@ -22,6 +23,9 @@ public class GroupQuit implements Response{
public GroupQuit(DatabaseRepository repo){ public GroupQuit(DatabaseRepository repo){
this.repo = repo; this.repo = repo;
} }
@RouteDoc(path = "/groupQuit", responseCode = 200, responseDescription = "L'utilisateur à quitter le groupe")
@RouteDoc(responseCode = 403, responseDescription = "L'utilisateur n'est pas dans le groupe / n'a pas pu le quittez")
@Route(path = "^\\/groupQuit$", type = POST, needLogin = true) @Route(path = "^\\/groupQuit$", type = POST, needLogin = true)
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception{ public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception{