http request (without websocket)

This commit is contained in:
jeffcheasey88 2024-01-03 15:23:48 +01:00
parent 4707e80617
commit 80eeb13f30
8 changed files with 248 additions and 30 deletions

View file

@ -7,5 +7,11 @@
<classpathentry exported="true" kind="lib" path="slf4j-api-2.0.6.jar"/> <classpathentry exported="true" kind="lib" path="slf4j-api-2.0.6.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/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/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>

View file

@ -39,9 +39,9 @@ public class HttpReader{
this.reader = origin.reader; this.reader = origin.reader;
} }
HttpReader(InputStream in, BufferedReader reader){ HttpReader(InputStream in){
this.in = in; this.in = in;
this.reader = reader; this.reader = new BufferedReader(new InputStreamReader(in));
} }
public boolean isClosed(){ public boolean isClosed(){
@ -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);

View file

@ -22,10 +22,7 @@ public class HttpWriter{
this.writer = origin.writer; this.writer = origin.writer;
} }
public HttpWriter(OutputStream out, BufferedWriter writer){ public HttpWriter(){}
this.out = out;
this.writer = writer;
}
public void write(byte[] buffer) throws IOException{ public void write(byte[] buffer) throws IOException{
this.out.write(buffer); this.out.write(buffer);
@ -119,6 +116,7 @@ public class HttpWriter{
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];
} }

View file

@ -50,7 +50,7 @@ public class RouteMapper<U extends User>{
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()){
@ -75,6 +75,54 @@ public class RouteMapper<U extends User>{
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]++;
@ -106,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();
} }

View file

@ -5,12 +5,11 @@ import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jose4j.jwa.AlgorithmConstraints.ConstraintType; import org.jose4j.jwa.AlgorithmConstraints.ConstraintType;
import org.jose4j.jwk.RsaJsonWebKey; import org.jose4j.jwk.RsaJsonWebKey;
@ -104,6 +103,15 @@ public class Router<U extends User>{
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);

View file

@ -1,5 +1,8 @@
package dev.peerat.framework; package dev.peerat.framework;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
public class TomcatHttpReader extends HttpReader{ public class TomcatHttpReader extends HttpReader{
@ -7,7 +10,7 @@ public class TomcatHttpReader extends HttpReader{
private HttpServletRequest request; private HttpServletRequest request;
public TomcatHttpReader(HttpServletRequest request) throws Exception{ public TomcatHttpReader(HttpServletRequest request) throws Exception{
super(request.getInputStream(), request.getReader()); super(request.getInputStream());
this.request = request; this.request = request;
} }
@ -21,7 +24,30 @@ public class TomcatHttpReader extends HttpReader{
@Override @Override
public String getHeader(String key){ public String getHeader(String key){
return request.getHeader(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;
}
} }

View file

@ -1,16 +1,22 @@
package dev.peerat.framework; package dev.peerat.framework;
import java.io.BufferedWriter; 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; import javax.servlet.http.HttpServletResponse;
public class TomcatHttpWriter extends HttpWriter{ public class TomcatHttpWriter extends HttpWriter{
private HttpServletResponse response; private HttpServletResponse response;
private List<Output> senders;
public TomcatHttpWriter(HttpServletResponse response) throws Exception{ public TomcatHttpWriter(HttpServletResponse response) throws Exception{
super(response.getOutputStream(), new BufferedWriter(response.getWriter())); super();
this.response = response; this.response = response;
this.senders = new ArrayList<>();
} }
@Override @Override
@ -21,4 +27,44 @@ public class TomcatHttpWriter extends HttpWriter{
response.setHeader(split[0], split[1]); 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;
}
} }

View file

@ -1,6 +1,7 @@
package dev.peerat.framework; package dev.peerat.framework;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import javax.servlet.ServletConfig; import javax.servlet.ServletConfig;
@ -14,11 +15,26 @@ import org.jose4j.jwt.consumer.InvalidJwtException;
public class TomcatServlet extends HttpServlet{ public class TomcatServlet extends HttpServlet{
private static Router<?> router; private static Router<?> router;
private static Locker<TomcatWebsocketContainer> sessions;
static void setRouter(Router<?> router){ static void setRouter(Router<?> router){
TomcatServlet.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 @Override
public void init(ServletConfig config) throws ServletException{ public void init(ServletConfig config) throws ServletException{
try{ try{
@ -33,25 +49,78 @@ public class TomcatServlet extends HttpServlet{
} }
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { 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; Context context = null;
HttpReader reader = null; TomcatHttpReader reader = null;
HttpWriter writer = null; TomcatHttpWriter writer = null;
try{ try{
reader = new TomcatHttpReader(request); reader = new TomcatHttpReader(request);
writer = new TomcatHttpWriter(response); writer = new TomcatHttpWriter(response);
context = new Context(RequestType.GET, request.getPathInfo(), isLogin(router, RequestType.GET, reader, writer), writer); context = new Context(type, request.getPathInfo(), isLogin(router, type, reader, writer), writer, router.getDefaultHeaders(type));
router.exec(context, reader, writer); router.exec(context, reader, writer);
writer.flush(); writer.flush(response.getOutputStream());
writer.close();
}catch(InvalidJwtException e){ }catch(InvalidJwtException e){
}catch(Exception e){ }catch(Exception e){
if(context != null && context.getResponseCode() == 0){ if(context != null && context.getResponseCode() == 0){
try{ try{
context.response(500); context.response(500);
writer.flush();
writer.close();
}catch(Exception ex){} }catch(Exception ex){}
} }
throw new IOException(e);
} }
if(context != null) router.getLogger().setValue(context); if(context != null) router.getLogger().setValue(context);
} }
@ -72,4 +141,23 @@ public class TomcatServlet extends HttpServlet{
} }
} }
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;
}
}
} }