HTTP支持Expect:100-continue
This commit is contained in:
@@ -41,7 +41,7 @@ public class HttpContext extends Context {
|
||||
|
||||
protected final AnyValue rpcAuthenticatorConfig;
|
||||
|
||||
//所有Servlet方法都不需要读取http-header且不存在HttpFilter的情况下,lazyHeaders=true
|
||||
//所有Servlet方法都不需要读取http-header且RestBaseServlet不是自定义HttpServlet且不存在HttpFilter的情况下,lazyHeaders=true
|
||||
protected boolean lazyHeaders; //存在动态改值
|
||||
|
||||
Function<WebSocket, WebSocketWriteIOThread> webSocketWriterIOThreadFunc;
|
||||
|
||||
@@ -315,6 +315,10 @@ public class HttpDispatcherServlet extends DispatcherServlet<String, HttpContext
|
||||
response.finish(200, null);
|
||||
return;
|
||||
}
|
||||
if (request.isExpect()) {
|
||||
response.finish(100, response.getHttpCode(100));
|
||||
return;
|
||||
}
|
||||
if (request.isWebSocket()) {
|
||||
servlet = wsmappings.get(uri);
|
||||
if (servlet == null && this.regxWsArray != null) {
|
||||
|
||||
@@ -67,6 +67,8 @@ public class HttpRequest extends Request<HttpContext> {
|
||||
|
||||
protected static final String KEY_HOST = "Host";
|
||||
|
||||
protected static final String KEY_EXPECT = "Expect";
|
||||
|
||||
public static final String SESSIONID_NAME = "JSESSIONID";
|
||||
|
||||
//---------- header 相关参数 开始 ----------
|
||||
@@ -87,6 +89,8 @@ public class HttpRequest extends Request<HttpContext> {
|
||||
|
||||
private boolean maybews = false; //是否可能是WebSocket
|
||||
|
||||
private boolean expect = false; //是否Expect:100-continue
|
||||
|
||||
protected boolean rpc;
|
||||
|
||||
protected int readState = READ_STATE_ROUTE;
|
||||
@@ -257,6 +261,10 @@ public class HttpRequest extends Request<HttpContext> {
|
||||
return maybews && "Upgrade".equalsIgnoreCase(getHeader("Connection")) && "GET".equalsIgnoreCase(method);
|
||||
}
|
||||
|
||||
protected boolean isExpect() {
|
||||
return expect;
|
||||
}
|
||||
|
||||
protected void setKeepAlive(boolean keepAlive) {
|
||||
this.keepAlive = keepAlive;
|
||||
}
|
||||
@@ -303,6 +311,7 @@ public class HttpRequest extends Request<HttpContext> {
|
||||
this.cookies = httplast.cookies;
|
||||
this.keepAlive = httplast.keepAlive;
|
||||
this.maybews = httplast.maybews;
|
||||
this.expect = httplast.expect;
|
||||
this.rpc = httplast.rpc;
|
||||
this.traceid = httplast.traceid;
|
||||
this.hashid = httplast.hashid;
|
||||
@@ -736,6 +745,12 @@ public class HttpRequest extends Request<HttpContext> {
|
||||
this.maybews = "websocket".equalsIgnoreCase(value);
|
||||
headers.put("Upgrade", value);
|
||||
break;
|
||||
case "Expect":
|
||||
case "expect":
|
||||
value = bytes.toString(true, charset);
|
||||
this.expect = "100-continue".equalsIgnoreCase(value);
|
||||
headers.put("Expect", value);
|
||||
break;
|
||||
case "user-agent":
|
||||
value = bytes.toString(charset);
|
||||
headers.put("User-Agent", value);
|
||||
@@ -824,6 +839,11 @@ public class HttpRequest extends Request<HttpContext> {
|
||||
return KEY_COOKIE;
|
||||
}
|
||||
}
|
||||
} else if (first == 'E' && size == 6) { //Expect
|
||||
if (bs[1] == 'x' && bs[2] == 'p' && bs[3] == 'e'
|
||||
&& bs[4] == 'c' && bs[5] == 't') {
|
||||
return KEY_EXPECT;
|
||||
}
|
||||
}
|
||||
return bytes.toString(latin1, charset);
|
||||
}
|
||||
@@ -844,6 +864,7 @@ public class HttpRequest extends Request<HttpContext> {
|
||||
req.cookies = this.cookies;
|
||||
req.keepAlive = this.keepAlive;
|
||||
req.maybews = this.maybews;
|
||||
req.expect = this.expect;
|
||||
req.rpc = this.rpc;
|
||||
req.traceid = this.traceid;
|
||||
req.hashid = this.hashid;
|
||||
@@ -881,6 +902,7 @@ public class HttpRequest extends Request<HttpContext> {
|
||||
this.cookie = null;
|
||||
this.cookies = null;
|
||||
this.maybews = false;
|
||||
this.expect = false;
|
||||
this.rpc = false;
|
||||
this.readState = READ_STATE_ROUTE;
|
||||
this.currentUserid = CURRUSERID_NIL;
|
||||
|
||||
@@ -227,7 +227,7 @@ public class HttpSimpleRequest implements java.io.Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpSimpleRequest header(String key, JsonConvert convert, Object value) {
|
||||
public HttpSimpleRequest header(String key, TextConvert convert, Object value) {
|
||||
if (value == null) {
|
||||
return this;
|
||||
}
|
||||
@@ -276,7 +276,7 @@ public class HttpSimpleRequest implements java.io.Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpSimpleRequest param(String key, JsonConvert convert, Object value) {
|
||||
public HttpSimpleRequest param(String key, TextConvert convert, Object value) {
|
||||
if (value == null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -1145,9 +1145,6 @@ public final class Rest {
|
||||
if ("init".equals(method.getName())) {
|
||||
continue;
|
||||
}
|
||||
if ("stop".equals(method.getName())) {
|
||||
continue;
|
||||
}
|
||||
if ("destroy".equals(method.getName())) {
|
||||
continue;
|
||||
}
|
||||
@@ -1597,9 +1594,6 @@ public final class Rest {
|
||||
if ("init".equals(method.getName())) {
|
||||
continue;
|
||||
}
|
||||
if ("stop".equals(method.getName())) {
|
||||
continue;
|
||||
}
|
||||
if ("destroy".equals(method.getName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -35,9 +35,9 @@ import org.redkale.util.*;
|
||||
* WebSocketEngine
|
||||
* WebSocketNode
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* WebSocket1 WebSocket2
|
||||
* / \
|
||||
* / \
|
||||
* WebSocket1 WebSocket2
|
||||
*
|
||||
* </pre></blockquote>
|
||||
*
|
||||
@@ -78,13 +78,13 @@ public abstract class WebSocketServlet extends HttpServlet implements Resourcabl
|
||||
//同RestWebSocket.liveinterval
|
||||
protected int liveinterval = DEFAILT_LIVEINTERVAL;
|
||||
|
||||
//同RestWebSocket.wsMaxConns
|
||||
//同RestWebSocket.wsmaxconns
|
||||
protected int wsmaxconns = 0;
|
||||
|
||||
//同RestWebSocket.wsThreads
|
||||
//同RestWebSocket.wsthreads
|
||||
protected int wsthreads = 0;
|
||||
|
||||
//同RestWebSocket.wsMaxBody
|
||||
//同RestWebSocket.wsmaxbody
|
||||
protected int wsmaxbody = 32 * 1024;
|
||||
|
||||
//同RestWebSocket.anyuser
|
||||
|
||||
@@ -106,7 +106,7 @@ public abstract class Sncp {
|
||||
continue;
|
||||
}
|
||||
if (method.getParameterCount() == 1 && method.getParameterTypes()[0] == AnyValue.class) {
|
||||
if (method.getName().equals("init") || method.getName().equals("stop") || method.getName().equals("destroy")) {
|
||||
if (method.getName().equals("init") || method.getName().equals("destroy")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -893,12 +893,6 @@ public abstract class Sncp {
|
||||
mv.visitMaxs(0, 2);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{ //stop
|
||||
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "stop", "(" + anyValueDesc + ")V", null, null));
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(0, 2);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{ //destroy
|
||||
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "destroy", "(" + anyValueDesc + ")V", null, null));
|
||||
mv.visitInsn(RETURN);
|
||||
|
||||
@@ -8,24 +8,7 @@ import java.nio.channels.CompletionHandler;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.redkale.asm.*;
|
||||
import static org.redkale.asm.Opcodes.ACC_FINAL;
|
||||
import static org.redkale.asm.Opcodes.ACC_PRIVATE;
|
||||
import static org.redkale.asm.Opcodes.ACC_PUBLIC;
|
||||
import static org.redkale.asm.Opcodes.ACC_SUPER;
|
||||
import static org.redkale.asm.Opcodes.ACONST_NULL;
|
||||
import static org.redkale.asm.Opcodes.ALOAD;
|
||||
import static org.redkale.asm.Opcodes.ARETURN;
|
||||
import static org.redkale.asm.Opcodes.DRETURN;
|
||||
import static org.redkale.asm.Opcodes.FRETURN;
|
||||
import static org.redkale.asm.Opcodes.GETFIELD;
|
||||
import static org.redkale.asm.Opcodes.ICONST_0;
|
||||
import static org.redkale.asm.Opcodes.INVOKEINTERFACE;
|
||||
import static org.redkale.asm.Opcodes.INVOKESPECIAL;
|
||||
import static org.redkale.asm.Opcodes.IRETURN;
|
||||
import static org.redkale.asm.Opcodes.LRETURN;
|
||||
import static org.redkale.asm.Opcodes.PUTFIELD;
|
||||
import static org.redkale.asm.Opcodes.RETURN;
|
||||
import static org.redkale.asm.Opcodes.V11;
|
||||
import static org.redkale.asm.Opcodes.*;
|
||||
import org.redkale.asm.Type;
|
||||
import org.redkale.util.*;
|
||||
|
||||
@@ -43,19 +26,19 @@ import org.redkale.util.*;
|
||||
*/
|
||||
public interface SncpAsyncHandler<V, A> extends CompletionHandler<V, A> {
|
||||
|
||||
public static SncpAsyncHandler createHandler(Class<? extends CompletionHandler> handlerClazz, CompletionHandler realHandler) {
|
||||
public static SncpAsyncHandler createHandler(Class<? extends CompletionHandler> handlerClazz, CompletionHandler factHandler) {
|
||||
Objects.requireNonNull(handlerClazz);
|
||||
Objects.requireNonNull(realHandler);
|
||||
Objects.requireNonNull(factHandler);
|
||||
if (handlerClazz == CompletionHandler.class) {
|
||||
return new SncpAsyncHandler() {
|
||||
@Override
|
||||
public void completed(Object result, Object attachment) {
|
||||
realHandler.completed(result, attachment);
|
||||
factHandler.completed(result, attachment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable exc, Object attachment) {
|
||||
realHandler.failed(exc, attachment);
|
||||
factHandler.failed(exc, attachment);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -84,7 +67,7 @@ public interface SncpAsyncHandler<V, A> extends CompletionHandler<V, A> {
|
||||
cw.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, handlerInterface ? "java/lang/Object" : handlerClassName, handlerInterface && handlerClass != sncpHandlerClass ? new String[]{handlerClassName, sncpHandlerName} : new String[]{sncpHandlerName});
|
||||
|
||||
{ //handler 属性
|
||||
fv = cw.visitField(ACC_PRIVATE, "realHandler", realHandlerDesc, null, null);
|
||||
fv = cw.visitField(ACC_PRIVATE, "factHandler", realHandlerDesc, null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
{//构造方法
|
||||
@@ -94,7 +77,7 @@ public interface SncpAsyncHandler<V, A> extends CompletionHandler<V, A> {
|
||||
av0 = mv.visitAnnotation(cpDesc, true);
|
||||
{
|
||||
AnnotationVisitor av1 = av0.visitArray("value");
|
||||
av1.visit(null, "realHandler");
|
||||
av1.visit(null, "factHandler");
|
||||
av1.visitEnd();
|
||||
}
|
||||
av0.visitEnd();
|
||||
@@ -103,7 +86,7 @@ public interface SncpAsyncHandler<V, A> extends CompletionHandler<V, A> {
|
||||
mv.visitMethodInsn(INVOKESPECIAL, handlerInterface ? "java/lang/Object" : handlerClassName, "<init>", "()V", false);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitFieldInsn(PUTFIELD, newDynName, "realHandler", realHandlerDesc);
|
||||
mv.visitFieldInsn(PUTFIELD, newDynName, "factHandler", realHandlerDesc);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(2, 2);
|
||||
mv.visitEnd();
|
||||
@@ -114,7 +97,7 @@ public interface SncpAsyncHandler<V, A> extends CompletionHandler<V, A> {
|
||||
if (Modifier.isPublic(mod) && "completed".equals(method.getName()) && method.getParameterCount() == 2) {
|
||||
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "completed", methodDesc, null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "realHandler", realHandlerDesc);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "factHandler", realHandlerDesc);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, realHandlerName, "completed", "(Ljava/lang/Object;Ljava/lang/Object;)V", true);
|
||||
@@ -136,7 +119,7 @@ public interface SncpAsyncHandler<V, A> extends CompletionHandler<V, A> {
|
||||
} else if (Modifier.isPublic(mod) && "failed".equals(method.getName()) && method.getParameterCount() == 2) {
|
||||
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "failed", methodDesc, null, null));
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "realHandler", realHandlerDesc);
|
||||
mv.visitFieldInsn(GETFIELD, newDynName, "factHandler", realHandlerDesc);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, realHandlerName, "failed", "(Ljava/lang/Throwable;Ljava/lang/Object;)V", true);
|
||||
@@ -192,7 +175,7 @@ public interface SncpAsyncHandler<V, A> extends CompletionHandler<V, A> {
|
||||
}.loadClass(newDynName.replace('/', '.'), bytes);
|
||||
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz);
|
||||
return (Creator<SncpAsyncHandler>) Creator.create(newClazz);
|
||||
}).create(realHandler);
|
||||
}).create(factHandler);
|
||||
}
|
||||
|
||||
static class HandlerInner {
|
||||
|
||||
Reference in New Issue
Block a user