Compare commits
3 commits
Author | SHA1 | Date | |
---|---|---|---|
|
c0e0e7bfde | ||
|
80eeb13f30 | ||
|
4707e80617 |
18 changed files with 385 additions and 24 deletions
|
@ -5,6 +5,13 @@
|
|||
<classpathentry exported="true" kind="lib" path="jose4j-0.9.3.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="password4j-1.6.3.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="slf4j-api-2.0.6.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="C:/Users/jeffc/eclipse-workspace/peer-at-code-framework/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"/>
|
||||
</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.
|
@ -26,7 +26,7 @@ public class Client<U extends User> extends Thread{
|
|||
reader.readHeaders();
|
||||
|
||||
RequestType type = RequestType.valueOf(headers[0]);
|
||||
context = new Context(type, headers[1], isLogin(router, type, reader), writer, router.getDefaultHeaders(type));
|
||||
context = new Context(type, headers[1], isLogin(type, reader), writer, router.getDefaultHeaders(type));
|
||||
router.exec(context, reader, writer);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
@ -44,12 +44,12 @@ public class Client<U extends User> extends Thread{
|
|||
if(context != null) logger.setValue(context);
|
||||
}
|
||||
|
||||
private User isLogin(Router<U> router, RequestType type, HttpReader reader) throws InvalidJwtException{
|
||||
private User isLogin(RequestType type, HttpReader reader) throws InvalidJwtException{
|
||||
String auth = reader.getHeader("Authorization");
|
||||
if(auth == null) return null;
|
||||
auth = auth.substring(7);
|
||||
try{
|
||||
return this.router.getUser(auth);
|
||||
return router.getUser(auth);
|
||||
}catch(InvalidJwtException e){
|
||||
try{
|
||||
writer.response(401, router.getDefaultHeaders(type));
|
||||
|
|
|
@ -39,6 +39,11 @@ public class HttpReader{
|
|||
this.reader = origin.reader;
|
||||
}
|
||||
|
||||
HttpReader(InputStream in){
|
||||
this.in = in;
|
||||
this.reader = new BufferedReader(new InputStreamReader(in));
|
||||
}
|
||||
|
||||
public boolean isClosed(){
|
||||
return this.socket.isClosed();
|
||||
}
|
||||
|
@ -82,7 +87,7 @@ public class HttpReader{
|
|||
}
|
||||
|
||||
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
|
||||
char[] content = new char[length];
|
||||
read(content);
|
||||
|
|
|
@ -21,6 +21,8 @@ public class HttpWriter{
|
|||
this.out = origin.out;
|
||||
this.writer = origin.writer;
|
||||
}
|
||||
|
||||
public HttpWriter(){}
|
||||
|
||||
public void write(byte[] buffer) throws IOException{
|
||||
this.out.write(buffer);
|
||||
|
@ -114,6 +116,7 @@ public class HttpWriter{
|
|||
|
||||
private static String codeMessage(int code){
|
||||
if(code == 100) return " Continue";
|
||||
if(code == 101) return " Switching Protocols";
|
||||
if(code >> 8 == 0) return HEIGHTBITS[code-200];
|
||||
return NINEBITS[code-300];
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public class RouteMapper<U extends User>{
|
|||
matcher = pattern.matcher(path);
|
||||
if(matcher.matches()){
|
||||
if(route.websocket()){
|
||||
switchToWebSocket(reader, writer);
|
||||
switchToWebSocket(reader, context);
|
||||
reader = new WebSocketReader(reader);
|
||||
writer = new WebSocketWriter(writer);
|
||||
if(route.needLogin()){
|
||||
|
@ -75,6 +75,54 @@ public class RouteMapper<U extends User>{
|
|||
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){
|
||||
if(this.calls == null) return;
|
||||
int call = this.calls[index]++;
|
||||
|
@ -106,17 +154,15 @@ public class RouteMapper<U extends User>{
|
|||
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");
|
||||
if (key == null) throw new IllegalArgumentException();
|
||||
|
||||
writer.write("HTTP/1.1 101 Switching Protocols\n");
|
||||
writer.write("Connection: Upgrade\n");
|
||||
writer.write("Upgrade: websocket\n");
|
||||
writer.write("Sec-WebSocket-Accept: " + printBase64Binary(MessageDigest.getInstance("SHA-1")
|
||||
.digest((key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes("UTF-8"))) + "\n");
|
||||
writer.write("\n");
|
||||
writer.flush();
|
||||
|
||||
context.response(101,
|
||||
"Connection: Upgrade",
|
||||
"Upgrade: websocket",
|
||||
"Sec-WebSocket-Accept: "+printBase64Binary(MessageDigest.getInstance("SHA-1")
|
||||
.digest((key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes("UTF-8"))));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.net.ServerSocket;
|
|||
import java.net.Socket;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.net.ssl.SSLServerSocket;
|
||||
|
@ -101,7 +102,16 @@ public class Router<U extends User>{
|
|||
if(this.mappers[context.getType().ordinal()].exec(context, reader, writer)) return;
|
||||
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){
|
||||
System.setProperty("javax.net.ssl.keyStore", keyStore);
|
||||
System.setProperty("javax.net.ssl.keyStorePassword", keyStorePassword);
|
||||
|
@ -133,6 +143,10 @@ public class Router<U extends User>{
|
|||
return this.logger;
|
||||
}
|
||||
|
||||
public void useTomcat(){
|
||||
TomcatServlet.setRouter(this);
|
||||
}
|
||||
|
||||
public void listen(int port, boolean ssl) throws Exception{
|
||||
if (ssl) { // Not needed with the use of a proxy
|
||||
try {
|
||||
|
|
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.Entry;
|
||||
|
||||
import be.jeffcheasey88.peeratcode.parser.Parser;
|
||||
import be.jeffcheasey88.peeratcode.parser.Token;
|
||||
import be.jeffcheasey88.peeratcode.parser.TokenType;
|
||||
import be.jeffcheasey88.peeratcode.parser.state.RedirectStateTree;
|
||||
import be.jeffcheasey88.peeratcode.parser.state.StateTree;
|
||||
import dev.peerat.parser.Parser;
|
||||
import dev.peerat.parser.Token;
|
||||
import dev.peerat.parser.TokenType;
|
||||
import dev.peerat.parser.state.RedirectStateTree;
|
||||
import dev.peerat.parser.state.StateTree;
|
||||
|
||||
public class JsonParser extends Parser<Json>{
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package dev.peerat.framework.utils.json;
|
||||
|
||||
import be.jeffcheasey88.peeratcode.parser.Token;
|
||||
import be.jeffcheasey88.peeratcode.parser.TokenType;
|
||||
import be.jeffcheasey88.peeratcode.parser.Tokenizer;
|
||||
import dev.peerat.parser.Token;
|
||||
import dev.peerat.parser.TokenType;
|
||||
import dev.peerat.parser.Tokenizer;
|
||||
|
||||
public class JsonTokenizer extends Tokenizer{
|
||||
|
||||
|
|
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