Compare commits
3 commits
Author | SHA1 | Date | |
---|---|---|---|
|
c0e0e7bfde | ||
|
80eeb13f30 | ||
|
4707e80617 |
27 changed files with 438 additions and 291 deletions
15
.classpath
15
.classpath
|
@ -2,9 +2,16 @@
|
||||||
<classpath>
|
<classpath>
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||||
<classpathentry kind="src" path="src"/>
|
<classpathentry kind="src" path="src"/>
|
||||||
<classpathentry exported="true" kind="lib" path="jose4j-0.9.6.jar"/>
|
<classpathentry exported="true" kind="lib" path="jose4j-0.9.3.jar"/>
|
||||||
<classpathentry exported="true" kind="lib" path="password4j-1.8.1.jar"/>
|
<classpathentry exported="true" kind="lib" path="password4j-1.6.3.jar"/>
|
||||||
<classpathentry exported="true" kind="lib" path="slf4j-api-2.0.12.jar"/>
|
<classpathentry exported="true" kind="lib" path="slf4j-api-2.0.6.jar"/>
|
||||||
<classpathentry exported="true" kind="lib" path="PeerAtCodeParser.jar"/>
|
<classpathentry kind="lib" path="C:/Users/jeffc/eclipse-workspace/peer-at-code-framework/javax.servlet-api-4.0.1.jar"/>
|
||||||
|
<classpathentry kind="lib" path="C:/Users/jeffc/eclipse-workspace/PeerAtORM/PeerAtCodeParser.jar"/>
|
||||||
|
<classpathentry kind="lib" path="C:/Users/jeffc/eclipse-workspace/peer-at-code-framework/tomcat-juli-10.1.17.jar"/>
|
||||||
|
<classpathentry kind="lib" path="C:/Users/jeffc/eclipse-workspace/peer-at-code-framework/tomcat-servlet-api-10.1.17.jar"/>
|
||||||
|
<classpathentry kind="lib" path="C:/Users/jeffc/eclipse-workspace/peer-at-code-framework/tomcat-util-10.1.17.jar"/>
|
||||||
|
<classpathentry kind="lib" path="C:/Users/jeffc/eclipse-workspace/peer-at-code-framework/tomcat-websocket-10.1.17.jar"/>
|
||||||
|
<classpathentry kind="lib" path="C:/Users/jeffc/eclipse-workspace/peer-at-code-framework/tomcat-websocket-api-10.1.17.jar"/>
|
||||||
|
<classpathentry kind="lib" path="C:/Users/jeffc/eclipse-workspace/peer-at-code-framework/tomcat-websocket-client-api-10.1.17.jar"/>
|
||||||
<classpathentry kind="output" path="bin"/>
|
<classpathentry kind="output" path="bin"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|
BIN
javax.servlet-api-4.0.1.jar
Normal file
BIN
javax.servlet-api-4.0.1.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
password4j-1.6.3.jar
Normal file
BIN
password4j-1.6.3.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
slf4j-api-2.0.6.jar
Normal file
BIN
slf4j-api-2.0.6.jar
Normal file
Binary file not shown.
|
@ -9,11 +9,13 @@ public class Client<U extends User> extends Thread{
|
||||||
private HttpReader reader;
|
private HttpReader reader;
|
||||||
private HttpWriter writer;
|
private HttpWriter writer;
|
||||||
private Router<U> router;
|
private Router<U> router;
|
||||||
|
private Locker<Context> logger;
|
||||||
|
|
||||||
public Client(Socket socket, Router<U> router) throws Exception{
|
public Client(Socket socket, Router<U> router) throws Exception{
|
||||||
this.reader = new HttpReader(socket);
|
this.reader = new HttpReader(socket);
|
||||||
this.writer = new HttpWriter(socket);
|
this.writer = new HttpWriter(socket);
|
||||||
this.router = router;
|
this.router = router;
|
||||||
|
this.logger = router.getLogger();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -29,20 +31,17 @@ public class Client<U extends User> extends Thread{
|
||||||
writer.flush();
|
writer.flush();
|
||||||
writer.close();
|
writer.close();
|
||||||
}catch(InvalidJwtException e){
|
}catch(InvalidJwtException e){
|
||||||
this.router.getExceptionLogger().setValue(e);
|
}catch(Exception e){
|
||||||
}catch(Throwable e){
|
e.printStackTrace();
|
||||||
this.router.getExceptionLogger().setValue(e);
|
|
||||||
if(context != null && context.getResponseCode() == 0){
|
if(context != null && context.getResponseCode() == 0){
|
||||||
try{
|
try{
|
||||||
context.response(500);
|
context.response(500);
|
||||||
writer.flush();
|
writer.flush();
|
||||||
writer.close();
|
writer.close();
|
||||||
}catch(Exception ex){
|
}catch(Exception ex){}
|
||||||
this.router.getExceptionLogger().setValue(ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(context != null) router.getLogger().setValue(context);
|
if(context != null) logger.setValue(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private User isLogin(RequestType type, HttpReader reader) throws InvalidJwtException{
|
private User isLogin(RequestType type, HttpReader reader) throws InvalidJwtException{
|
||||||
|
@ -50,15 +49,13 @@ public class Client<U extends User> extends Thread{
|
||||||
if(auth == null) return null;
|
if(auth == null) return null;
|
||||||
auth = auth.substring(7);
|
auth = auth.substring(7);
|
||||||
try{
|
try{
|
||||||
return this.router.getUser(auth);
|
return router.getUser(auth);
|
||||||
}catch(InvalidJwtException e){
|
}catch(InvalidJwtException e){
|
||||||
try{
|
try{
|
||||||
writer.response(401, this.router.getDefaultHeaders(type));
|
writer.response(401, router.getDefaultHeaders(type));
|
||||||
writer.flush();
|
writer.flush();
|
||||||
writer.close();
|
writer.close();
|
||||||
}catch(Exception ex){
|
}catch(Exception ex){}
|
||||||
this.router.getExceptionLogger().setValue(ex);
|
|
||||||
}
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,70 +0,0 @@
|
||||||
package dev.peerat.framework;
|
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Parameter;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
|
|
||||||
public class DependencyInjector{
|
|
||||||
|
|
||||||
private Map<String, Object> map;
|
|
||||||
private List<BiFunction<Constructor<?>, Parameter, Object>> builders;
|
|
||||||
private Object[] injections;
|
|
||||||
|
|
||||||
public DependencyInjector(){
|
|
||||||
this.map = new HashMap<>();
|
|
||||||
this.builders = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public DependencyInjector of(String name, Object value){
|
|
||||||
this.map.put(name, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DependencyInjector of(BiFunction<Constructor<?>, Parameter, Object> builder){
|
|
||||||
this.builders.add(builder);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DependencyInjector of(Object... injections){
|
|
||||||
if(this.injections == null){
|
|
||||||
this.injections = injections;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
Object[] copy = new Object[this.injections.length+injections.length];
|
|
||||||
System.arraycopy(this.injections, 0, copy, 0, this.injections.length);
|
|
||||||
System.arraycopy(injections, 0, copy, this.injections.length, injections.length);
|
|
||||||
this.injections = copy;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object applyDependency(Constructor<?> constructor, Parameter parameter, Map<Class<?>, Object> cache){
|
|
||||||
Injection annotation = parameter.getAnnotation(Injection.class);
|
|
||||||
if(annotation != null){
|
|
||||||
Object result = this.map.get(annotation.value());
|
|
||||||
if(result == null) throw new IllegalArgumentException("No depdency named "+annotation.value()+" ("+this.map.keySet()+") in constructor "+constructor);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
for(BiFunction<Constructor<?>, Parameter, Object> function : builders){
|
|
||||||
Object result = function.apply(constructor, parameter);
|
|
||||||
if(result != null) return result;
|
|
||||||
}
|
|
||||||
if(this.injections == null) return null;
|
|
||||||
Class<?> type = parameter.getType();
|
|
||||||
Object result = null;
|
|
||||||
for(Object injection : injections){
|
|
||||||
if(type.isAssignableFrom(injection.getClass())){
|
|
||||||
if(cache.containsKey(type)){
|
|
||||||
throw new IllegalArgumentException("Double dependency for type "+type+", can be in constructor "+constructor);
|
|
||||||
}else{
|
|
||||||
cache.put(type, injection);
|
|
||||||
result = injection;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,7 +9,6 @@ import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -40,6 +39,11 @@ public class HttpReader{
|
||||||
this.reader = origin.reader;
|
this.reader = origin.reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HttpReader(InputStream in){
|
||||||
|
this.in = in;
|
||||||
|
this.reader = new BufferedReader(new InputStreamReader(in));
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isClosed(){
|
public boolean isClosed(){
|
||||||
return this.socket.isClosed();
|
return this.socket.isClosed();
|
||||||
}
|
}
|
||||||
|
@ -53,10 +57,6 @@ public class HttpReader{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getHeaders(){
|
|
||||||
return this.headers.keySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getHeader(String key){
|
public String getHeader(String key){
|
||||||
return this.headers.get(key.toLowerCase());
|
return this.headers.get(key.toLowerCase());
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ public class HttpReader{
|
||||||
}
|
}
|
||||||
|
|
||||||
public <J extends Json> J readJson() throws Exception{
|
public <J extends Json> J readJson() throws Exception{
|
||||||
int length = Integer.parseInt(this.headers.get("content-length"));
|
int length = Integer.parseInt(getHeader("content-length"));
|
||||||
//to limit
|
//to limit
|
||||||
char[] content = new char[length];
|
char[] content = new char[length];
|
||||||
read(content);
|
read(content);
|
||||||
|
|
|
@ -21,6 +21,8 @@ public class HttpWriter{
|
||||||
this.out = origin.out;
|
this.out = origin.out;
|
||||||
this.writer = origin.writer;
|
this.writer = origin.writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HttpWriter(){}
|
||||||
|
|
||||||
public void write(byte[] buffer) throws IOException{
|
public void write(byte[] buffer) throws IOException{
|
||||||
this.out.write(buffer);
|
this.out.write(buffer);
|
||||||
|
@ -46,7 +48,7 @@ public class HttpWriter{
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String[] HEIGHTBITS = new String[27];
|
private static String[] HEIGHTBITS = new String[9];
|
||||||
private static String[] NINEBITS = new String[212];
|
private static String[] NINEBITS = new String[212];
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -59,7 +61,6 @@ public class HttpWriter{
|
||||||
HEIGHTBITS[6] = " Partial Content";
|
HEIGHTBITS[6] = " Partial Content";
|
||||||
HEIGHTBITS[7] = " Mutli-Status";
|
HEIGHTBITS[7] = " Mutli-Status";
|
||||||
HEIGHTBITS[8] = " Already Reported";
|
HEIGHTBITS[8] = " Already Reported";
|
||||||
HEIGHTBITS[26] = " IM Used";
|
|
||||||
|
|
||||||
NINEBITS[0] = " Multiple Choices";
|
NINEBITS[0] = " Multiple Choices";
|
||||||
NINEBITS[1] = " Moved Permanently";
|
NINEBITS[1] = " Moved Permanently";
|
||||||
|
@ -89,8 +90,6 @@ public class HttpWriter{
|
||||||
NINEBITS[116] = " Range Not Satisfiable";
|
NINEBITS[116] = " Range Not Satisfiable";
|
||||||
NINEBITS[117] = " Expectation Failed";
|
NINEBITS[117] = " Expectation Failed";
|
||||||
NINEBITS[118] = " I'm a Teapot";
|
NINEBITS[118] = " I'm a Teapot";
|
||||||
NINEBITS[119] = " Insufficient Space On Resource";
|
|
||||||
NINEBITS[120] = " Method Failure";
|
|
||||||
NINEBITS[121] = " Misdirected Request";
|
NINEBITS[121] = " Misdirected Request";
|
||||||
NINEBITS[122] = " Unprocessable Content";
|
NINEBITS[122] = " Unprocessable Content";
|
||||||
NINEBITS[123] = " Locked";
|
NINEBITS[123] = " Locked";
|
||||||
|
@ -111,13 +110,13 @@ public class HttpWriter{
|
||||||
NINEBITS[206] = " Variant Also Negotiates";
|
NINEBITS[206] = " Variant Also Negotiates";
|
||||||
NINEBITS[207] = " Insufficient Storage";
|
NINEBITS[207] = " Insufficient Storage";
|
||||||
NINEBITS[208] = " Loop Detected";
|
NINEBITS[208] = " Loop Detected";
|
||||||
NINEBITS[209] = " Bandwith Limit Exceeded";
|
|
||||||
NINEBITS[210] = " Not Extended";
|
NINEBITS[210] = " Not Extended";
|
||||||
NINEBITS[211] = " Network Authentication Required";
|
NINEBITS[211] = " Network Authentication Required";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String codeMessage(int code){
|
private static String codeMessage(int code){
|
||||||
if(code == 100) return " Continue";
|
if(code == 100) return " Continue";
|
||||||
|
if(code == 101) return " Switching Protocols";
|
||||||
if(code >> 8 == 0) return HEIGHTBITS[code-200];
|
if(code >> 8 == 0) return HEIGHTBITS[code-200];
|
||||||
return NINEBITS[code-300];
|
return NINEBITS[code-300];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
package dev.peerat.framework;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
public @interface Injection{
|
|
||||||
|
|
||||||
String value();
|
|
||||||
|
|
||||||
}
|
|
|
@ -8,6 +8,8 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import dev.peerat.framework.Locker.Key;
|
||||||
|
|
||||||
public class Locker<V>{
|
public class Locker<V>{
|
||||||
|
|
||||||
private Map<Key, BlockingQueue<V>> map;
|
private Map<Key, BlockingQueue<V>> map;
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
package dev.peerat.framework;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
|
|
||||||
public interface RouteInterceptor{
|
|
||||||
|
|
||||||
boolean intercept(Matcher matcher, Context context, HttpReader reader, HttpWriter writer, Method method);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,8 +1,6 @@
|
||||||
package dev.peerat.framework;
|
package dev.peerat.framework;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.util.List;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -13,7 +11,6 @@ public class RouteMapper<U extends User>{
|
||||||
private Router<U> router;
|
private Router<U> router;
|
||||||
|
|
||||||
private Response[] responses;
|
private Response[] responses;
|
||||||
private Method[] methods;
|
|
||||||
private Route[] routes;
|
private Route[] routes;
|
||||||
private Pattern[] patterns;
|
private Pattern[] patterns;
|
||||||
private int[] calls;
|
private int[] calls;
|
||||||
|
@ -22,15 +19,13 @@ public class RouteMapper<U extends User>{
|
||||||
public RouteMapper(Router<U> router){
|
public RouteMapper(Router<U> router){
|
||||||
this.router = router;
|
this.router = router;
|
||||||
this.responses = new Response[0];
|
this.responses = new Response[0];
|
||||||
this.methods = new Method[0];
|
|
||||||
this.routes = new Route[0];
|
this.routes = new Route[0];
|
||||||
this.patterns = new Pattern[0];
|
this.patterns = new Pattern[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void register(Response response, Method method, Route route, Pattern pattern){
|
public void register(Response response, Route route, Pattern pattern){
|
||||||
int length = responses.length+1;
|
int length = responses.length+1;
|
||||||
this.responses = addElement(responses, new Response[length], response);
|
this.responses = addElement(responses, new Response[length], response);
|
||||||
this.methods = addElement(methods, new Method[length], method);
|
|
||||||
this.routes = addElement(routes, new Route[length], route);
|
this.routes = addElement(routes, new Route[length], route);
|
||||||
this.patterns = addElement(patterns, new Pattern[length], pattern);
|
this.patterns = addElement(patterns, new Pattern[length], pattern);
|
||||||
if(this.calls != null) this.calls = new int[length];
|
if(this.calls != null) this.calls = new int[length];
|
||||||
|
@ -41,21 +36,21 @@ public class RouteMapper<U extends User>{
|
||||||
this.dif = 2;
|
this.dif = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean exec(Context context, HttpReader reader, HttpWriter writer, List<RouteInterceptor> interceptors) throws Exception{
|
public boolean exec(Context context, HttpReader reader, HttpWriter writer) throws Exception{
|
||||||
Response response = null;
|
Response result = null;
|
||||||
Method method = null;
|
|
||||||
Matcher matcher = null;
|
Matcher matcher = null;
|
||||||
|
|
||||||
String path = context.getPath();
|
String path = context.getPath();
|
||||||
|
|
||||||
synchronized(responses){
|
synchronized(responses){
|
||||||
for(int i = 0; i < responses.length; i++){
|
for(int i = 0; i < responses.length; i++){
|
||||||
|
Response response = responses[i];
|
||||||
Route route = routes[i];
|
Route route = routes[i];
|
||||||
Pattern pattern = patterns[i];
|
Pattern pattern = patterns[i];
|
||||||
matcher = pattern.matcher(path);
|
matcher = pattern.matcher(path);
|
||||||
if(matcher.matches()){
|
if(matcher.matches()){
|
||||||
if(route.websocket()){
|
if(route.websocket()){
|
||||||
switchToWebSocket(reader, writer);
|
switchToWebSocket(reader, context);
|
||||||
reader = new WebSocketReader(reader);
|
reader = new WebSocketReader(reader);
|
||||||
writer = new WebSocketWriter(writer);
|
writer = new WebSocketWriter(writer);
|
||||||
if(route.needLogin()){
|
if(route.needLogin()){
|
||||||
|
@ -67,23 +62,67 @@ public class RouteMapper<U extends User>{
|
||||||
writer.response(401, router.getDefaultHeaders(context.getType()));
|
writer.response(401, router.getDefaultHeaders(context.getType()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
response = responses[i];
|
|
||||||
method = methods[i];
|
|
||||||
order(i);
|
order(i);
|
||||||
|
result = response;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(response != null){
|
if(result != null){
|
||||||
for(RouteInterceptor interceptor : interceptors){
|
result.exec(matcher, context, reader, writer);
|
||||||
if(!interceptor.intercept(matcher, context, reader, writer, method)) return true;
|
|
||||||
}
|
|
||||||
response.exec(matcher, context, reader, writer);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Response execTomcat(Context context, HttpReader reader, HttpWriter writer) throws Exception{
|
||||||
|
Response result = null;
|
||||||
|
Matcher matcher = null;
|
||||||
|
|
||||||
|
String path = context.getPath();
|
||||||
|
|
||||||
|
synchronized(responses){
|
||||||
|
for(int i = 0; i < responses.length; i++){
|
||||||
|
Response response = responses[i];
|
||||||
|
Route route = routes[i];
|
||||||
|
Pattern pattern = patterns[i];
|
||||||
|
matcher = pattern.matcher(path);
|
||||||
|
if(matcher.matches()){
|
||||||
|
if(route.websocket()){
|
||||||
|
switchToWebSocket(reader, context);
|
||||||
|
result = response;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if((!context.isLogged()) && route.needLogin()){
|
||||||
|
writer.response(401, router.getDefaultHeaders(context.getType()));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
order(i);
|
||||||
|
result = response;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher matchTomcat(Context context){
|
||||||
|
Matcher result = null;
|
||||||
|
String path = context.getPath();
|
||||||
|
synchronized(responses){
|
||||||
|
for(int i = 0; i < responses.length; i++){
|
||||||
|
Pattern pattern = patterns[i];
|
||||||
|
Matcher match = pattern.matcher(path);
|
||||||
|
if(match.matches()){
|
||||||
|
result = match;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private void order(int index){
|
private void order(int index){
|
||||||
if(this.calls == null) return;
|
if(this.calls == null) return;
|
||||||
int call = this.calls[index]++;
|
int call = this.calls[index]++;
|
||||||
|
@ -95,7 +134,6 @@ public class RouteMapper<U extends User>{
|
||||||
if(index < 1) return;
|
if(index < 1) return;
|
||||||
if(call > this.calls[index-1]){
|
if(call > this.calls[index-1]){
|
||||||
switchElement(responses, index, index-1);
|
switchElement(responses, index, index-1);
|
||||||
switchElement(methods, index, index-1);
|
|
||||||
switchElement(routes, index, index-1);
|
switchElement(routes, index, index-1);
|
||||||
switchElement(patterns, index, index-1);
|
switchElement(patterns, index, index-1);
|
||||||
|
|
||||||
|
@ -116,17 +154,15 @@ public class RouteMapper<U extends User>{
|
||||||
array[after] = tmp;
|
array[after] = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void switchToWebSocket(HttpReader reader, HttpWriter writer) throws Exception{
|
private void switchToWebSocket(HttpReader reader, Context context) throws Exception{
|
||||||
String key = reader.getHeader("Sec-WebSocket-Key");
|
String key = reader.getHeader("Sec-WebSocket-Key");
|
||||||
if (key == null) throw new IllegalArgumentException();
|
if (key == null) throw new IllegalArgumentException();
|
||||||
|
|
||||||
writer.write("HTTP/1.1 101 Switching Protocols\n");
|
context.response(101,
|
||||||
writer.write("Connection: Upgrade\n");
|
"Connection: Upgrade",
|
||||||
writer.write("Upgrade: websocket\n");
|
"Upgrade: websocket",
|
||||||
writer.write("Sec-WebSocket-Accept: " + printBase64Binary(MessageDigest.getInstance("SHA-1")
|
"Sec-WebSocket-Accept: "+printBase64Binary(MessageDigest.getInstance("SHA-1")
|
||||||
.digest((key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes("UTF-8"))) + "\n");
|
.digest((key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes("UTF-8"))));
|
||||||
writer.write("\n");
|
|
||||||
writer.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,17 @@
|
||||||
package dev.peerat.framework;
|
package dev.peerat.framework;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Parameter;
|
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.security.Key;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.net.ssl.SSLServerSocket;
|
import javax.net.ssl.SSLServerSocket;
|
||||||
import javax.net.ssl.SSLServerSocketFactory;
|
import javax.net.ssl.SSLServerSocketFactory;
|
||||||
|
|
||||||
import org.jose4j.jwa.AlgorithmConstraints.ConstraintType;
|
import org.jose4j.jwa.AlgorithmConstraints.ConstraintType;
|
||||||
import org.jose4j.jwk.JsonWebKey.OutputControlLevel;
|
|
||||||
import org.jose4j.jwk.RsaJsonWebKey;
|
import org.jose4j.jwk.RsaJsonWebKey;
|
||||||
import org.jose4j.jwk.RsaJwkGenerator;
|
import org.jose4j.jwk.RsaJwkGenerator;
|
||||||
import org.jose4j.jws.AlgorithmIdentifiers;
|
import org.jose4j.jws.AlgorithmIdentifiers;
|
||||||
|
@ -39,9 +29,7 @@ public class Router<U extends User>{
|
||||||
}
|
}
|
||||||
|
|
||||||
private Locker<Context> logger;
|
private Locker<Context> logger;
|
||||||
private Locker<Throwable> exceptions;
|
|
||||||
private RouteMapper<U>[] mappers;
|
private RouteMapper<U>[] mappers;
|
||||||
private List<RouteInterceptor> interceptors;
|
|
||||||
private Response noFileFound;
|
private Response noFileFound;
|
||||||
private RsaJsonWebKey rsaJsonWebKey;
|
private RsaJsonWebKey rsaJsonWebKey;
|
||||||
private JwtConsumer jwtConsumer;
|
private JwtConsumer jwtConsumer;
|
||||||
|
@ -50,44 +38,28 @@ public class Router<U extends User>{
|
||||||
private String[][] headers;
|
private String[][] headers;
|
||||||
private ServerSocket serverSocket;
|
private ServerSocket serverSocket;
|
||||||
|
|
||||||
public Router(){
|
public Router() throws Exception{
|
||||||
this.logger = new Locker<>();
|
this.logger = new Locker<>();
|
||||||
this.exceptions = new Locker<>();
|
|
||||||
int types = RequestType.values().length;
|
int types = RequestType.values().length;
|
||||||
this.mappers = new RouteMapper[types];
|
this.mappers = new RouteMapper[types];
|
||||||
this.interceptors = new ArrayList<>();
|
|
||||||
for(RequestType type : RequestType.values()) this.mappers[type.ordinal()] = new RouteMapper<>(this);
|
for(RequestType type : RequestType.values()) this.mappers[type.ordinal()] = new RouteMapper<>(this);
|
||||||
|
this.rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
|
||||||
this.headers = new String[types][0];
|
this.headers = new String[types][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public Router<U> configureJwt(Consumer<JwtConsumerBuilder> consumer, Consumer<JwtClaims> claims, Function<JwtClaims, U> userCreator) throws Exception{
|
public Router<U> configureJwt(Consumer<JwtConsumerBuilder> consumer, Consumer<JwtClaims> claims, Function<JwtClaims, U> userCreator){
|
||||||
this.rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
|
|
||||||
configureJwtWithKey(consumer, claims, userCreator, this.rsaJsonWebKey.getKey());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Router<U> configureJwt(Consumer<JwtConsumerBuilder> consumer, Consumer<JwtClaims> claims, Function<JwtClaims, U> userCreator, Map<String, Object> keyParams) throws Exception{
|
|
||||||
this.rsaJsonWebKey = new RsaJsonWebKey(keyParams);
|
|
||||||
configureJwtWithKey(consumer, claims, userCreator, this.rsaJsonWebKey.getKey());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureJwtWithKey(Consumer<JwtConsumerBuilder> consumer, Consumer<JwtClaims> claims, Function<JwtClaims, U> userCreator, Key key) throws Exception{
|
|
||||||
JwtConsumerBuilder builder = new JwtConsumerBuilder()
|
JwtConsumerBuilder builder = new JwtConsumerBuilder()
|
||||||
.setRequireExpirationTime()
|
.setRequireExpirationTime()
|
||||||
.setAllowedClockSkewInSeconds(30)
|
.setAllowedClockSkewInSeconds(30)
|
||||||
.setVerificationKey(key)
|
.setVerificationKey(rsaJsonWebKey.getKey())
|
||||||
.setJwsAlgorithmConstraints(ConstraintType.PERMIT, AlgorithmIdentifiers.RSA_USING_SHA256);
|
.setJwsAlgorithmConstraints(ConstraintType.PERMIT, AlgorithmIdentifiers.RSA_USING_SHA256);
|
||||||
|
|
||||||
consumer.accept(builder);
|
consumer.accept(builder);
|
||||||
|
|
||||||
this.jwtConsumer = builder.build();
|
this.jwtConsumer = builder.build();
|
||||||
this.claims = claims;
|
this.claims = claims;
|
||||||
this.userCreator = userCreator;
|
this.userCreator = userCreator;
|
||||||
}
|
return this;
|
||||||
|
|
||||||
public Map<String, Object> exportJwtKey(){
|
|
||||||
return this.rsaJsonWebKey.toParams(OutputControlLevel.INCLUDE_PRIVATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Router<U> addDefaultHeaders(RequestType type, String... headers){
|
public Router<U> addDefaultHeaders(RequestType type, String... headers){
|
||||||
|
@ -105,84 +77,18 @@ public class Router<U extends User>{
|
||||||
Response.class.getDeclaredMethods()[0].getParameterTypes());
|
Response.class.getDeclaredMethods()[0].getParameterTypes());
|
||||||
Route route = method.getAnnotation(Route.class);
|
Route route = method.getAnnotation(Route.class);
|
||||||
|
|
||||||
this.mappers[route.type().ordinal()].register(response, method, route, Pattern.compile(route.path()));
|
this.mappers[route.type().ordinal()].register(response, route, Pattern.compile(route.path()));
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
throw new IllegalArgumentException(e);
|
throw new IllegalArgumentException(e);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Router<U> registerPackages(Object... injections){
|
|
||||||
return registerPackages(new DependencyInjector().of(injections));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Router<U> registerPackages(DependencyInjector injector){
|
|
||||||
String clazz = Thread.currentThread().getStackTrace()[2].getClassName();
|
|
||||||
String pack = clazz.substring(0, clazz.lastIndexOf('.'));
|
|
||||||
return registerPackages(pack, injector);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Router<U> registerPackages(String name, Object... injections){
|
|
||||||
return registerPackages(name, new DependencyInjector().of(injections));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Router<U> registerPackages(String name, DependencyInjector injector){
|
|
||||||
InputStream stream = ClassLoader.getSystemClassLoader().getResourceAsStream(name.replace(".", "/"));
|
|
||||||
try{
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
|
|
||||||
String line;
|
|
||||||
Map<Class<?>, Object> cache = new HashMap<>();
|
|
||||||
while((line = reader.readLine()) != null){
|
|
||||||
if(line.endsWith(".class")){
|
|
||||||
Class<?> clazz = Class.forName(name+"."+line.substring(0, line.lastIndexOf('.')));
|
|
||||||
if(Response.class.isAssignableFrom(clazz)){
|
|
||||||
if(clazz.equals(Response.class)) continue;
|
|
||||||
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
|
|
||||||
if(constructors.length != 1) continue;
|
|
||||||
injectDependencies(constructors[0], cache, injector);
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
registerPackages(name+"."+line, injector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reader.close();
|
|
||||||
}catch(Exception e){
|
|
||||||
System.err.println("Failed to read "+name);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void injectDependencies(Constructor<?> constructor, Map<Class<?>, Object> cache, DependencyInjector injector){
|
|
||||||
Parameter[] parameters = constructor.getParameters();
|
|
||||||
Object[] injections = new Object[parameters.length];
|
|
||||||
for(int i = 0; i < parameters.length; i++){
|
|
||||||
Parameter parameter = parameters[i];
|
|
||||||
Class<?> type = parameter.getType();
|
|
||||||
Object dependency = cache.get(type);
|
|
||||||
if(dependency != null) injections[i] = dependency;
|
|
||||||
else if((injections[i] = injector.applyDependency(constructor, parameter, cache)) == null) throw new IllegalArgumentException("No dependency for type "+type+" in constructor "+constructor);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Response response = (Response) constructor.newInstance(injections);
|
|
||||||
register(response);
|
|
||||||
System.out.println("registerd "+response.getClass());
|
|
||||||
} catch (Exception e){
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Router<U> setDefault(Response response){
|
public Router<U> setDefault(Response response){
|
||||||
this.noFileFound = response;
|
this.noFileFound = response;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Router<U> addInterceptor(RouteInterceptor interceptor){
|
|
||||||
this.interceptors.add(interceptor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Router<U> activeReOrdering(){
|
public Router<U> activeReOrdering(){
|
||||||
for(RouteMapper<?> mapper : this.mappers) mapper.activeReOrdering();
|
for(RouteMapper<?> mapper : this.mappers) mapper.activeReOrdering();
|
||||||
return this;
|
return this;
|
||||||
|
@ -193,10 +99,19 @@ public class Router<U extends User>{
|
||||||
}
|
}
|
||||||
|
|
||||||
void exec(Context context, HttpReader reader, HttpWriter writer) throws Exception{
|
void exec(Context context, HttpReader reader, HttpWriter writer) throws Exception{
|
||||||
if(this.mappers[context.getType().ordinal()].exec(context, reader, writer, this.interceptors)) return;
|
if(this.mappers[context.getType().ordinal()].exec(context, reader, writer)) return;
|
||||||
if(noFileFound != null) noFileFound.exec(null, context, reader, writer);
|
if(noFileFound != null) noFileFound.exec(null, context, reader, writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Response execTomcat(Context context, HttpReader reader, HttpWriter writer) throws Exception{
|
||||||
|
Response result = this.mappers[context.getType().ordinal()].execTomcat(context, reader, writer);
|
||||||
|
return result != null ? result : noFileFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher matchTomcat(Context context){
|
||||||
|
return this.mappers[context.getType().ordinal()].matchTomcat(context);
|
||||||
|
}
|
||||||
|
|
||||||
public Router<U> configureSSL(String keyStore, String keyStorePassword){
|
public Router<U> configureSSL(String keyStore, String keyStorePassword){
|
||||||
System.setProperty("javax.net.ssl.keyStore", keyStore);
|
System.setProperty("javax.net.ssl.keyStore", keyStore);
|
||||||
System.setProperty("javax.net.ssl.keyStorePassword", keyStorePassword);
|
System.setProperty("javax.net.ssl.keyStorePassword", keyStorePassword);
|
||||||
|
@ -228,8 +143,8 @@ public class Router<U extends User>{
|
||||||
return this.logger;
|
return this.logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Locker<Throwable> getExceptionLogger(){
|
public void useTomcat(){
|
||||||
return this.exceptions;
|
TomcatServlet.setRouter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void listen(int port, boolean ssl) throws Exception{
|
public void listen(int port, boolean ssl) throws Exception{
|
||||||
|
|
53
src/dev/peerat/framework/TomcatHttpReader.java
Normal file
53
src/dev/peerat/framework/TomcatHttpReader.java
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
package dev.peerat.framework;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
public class TomcatHttpReader extends HttpReader{
|
||||||
|
|
||||||
|
private HttpServletRequest request;
|
||||||
|
|
||||||
|
public TomcatHttpReader(HttpServletRequest request) throws Exception{
|
||||||
|
super(request.getInputStream());
|
||||||
|
this.request = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isClosed(){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void readHeaders() throws Exception{}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHeader(String key){
|
||||||
|
String result;
|
||||||
|
result = request.getHeader(key);
|
||||||
|
if(result != null) return result;
|
||||||
|
result = request.getHeader(key.toLowerCase());
|
||||||
|
if(result != null) return result;
|
||||||
|
result = request.getHeader(key.toUpperCase());
|
||||||
|
if(result != null) return result;
|
||||||
|
result = request.getHeader(firstUpper(key.toLowerCase()));
|
||||||
|
if(result != null) return result;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String firstUpper(String value){
|
||||||
|
boolean beUpper = true;
|
||||||
|
String result = "";
|
||||||
|
for(char c : value.toCharArray()){
|
||||||
|
if(beUpper){
|
||||||
|
result+=Character.toUpperCase(c);
|
||||||
|
beUpper = false;
|
||||||
|
}else if(c == '-'){
|
||||||
|
beUpper = true;
|
||||||
|
result+='-';
|
||||||
|
}else result+=c;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
70
src/dev/peerat/framework/TomcatHttpWriter.java
Normal file
70
src/dev/peerat/framework/TomcatHttpWriter.java
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package dev.peerat.framework;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
public class TomcatHttpWriter extends HttpWriter{
|
||||||
|
|
||||||
|
private HttpServletResponse response;
|
||||||
|
private List<Output> senders;
|
||||||
|
|
||||||
|
public TomcatHttpWriter(HttpServletResponse response) throws Exception{
|
||||||
|
super();
|
||||||
|
this.response = response;
|
||||||
|
this.senders = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void response(int code, String... headers) throws Exception {
|
||||||
|
response.setStatus(code);
|
||||||
|
for(String header : headers){
|
||||||
|
String[] split = header.split("\\s*:\\s*");
|
||||||
|
response.setHeader(split[0], split[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(String message) throws IOException {
|
||||||
|
this.senders.add((out) -> {
|
||||||
|
PrintWriter writer = new PrintWriter(out);
|
||||||
|
writer.write(message);
|
||||||
|
writer.flush();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] buffer) throws IOException{
|
||||||
|
this.senders.add((out) -> {
|
||||||
|
out.write(buffer);
|
||||||
|
out.flush();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flush() throws IOException{
|
||||||
|
if(out == null) return;
|
||||||
|
flush(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OutputStream out;
|
||||||
|
|
||||||
|
public void free(OutputStream out){
|
||||||
|
this.out = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush(OutputStream out) throws IOException{
|
||||||
|
for(Output sender : senders) sender.accept(out);
|
||||||
|
senders.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static interface Output{
|
||||||
|
|
||||||
|
void accept(OutputStream out) throws IOException;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
163
src/dev/peerat/framework/TomcatServlet.java
Normal file
163
src/dev/peerat/framework/TomcatServlet.java
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
package dev.peerat.framework;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import javax.servlet.ServletConfig;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.jose4j.jwt.consumer.InvalidJwtException;
|
||||||
|
|
||||||
|
public class TomcatServlet extends HttpServlet{
|
||||||
|
|
||||||
|
private static Router<?> router;
|
||||||
|
private static Locker<TomcatWebsocketContainer> sessions;
|
||||||
|
|
||||||
|
static void setRouter(Router<?> router){
|
||||||
|
TomcatServlet.router = router;
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
sessions = new Locker<>();
|
||||||
|
sessions.listenAsync((container) -> {
|
||||||
|
try{
|
||||||
|
Thread.sleep(1000);
|
||||||
|
WebSocketWriter writer = new WebSocketWriter(new TomcatHttpWriter(container.getResponse()));
|
||||||
|
writer.write("{\"test\":4}");
|
||||||
|
writer.flush();
|
||||||
|
}catch(Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(ServletConfig config) throws ServletException{
|
||||||
|
try{
|
||||||
|
String value = config.getInitParameter("router");
|
||||||
|
Class<?> clazz = Class.forName(value);
|
||||||
|
for(Method method : clazz.getDeclaredMethods()){
|
||||||
|
if(method.getName().equals("main")) method.invoke(null, new Object[] {null});
|
||||||
|
}
|
||||||
|
}catch(Exception ex){
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||||
|
if(request.getHeader("Sec-WebSocket-Key") != null){
|
||||||
|
Context context = null;
|
||||||
|
TomcatHttpReader reader = null;
|
||||||
|
TomcatHttpWriter writer = null;
|
||||||
|
try{
|
||||||
|
reader = new TomcatHttpReader(request);
|
||||||
|
writer = new TomcatHttpWriter(response);
|
||||||
|
context = new Context(RequestType.GET, request.getPathInfo(), isLogin(router, RequestType.GET, reader, writer), writer, router.getDefaultHeaders(RequestType.GET));
|
||||||
|
Response resp = router.execTomcat(context, reader, writer);
|
||||||
|
OutputStream output = response.getOutputStream();
|
||||||
|
writer.flush(output);
|
||||||
|
writer.free(output);
|
||||||
|
WebSocketReader wreader = new WebSocketReader(reader);
|
||||||
|
sessions.setValue(new TomcatWebsocketContainer(wreader, response));
|
||||||
|
}catch(InvalidJwtException e){
|
||||||
|
}catch(Exception e){
|
||||||
|
response.setHeader("exce", e.getMessage());
|
||||||
|
if(context != null && context.getResponseCode() == 0){
|
||||||
|
try{
|
||||||
|
context.response(500);
|
||||||
|
}catch(Exception ex){}
|
||||||
|
}
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
|
if(context != null) router.getLogger().setValue(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
doIt(RequestType.GET, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doDelete(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||||
|
doIt(RequestType.DELETE, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doHead(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||||
|
doIt(RequestType.HEAD, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doOptions(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||||
|
doIt(RequestType.OPTIONS, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||||
|
doIt(RequestType.POST, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPut(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||||
|
doIt(RequestType.PUT, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doTrace(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||||
|
doIt(RequestType.TRACE, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doIt(RequestType type, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||||
|
Context context = null;
|
||||||
|
TomcatHttpReader reader = null;
|
||||||
|
TomcatHttpWriter writer = null;
|
||||||
|
try{
|
||||||
|
reader = new TomcatHttpReader(request);
|
||||||
|
writer = new TomcatHttpWriter(response);
|
||||||
|
context = new Context(type, request.getPathInfo(), isLogin(router, type, reader, writer), writer, router.getDefaultHeaders(type));
|
||||||
|
router.exec(context, reader, writer);
|
||||||
|
writer.flush(response.getOutputStream());
|
||||||
|
}catch(InvalidJwtException e){
|
||||||
|
}catch(Exception e){
|
||||||
|
if(context != null && context.getResponseCode() == 0){
|
||||||
|
try{
|
||||||
|
context.response(500);
|
||||||
|
}catch(Exception ex){}
|
||||||
|
}
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
|
if(context != null) router.getLogger().setValue(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private User isLogin(Router<?> router, RequestType type, HttpReader reader, HttpWriter writer) throws Exception{
|
||||||
|
String auth = reader.getHeader("Authorization");
|
||||||
|
if(auth == null) return null;
|
||||||
|
auth = auth.substring(7);
|
||||||
|
try{
|
||||||
|
return router.getUser(auth);
|
||||||
|
}catch(InvalidJwtException e){
|
||||||
|
try{
|
||||||
|
writer.response(401, router.getDefaultHeaders(type));
|
||||||
|
writer.flush();
|
||||||
|
writer.close();
|
||||||
|
}catch(Exception ex){}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TomcatWebsocketContainer{
|
||||||
|
|
||||||
|
private WebSocketReader reader;
|
||||||
|
private HttpServletResponse response;
|
||||||
|
|
||||||
|
public TomcatWebsocketContainer(WebSocketReader reader, HttpServletResponse response){
|
||||||
|
this.reader = reader;
|
||||||
|
this.response = response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WebSocketReader getReader(){
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpServletResponse getResponse(){
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,11 +6,11 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import be.jeffcheasey88.peeratcode.parser.Parser;
|
import dev.peerat.parser.Parser;
|
||||||
import be.jeffcheasey88.peeratcode.parser.Token;
|
import dev.peerat.parser.Token;
|
||||||
import be.jeffcheasey88.peeratcode.parser.TokenType;
|
import dev.peerat.parser.TokenType;
|
||||||
import be.jeffcheasey88.peeratcode.parser.state.RedirectStateTree;
|
import dev.peerat.parser.state.RedirectStateTree;
|
||||||
import be.jeffcheasey88.peeratcode.parser.state.StateTree;
|
import dev.peerat.parser.state.StateTree;
|
||||||
|
|
||||||
public class JsonParser extends Parser<Json>{
|
public class JsonParser extends Parser<Json>{
|
||||||
|
|
||||||
|
@ -45,11 +45,7 @@ public class JsonParser extends Parser<Json>{
|
||||||
content.then(new RedirectStateTree<>(base, (global, local) -> global.set(local.get()))).end();
|
content.then(new RedirectStateTree<>(base, (global, local) -> global.set(local.get()))).end();
|
||||||
content.then((validator) -> validator.validate((token) -> token.getType().equals(TokenType.STRING), (bag, token) -> bag.set(token))).end();
|
content.then((validator) -> validator.validate((token) -> token.getType().equals(TokenType.STRING), (bag, token) -> bag.set(token))).end();
|
||||||
content.then((validator) -> validator.validate((token) -> token.getType().equals(TokenType.CHAR), (bag, token) -> bag.set(token))).end();
|
content.then((validator) -> validator.validate((token) -> token.getType().equals(TokenType.CHAR), (bag, token) -> bag.set(token))).end();
|
||||||
StateTree<Json> number = content.then((validator) -> validator.validate((token) -> token.getType().equals(TokenType.NAME), (bag, token) -> bag.set(token)));
|
content.then((validator) -> validator.validate((token) -> token.getType().equals(TokenType.NAME), (bag, token) -> bag.set(token))).end();
|
||||||
number.end();
|
|
||||||
number.then((validator) -> validator.validate((token) -> token.getValue().equals("."), (bag, token) -> bag.set(bag.<Token>get().concat(token))))
|
|
||||||
.then((validator) -> validator.validate((token) -> token.getType().equals(TokenType.NAME), (bag, token) -> bag.set(bag.<Token>get().concat(token))))
|
|
||||||
.end();
|
|
||||||
|
|
||||||
StateTree<Json> mapper = new StateTree<>();
|
StateTree<Json> mapper = new StateTree<>();
|
||||||
StateTree<Json> mapper_key = mapper.then((validator) -> validator.validate((token) -> token.getType().equals(TokenType.STRING), (bag, token) -> {
|
StateTree<Json> mapper_key = mapper.then((validator) -> validator.validate((token) -> token.getType().equals(TokenType.STRING), (bag, token) -> {
|
||||||
|
@ -114,10 +110,10 @@ public class JsonParser extends Parser<Json>{
|
||||||
return Long.parseLong(content);
|
return Long.parseLong(content);
|
||||||
}catch(Exception _){
|
}catch(Exception _){
|
||||||
try {
|
try {
|
||||||
return Double.parseDouble(content);
|
return Boolean.parseBoolean(content);
|
||||||
}catch(Exception __){
|
}catch(Exception __){
|
||||||
try{
|
try{
|
||||||
return Boolean.parseBoolean(content);
|
return Double.parseDouble(content);
|
||||||
}catch(Exception ___){}
|
}catch(Exception ___){}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package dev.peerat.framework.utils.json;
|
package dev.peerat.framework.utils.json;
|
||||||
|
|
||||||
import be.jeffcheasey88.peeratcode.parser.Token;
|
import dev.peerat.parser.Token;
|
||||||
import be.jeffcheasey88.peeratcode.parser.TokenType;
|
import dev.peerat.parser.TokenType;
|
||||||
import be.jeffcheasey88.peeratcode.parser.Tokenizer;
|
import dev.peerat.parser.Tokenizer;
|
||||||
|
|
||||||
public class JsonTokenizer extends Tokenizer{
|
public class JsonTokenizer extends Tokenizer{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void parse(String line){
|
public void parse(String line){
|
||||||
for(int i = 0; i < line.length(); i++){
|
for(int i = 0; i < line.length(); i++){
|
||||||
|
@ -29,22 +29,7 @@ public class JsonTokenizer extends Tokenizer{
|
||||||
for(; j < line.length(); j++){
|
for(; j < line.length(); j++){
|
||||||
c = line.charAt(j);
|
c = line.charAt(j);
|
||||||
if(c == '\\'){
|
if(c == '\\'){
|
||||||
c = line.charAt(++j);
|
buffer+=c+line.charAt(++j);
|
||||||
switch(c){
|
|
||||||
case 'n':
|
|
||||||
buffer+='\n';
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
buffer+='\r';
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
buffer+='\t';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
buffer+=c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if(c == '\"') break;
|
if(c == '\"') break;
|
||||||
buffer+=c;
|
buffer+=c;
|
||||||
|
@ -53,6 +38,21 @@ public class JsonTokenizer extends Tokenizer{
|
||||||
i=j;
|
i=j;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if(c == '\''){
|
||||||
|
String buffer = "";
|
||||||
|
int j = i+1;
|
||||||
|
for(; j < line.length(); j++){
|
||||||
|
c = line.charAt(j);
|
||||||
|
if(c == '\\'){
|
||||||
|
buffer+=c+line.charAt(++j);
|
||||||
|
}
|
||||||
|
if(c == '\'') break;
|
||||||
|
buffer+=c;
|
||||||
|
}
|
||||||
|
getTokens().add(new Token(1, i+1, buffer, TokenType.CHAR));
|
||||||
|
i=j;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
getTokens().add(new Token(1, i+1, ""+c, TokenType.DELIMITER));
|
getTokens().add(new Token(1, i+1, ""+c, TokenType.DELIMITER));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
BIN
tomcat-juli-10.1.17.jar
Normal file
BIN
tomcat-juli-10.1.17.jar
Normal file
Binary file not shown.
BIN
tomcat-servlet-api-10.1.17.jar
Normal file
BIN
tomcat-servlet-api-10.1.17.jar
Normal file
Binary file not shown.
BIN
tomcat-util-10.1.17.jar
Normal file
BIN
tomcat-util-10.1.17.jar
Normal file
Binary file not shown.
BIN
tomcat-websocket-10.1.17.jar
Normal file
BIN
tomcat-websocket-10.1.17.jar
Normal file
Binary file not shown.
BIN
tomcat-websocket-api-10.1.17.jar
Normal file
BIN
tomcat-websocket-api-10.1.17.jar
Normal file
Binary file not shown.
BIN
tomcat-websocket-client-api-10.1.17.jar
Normal file
BIN
tomcat-websocket-client-api-10.1.17.jar
Normal file
Binary file not shown.
Loading…
Add table
Reference in a new issue