result = WebContext.blade().getStatics().stream()
+ .filter(s -> s.equals(uri) || uri.startsWith(s)).findFirst();
+
if (!result.isPresent()) {
- NOT_STATIC_URI.add(uri);
+ notStaticUri.add(uri);
return false;
}
return true;
}
- public static LocalContext getLocalContext() {
- return LOCAL_CONTEXT_THREAD_LOCAL.get();
- }
-
- public static void setLocalContext(LocalContext localContext) {
- LOCAL_CONTEXT_THREAD_LOCAL.set(localContext);
- }
-
- private void cleanContext() {
- LOCAL_CONTEXT_THREAD_LOCAL.remove();
- WEB_CONTEXT_THREAD_LOCAL.remove();
- }
-
}
\ No newline at end of file
diff --git a/src/main/java/com/blade/server/netty/HttpServerInitializer.java b/src/main/java/com/blade/server/netty/HttpServerInitializer.java
index 72090c060..0f06ff353 100644
--- a/src/main/java/com/blade/server/netty/HttpServerInitializer.java
+++ b/src/main/java/com/blade/server/netty/HttpServerInitializer.java
@@ -8,14 +8,12 @@
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpContentCompressor;
-import io.netty.handler.codec.http.HttpRequestDecoder;
-import io.netty.handler.codec.http.HttpResponseEncoder;
+import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.HttpServerExpectContinueHandler;
import io.netty.handler.codec.http.cors.CorsConfigBuilder;
import io.netty.handler.codec.http.cors.CorsHandler;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.ssl.SslContext;
-import io.netty.handler.stream.ChunkedWriteHandler;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;
@@ -64,16 +62,13 @@ protected void initChannel(SocketChannel ch) {
pipeline.addLast(sslCtx.newHandler(ch.alloc()));
}
- pipeline.addLast(new HttpRequestDecoder());
- pipeline.addLast(new HttpResponseEncoder());
+ pipeline.addLast(new HttpServerCodec());
+ pipeline.addLast(new HttpServerExpectContinueHandler());
if (useGZIP) {
pipeline.addLast(new HttpContentCompressor());
}
- pipeline.addLast(new ChunkedWriteHandler());
- pipeline.addLast(new HttpServerExpectContinueHandler());
-
if (enableCors) {
pipeline.addLast(new CorsHandler(CorsConfigBuilder.forAnyOrigin().allowNullOrigin().allowCredentials().build()));
}
@@ -82,6 +77,7 @@ protected void initChannel(SocketChannel ch) {
pipeline.addLast(new WebSocketServerProtocolHandler(blade.webSocketPath(), null, true));
pipeline.addLast(WEB_SOCKET_HANDLER);
}
+ pipeline.addLast(new MergeRequestHandler());
pipeline.addLast(httpServerHandler);
} catch (Exception e) {
log.error("Add channel pipeline error", e);
diff --git a/src/main/java/com/blade/server/netty/IoMultiplexer.java b/src/main/java/com/blade/server/netty/IoMultiplexer.java
deleted file mode 100644
index 02c350815..000000000
--- a/src/main/java/com/blade/server/netty/IoMultiplexer.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.blade.server.netty;
-
-public enum IoMultiplexer {
- EPOLL, KQUEUE, JDK
-}
\ No newline at end of file
diff --git a/src/main/java/com/blade/server/netty/LogicRunner.java b/src/main/java/com/blade/server/netty/LogicRunner.java
deleted file mode 100644
index 015f05508..000000000
--- a/src/main/java/com/blade/server/netty/LogicRunner.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * Copyright (c) 2018, biezhi 王爵 nice (biezhi.me@gmail.com)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.blade.server.netty;
-
-import com.blade.kit.BladeCache;
-import com.blade.mvc.WebContext;
-import com.blade.mvc.http.Request;
-import lombok.extern.slf4j.Slf4j;
-
-import java.time.Instant;
-import java.util.concurrent.CompletableFuture;
-
-import static com.blade.kit.BladeKit.log200;
-import static com.blade.kit.BladeKit.log200AndCost;
-import static com.blade.mvc.Const.REQUEST_COST_TIME;
-
-/**
- * Http Logic Runner
- *
- * @author biezhi
- * @date 2018/10/15
- */
-@Slf4j
-public class LogicRunner {
-
- private CompletableFuture future;
- private WebContext webContext;
- private Instant started;
- private RouteMethodHandler routeHandler;
- private boolean isFinished;
-
- public LogicRunner(RouteMethodHandler routeHandler, WebContext webContext) {
- this.routeHandler = routeHandler;
- this.webContext = webContext;
- if (!HttpServerHandler.PERFORMANCE && HttpServerHandler.ALLOW_COST) {
- this.started = Instant.now();
- }
- }
-
- /**
- * Routing logic execution
- */
- public LogicRunner handle() {
- WebContext.set(webContext);
- Request request = webContext.getRequest();
- String uri = request.uri();
- String method = request.method();
- try {
- routeHandler.handle(webContext);
-
- if (HttpServerHandler.PERFORMANCE) {
- return this;
- }
-
- if (HttpServerHandler.ALLOW_COST) {
- long cost = log200AndCost(log, this.started, BladeCache.getPaddingMethod(method), uri);
- request.attribute(REQUEST_COST_TIME, cost);
- } else {
- log200(log, BladeCache.getPaddingMethod(method), uri);
- }
- } catch (Exception e) {
- routeHandler.exceptionCaught(uri, method, e);
- }
- return this;
- }
-
- public void finishWrite() {
- WebContext.set(webContext);
- routeHandler.finishWrite(webContext);
- WebContext.remove();
- isFinished = true;
- if (null != future) {
- future.complete(null);
- }
- }
-
- public void setFuture(CompletableFuture future) {
- this.future = future;
- if (isFinished) {
- future.complete(null);
- }
- }
-
-}
diff --git a/src/main/java/com/blade/server/netty/MergeRequestHandler.java b/src/main/java/com/blade/server/netty/MergeRequestHandler.java
new file mode 100644
index 000000000..ddb61ab06
--- /dev/null
+++ b/src/main/java/com/blade/server/netty/MergeRequestHandler.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2018, biezhi 王爵 nice (biezhi.me@gmail.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.blade.server.netty;
+
+import com.blade.mvc.handler.ExceptionHandler;
+import com.blade.mvc.http.HttpRequest;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.handler.codec.http.*;
+import lombok.extern.slf4j.Slf4j;
+
+import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
+
+/**
+ * Merge Netty HttpObject as {@link HttpRequest}
+ *
+ * @author biezhi
+ * 2018/10/15
+ */
+@Slf4j
+public class MergeRequestHandler extends SimpleChannelInboundHandler {
+
+ private HttpRequest httpRequest;
+
+ @Override
+ protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) {
+ if (msg instanceof io.netty.handler.codec.http.HttpRequest) {
+ httpRequest = new HttpRequest();
+ httpRequest.setNettyRequest((io.netty.handler.codec.http.HttpRequest) msg);
+ return;
+ }
+ if (msg instanceof HttpContent) {
+ httpRequest.appendContent((HttpContent) msg);
+ }
+ if (msg instanceof LastHttpContent) {
+ ctx.fireChannelRead(httpRequest);
+ }
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+ if (!ExceptionHandler.isResetByPeer(cause)) {
+ log.error(cause.getMessage(), cause);
+ FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(500));
+ ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/blade/server/netty/NettyServer.java b/src/main/java/com/blade/server/netty/NettyServer.java
index 19f640f48..11df9e543 100644
--- a/src/main/java/com/blade/server/netty/NettyServer.java
+++ b/src/main/java/com/blade/server/netty/NettyServer.java
@@ -51,14 +51,11 @@
import com.blade.task.cron.CronThreadPoolExecutor;
import com.blade.watcher.EnvironmentWatcher;
import io.netty.bootstrap.ServerBootstrap;
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelOption;
-import io.netty.channel.EventLoopGroup;
+import io.netty.channel.*;
import io.netty.channel.epoll.EpollChannelOption;
+import io.netty.channel.nio.NioEventLoop;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
-import io.netty.handler.logging.LogLevel;
-import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.util.ResourceLeakDetector;
@@ -67,9 +64,11 @@
import java.io.File;
import java.lang.reflect.Method;
+import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
@@ -89,6 +88,7 @@ public class NettyServer implements Server {
private Blade blade;
private Environment environment;
private EventLoopGroup bossGroup;
+ private EventLoop scheduleEventLoop;
private EventLoopGroup workerGroup;
private Channel channel;
private RouteBuilder routeBuilder;
@@ -96,8 +96,6 @@ public class NettyServer implements Server {
private List loaders;
private List taskStruts = new ArrayList<>();
- private final int padSize = 26;
-
private volatile boolean isStop;
@Override
@@ -108,12 +106,18 @@ public void start(Blade blade) throws Exception {
this.loaders = blade.loaders();
long startMs = System.currentTimeMillis();
- log.info("{} {}{}", StringKit.padRight("environment.jdk.version", padSize), getPrefixSymbol(), System.getProperty("java.version"));
- log.info("{} {}{}", StringKit.padRight("environment.user.dir", padSize), getPrefixSymbol(), System.getProperty("user.dir"));
- log.info("{} {}{}", StringKit.padRight("environment.java.io.tmpdir", padSize), getPrefixSymbol(), System.getProperty("java.io.tmpdir"));
- log.info("{} {}{}", StringKit.padRight("environment.user.timezone", padSize), getPrefixSymbol(), System.getProperty("user.timezone"));
- log.info("{} {}{}", StringKit.padRight("environment.file.encoding", padSize), getPrefixSymbol(), System.getProperty("file.encoding"));
- log.info("{} {}{}", StringKit.padRight("environment.classpath", padSize), getPrefixSymbol(), CLASSPATH);
+
+ int padSize = 16;
+ log.info("{} {}{}", StringKit.padRight("app.env", padSize), getPrefixSymbol(), environment.get(ENV_KEY_APP_ENV, "default"));
+ log.info("{} {}{}", StringKit.padRight("app.pid", padSize), getPrefixSymbol(), BladeKit.getPID());
+ log.info("{} {}{}", StringKit.padRight("app.devMode", padSize), getPrefixSymbol(), blade.devMode());
+
+ log.info("{} {}{}", StringKit.padRight("jdk.version", padSize), getPrefixSymbol(), System.getProperty("java.version"));
+ log.info("{} {}{}", StringKit.padRight("user.dir", padSize), getPrefixSymbol(), System.getProperty("user.dir"));
+ log.info("{} {}{}", StringKit.padRight("java.io.tmpdir", padSize), getPrefixSymbol(), System.getProperty("java.io.tmpdir"));
+ log.info("{} {}{}", StringKit.padRight("user.timezone", padSize), getPrefixSymbol(), System.getProperty("user.timezone"));
+ log.info("{} {}{}", StringKit.padRight("file.encoding", padSize), getPrefixSymbol(), System.getProperty("file.encoding"));
+ log.info("{} {}{}", StringKit.padRight("app.classpath", padSize), getPrefixSymbol(), CLASSPATH);
this.initConfig();
@@ -130,9 +134,9 @@ public void start(Blade blade) throws Exception {
private void sessionCleaner() {
if (null != blade.sessionManager()) {
- Thread sessionCleanerThread = new Thread(new SessionCleaner(blade.sessionManager()));
- sessionCleanerThread.setName("session-cleaner");
- sessionCleanerThread.start();
+ scheduleEventLoop.
+ scheduleWithFixedDelay(new SessionCleaner(blade.sessionManager()),
+ 1000, 1000, TimeUnit.MILLISECONDS);
}
}
@@ -191,13 +195,7 @@ private void startServer(long startMs) throws Exception {
sslCtx = SslContextBuilder.forServer(new File(certFilePath), new File(privateKeyPath), privateKeyPassword).build();
}
- // Configure the server.
- int backlog = environment.getInt(ENV_KEY_NETTY_SO_BACKLOG, DEFAULT_SO_BACKLOG);
-
var bootstrap = new ServerBootstrap();
- bootstrap.option(ChannelOption.SO_BACKLOG, backlog);
- bootstrap.option(ChannelOption.SO_REUSEADDR, true);
- bootstrap.childOption(ChannelOption.SO_REUSEADDR, true);
int acceptThreadCount = environment.getInt(ENC_KEY_NETTY_ACCEPT_THREAD_COUNT, DEFAULT_ACCEPT_THREAD_COUNT);
int ioThreadCount = environment.getInt(ENV_KEY_NETTY_IO_THREAD_COUNT, DEFAULT_IO_THREAD_COUNT);
@@ -215,12 +213,13 @@ private void startServer(long startMs) throws Exception {
log.info("{}Use NioEventLoopGroup", getStartedSymbol());
this.bossGroup = new NioEventLoopGroup(acceptThreadCount, new NamedThreadFactory("boss@"));
- this.workerGroup = new NioEventLoopGroup(ioThreadCount, new NamedThreadFactory("io@"));
+ this.workerGroup = new NioEventLoopGroup(ioThreadCount, new NamedThreadFactory("worker@"));
bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class);
}
- bootstrap.handler(new LoggingHandler(LogLevel.DEBUG))
- .childHandler(new HttpServerInitializer(sslCtx, blade, bossGroup.next()));
+ scheduleEventLoop = new DefaultEventLoop();
+
+ bootstrap.childHandler(new HttpServerInitializer(sslCtx, blade, scheduleEventLoop));
String address = environment.get(ENV_KEY_SERVER_ADDRESS, DEFAULT_SERVER_ADDRESS);
Integer port = environment.getInt(ENV_KEY_SERVER_PORT, DEFAULT_SERVER_PORT);
@@ -252,7 +251,7 @@ private void startTask() {
}
var jobCount = new AtomicInteger();
- for (var taskStruct: taskStruts) {
+ for (var taskStruct : taskStruts) {
addTask(executorService, jobCount, taskStruct);
}
}
@@ -326,10 +325,10 @@ private boolean isExceptionHandler(Class> clazz) {
}
private void watchEnv() {
- boolean watchEnv = environment.getBoolean(ENV_KEY_APP_WATCH_ENV, true);
- log.info("{}Watched environment: {}", getStartedSymbol(), watchEnv, getStartedSymbol());
+ boolean watchEnv = environment.getBoolean(ENV_KEY_APP_WATCH_ENV, false);
if (watchEnv) {
+ log.info("{}Watched environment started", getStartedSymbol());
var thread = new Thread(new EnvironmentWatcher());
thread.setName("watch@thread");
thread.start();
diff --git a/src/main/java/com/blade/server/netty/RouteMethodHandler.java b/src/main/java/com/blade/server/netty/RouteMethodHandler.java
index 2ec93b13e..552a40614 100644
--- a/src/main/java/com/blade/server/netty/RouteMethodHandler.java
+++ b/src/main/java/com/blade/server/netty/RouteMethodHandler.java
@@ -27,7 +27,6 @@
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.*;
-import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.stream.ChunkedStream;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
@@ -37,14 +36,10 @@
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import static com.blade.kit.BladeKit.log404;
import static com.blade.kit.BladeKit.log500;
-import static com.blade.mvc.Const.ENV_KEY_SESSION_KEY;
import static com.blade.server.netty.HttpConst.CONTENT_LENGTH;
import static com.blade.server.netty.HttpConst.KEEP_ALIVE;
import static io.netty.handler.codec.http.HttpHeaderNames.TRANSFER_ENCODING;
@@ -72,7 +67,6 @@ public void handle(WebContext webContext) throws Exception {
String uri = context.uri();
Route route = webContext.getRoute();
if (null == route) {
- log404(log, context.method(), context.uri());
throw new NotFoundException(context.uri());
}
@@ -99,85 +93,52 @@ public void handle(WebContext webContext) throws Exception {
}
}
- public void exceptionCaught(String uri, String method, Exception e) {
- if (e instanceof BladeException) {
- } else {
- log500(log, method, uri);
- }
- if (null != WebContext.blade().exceptionHandler()) {
- WebContext.blade().exceptionHandler().handle(e);
- } else {
- log.error("Request Exception", e);
- }
- }
-
- public void finishWrite(WebContext webContext) {
- Request request = webContext.getRequest();
- Response response = webContext.getResponse();
- Session session = request.session();
-
+ public FullHttpResponse handleResponse(Request request, Response response, ChannelHandlerContext context) {
+ Session session = request.session();
if (null != session) {
- String sessionKey = WebContext.blade().environment().get(ENV_KEY_SESSION_KEY, HttpConst.DEFAULT_SESSION_KEY);
- Cookie cookie = new Cookie();
- cookie.name(sessionKey);
+ Cookie cookie = new Cookie();
+ cookie.name(WebContext.sessionKey());
cookie.value(session.id());
cookie.httpOnly(true);
cookie.secure(request.isSecure());
response.cookie(cookie);
}
- this.handleResponse(request, response, webContext.getChannelHandlerContext());
- }
- public void handleResponse(Request request, Response response, ChannelHandlerContext context) {
- response.body().write(new BodyWriter() {
+ FullHttpResponse fullHttpResponse = response.body().write(new BodyWriter() {
@Override
- public void onByteBuf(ByteBuf byteBuf) {
- handleFullResponse(
- createResponseByByteBuf(response, byteBuf),
- context,
- request.keepAlive());
+ public FullHttpResponse onByteBuf(ByteBuf byteBuf) {
+ return createResponseByByteBuf(response, byteBuf);
}
@Override
- public void onStream(Closeable closeable) {
- if (closeable instanceof InputStream) {
- handleStreamResponse(response, (InputStream) closeable, context, request.keepAlive());
- }
+ public FullHttpResponse onStream(Closeable closeable) {
+ // TODO
+ return null;
}
@Override
- public void onView(ViewBody body) {
+ public FullHttpResponse onView(ViewBody body) {
try {
var sw = new StringWriter();
WebContext.blade().templateEngine().render(body.modelAndView(), sw);
- response.contentType(Const.CONTENT_TYPE_HTML);
-
- handleFullResponse(
- createTextResponse(response, sw.toString()),
- context,
- request.keepAlive());
+ WebContext.response().contentType(Const.CONTENT_TYPE_HTML);
+ return this.onByteBuf(Unpooled.copiedBuffer(sw.toString().getBytes(StandardCharsets.UTF_8)));
} catch (Exception e) {
log.error("Render view error", e);
}
+ return null;
}
@Override
- public void onRawBody(RawBody body) {
- if (null != body.httpResponse()) {
- handleFullResponse(body.httpResponse(), context, request.keepAlive());
- }
- if (null != body.defaultHttpResponse()) {
- handleFullResponse(body.defaultHttpResponse(), context, request.keepAlive());
- }
+ public FullHttpResponse onRawBody(RawBody body) {
+ return body.httpResponse();
}
@Override
- public void onByteBuf(Object byteBuf) {
+ public FullHttpResponse onByteBuf(Object byteBuf) {
var httpResponse = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(response.statusCode()));
- Iterator> iterator = response.headers().entrySet().iterator();
- while (iterator.hasNext()) {
- Map.Entry next = iterator.next();
+ for (Map.Entry next : response.headers().entrySet()) {
httpResponse.headers().set(next.getKey(), next.getValue());
}
@@ -191,29 +152,19 @@ public void onByteBuf(Object byteBuf) {
if (!request.keepAlive()) {
lastContentFuture.addListener(ChannelFutureListener.CLOSE);
}
+ return null;
}
});
- }
-
- private Void handleFullResponse(HttpResponse response, ChannelHandlerContext context, boolean keepAlive) {
- if (context.channel().isActive()) {
- if (!keepAlive) {
- context.write(response).addListener(ChannelFutureListener.CLOSE);
- } else {
- response.headers().set(HttpConst.CONNECTION, KEEP_ALIVE);
- context.write(response, context.voidPromise());
- }
- context.flush();
+ if (request.keepAlive()) {
+ fullHttpResponse.headers().set(HttpConst.CONNECTION, KEEP_ALIVE);
}
- return null;
+ return fullHttpResponse;
}
- public Map getDefaultHeader() {
- var map = new HashMap(2);
- map.put("Date", HttpServerInitializer.date);
- map.put("X-Powered-By", HttpConst.VERSION);
- return map;
+ private void setDefaultHeaders(HttpHeaders headers) {
+ headers.set(HttpConst.DATE, HttpServerInitializer.date);
+ headers.set(HttpConst.X_POWER_BY, HttpConst.HEADER_VERSION);
}
public Void handleStreamResponse(Response response, InputStream body,
@@ -222,10 +173,9 @@ public Void handleStreamResponse(Response response, InputStream body,
var httpResponse = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(response.statusCode()));
httpResponse.headers().set(TRANSFER_ENCODING, HttpHeaderValues.CHUNKED);
+ setDefaultHeaders(httpResponse.headers());
- Iterator> iterator = response.headers().entrySet().iterator();
- while (iterator.hasNext()) {
- Map.Entry next = iterator.next();
+ for (Map.Entry next : response.headers().entrySet()) {
httpResponse.headers().set(next.getKey(), next.getValue());
}
@@ -239,55 +189,29 @@ public Void handleStreamResponse(Response response, InputStream body,
return null;
}
- public FullHttpResponse createResponseByByteBuf(Response response, ByteBuf byteBuf) {
+ private FullHttpResponse createResponseByByteBuf(Response response, ByteBuf byteBuf) {
Map headers = response.headers();
- headers.putAll(getDefaultHeader());
var httpResponse = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(response.statusCode()), byteBuf);
httpResponse.headers().set(CONTENT_LENGTH, httpResponse.content().readableBytes());
+ setDefaultHeaders(httpResponse.headers());
if (response.cookiesRaw().size() > 0) {
this.appendCookie(response, httpResponse);
}
- Iterator> iterator = headers.entrySet().iterator();
- while (iterator.hasNext()) {
- Map.Entry next = iterator.next();
- httpResponse.headers().set(next.getKey(), next.getValue());
- }
- return httpResponse;
- }
-
- public FullHttpResponse createTextResponse(Response response, String body) {
- Map headers = response.headers();
- headers.putAll(getDefaultHeader());
-
- ByteBuf bodyBuf = Unpooled.wrappedBuffer(body.getBytes(StandardCharsets.UTF_8));
-
- var httpResponse = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(response.statusCode()),
- null == bodyBuf ? Unpooled.buffer(0) : bodyBuf);
-
- httpResponse.headers().set(CONTENT_LENGTH, httpResponse.content().readableBytes());
-
- if (response.cookiesRaw().size() > 0) {
- this.appendCookie(response, httpResponse);
- }
-
- Iterator> iterator = headers.entrySet().iterator();
- while (iterator.hasNext()) {
- Map.Entry next = iterator.next();
- httpResponse.headers().set(next.getKey(), next.getValue());
+ for (Map.Entry next : headers.entrySet()) {
+ httpResponse.headers().set(HttpConst.getAsciiString(next.getKey()), next.getValue());
}
return httpResponse;
}
private void appendCookie(Response response, DefaultFullHttpResponse httpResponse) {
- Iterator iterator = response.cookiesRaw().iterator();
- while (iterator.hasNext()) {
- io.netty.handler.codec.http.cookie.Cookie next = iterator.next();
- httpResponse.headers().add(HttpConst.SET_COOKIE, io.netty.handler.codec.http.cookie.ServerCookieEncoder.LAX.encode(next));
+ for (io.netty.handler.codec.http.cookie.Cookie next : response.cookiesRaw()) {
+ httpResponse.headers().add(HttpConst.SET_COOKIE,
+ io.netty.handler.codec.http.cookie.ServerCookieEncoder.LAX.encode(next));
}
}
@@ -330,7 +254,11 @@ private void routeHandle(RouteContext context) {
int len = actionMethod.getParameterTypes().length;
MethodAccess methodAccess = BladeCache.getMethodAccess(target.getClass());
- Object returnParam = methodAccess.invoke(target, actionMethod.getName(), len > 0 ? context.routeParameters() : null);
+
+ Object returnParam = methodAccess.invoke(
+ target, actionMethod.getName(), len > 0 ?
+ context.routeParameters() : null);
+
if (null == returnParam) {
return;
}
@@ -340,11 +268,15 @@ private void routeHandle(RouteContext context) {
return;
}
if (returnType == String.class) {
- context.body(new ViewBody(new ModelAndView(returnParam.toString())));
+ context.body(
+ ViewBody.of(new ModelAndView(returnParam.toString()))
+ );
return;
}
if (returnType == ModelAndView.class) {
- context.body(new ViewBody((ModelAndView) returnParam));
+ context.body(
+ ViewBody.of((ModelAndView) returnParam)
+ );
}
}
}
@@ -377,7 +309,9 @@ private boolean invokeHook(RouteContext context, Route hookRoute) throws Excepti
returnParam = methodAccess.invoke(target, hookMethod.getName(), context);
} else if (len == 2) {
MethodAccess methodAccess = BladeCache.getMethodAccess(target.getClass());
- returnParam = methodAccess.invoke(target, hookMethod.getName(), context.request(), context.response());
+
+ returnParam = methodAccess.invoke(target, hookMethod.getName(),
+ context.request(), context.response());
} else {
throw new InternalErrorException("Bad web hook structure");
}
@@ -394,7 +328,9 @@ private boolean invokeHook(RouteContext context, Route hookRoute) throws Excepti
return true;
}
- private boolean invokeMiddleware(List middleware, RouteContext context) throws BladeException {
+ private boolean invokeMiddleware(List middleware,
+ RouteContext context) throws BladeException {
+
if (BladeKit.isEmpty(middleware)) {
return true;
}
diff --git a/src/test/java/com/blade/BaseTestCase.java b/src/test/java/com/blade/BaseTestCase.java
index 887147bb7..7e37ed87f 100644
--- a/src/test/java/com/blade/BaseTestCase.java
+++ b/src/test/java/com/blade/BaseTestCase.java
@@ -25,6 +25,8 @@ public class BaseTestCase {
protected com.blade.mvc.http.HttpRequest mockHttpRequest(String methodName) {
com.blade.mvc.http.HttpRequest request = mock(com.blade.mvc.http.HttpRequest.class);
when(request.method()).thenReturn(methodName);
+ when(request.url()).thenReturn("/");
+ when(request.uri()).thenReturn("/");
when(request.httpMethod()).thenReturn(HttpMethod.valueOf(methodName));
return request;
}
diff --git a/src/test/java/com/blade/EnvironmentTest.java b/src/test/java/com/blade/EnvironmentTest.java
index 700a0f908..b0ce4592a 100644
--- a/src/test/java/com/blade/EnvironmentTest.java
+++ b/src/test/java/com/blade/EnvironmentTest.java
@@ -143,7 +143,7 @@ public void testGetValueOrNull() {
public void testGetPrefix() {
Environment environment = Environment.of("application.properties");
Map map = environment.getPrefix("app");
- assertEquals(6, map.size());
+ assertEquals(7, map.size());
assertEquals("0.0.2", map.get("version"));
}
@@ -156,7 +156,7 @@ public void testHasKey() {
}
@Test
- public void testHasValue(){
+ public void testHasValue() {
Environment environment = Environment.empty();
assertEquals(Boolean.FALSE, environment.hasValue("hello"));
}
@@ -194,7 +194,7 @@ public void testAddAll() {
}
@Test
- public void testSet(){
+ public void testSet() {
Environment environment = Environment.empty();
environment.set("name", "biezhi");
diff --git a/src/test/java/com/blade/mvc/HttpRequestTest.java b/src/test/java/com/blade/mvc/HttpRequestTest.java
index 5e3b3ed43..ef77734c7 100644
--- a/src/test/java/com/blade/mvc/HttpRequestTest.java
+++ b/src/test/java/com/blade/mvc/HttpRequestTest.java
@@ -296,6 +296,7 @@ public void testFileItems() {
Map attr = new HashMap<>();
FileItem fileItem = new FileItem();
+ fileItem.setName("file");
fileItem.setFileName("hello.png");
fileItem.setPath("/usr/hello.png");
fileItem.setContentType("image/png");
@@ -305,15 +306,17 @@ public void testFileItems() {
when(mockRequest.fileItems()).thenReturn(attr);
- Request request = new HttpRequest(mockRequest);
- FileItem img = request.fileItem("img").get();
+ Request request = new HttpRequest(mockRequest);
+
+ FileItem img = request.fileItem("img").get();
assertNotNull(img);
- assertNull(img.getData());
+ assertNull(img.getFile());
- assertEquals("hello.png", img.getName());
- assertEquals("/usr/hello.png", img.getFileName());
+ assertEquals("file", img.getName());
+ assertEquals("hello.png", img.getFileName());
+ assertEquals("/usr/hello.png", img.getPath());
assertEquals(Long.valueOf(20445), Optional.of(img.getLength()).get());
assertEquals("image/png", img.getContentType());
diff --git a/src/test/java/com/blade/mvc/HttpResponseTest.java b/src/test/java/com/blade/mvc/HttpResponseTest.java
index 220e125e7..e1f94f38f 100644
--- a/src/test/java/com/blade/mvc/HttpResponseTest.java
+++ b/src/test/java/com/blade/mvc/HttpResponseTest.java
@@ -74,10 +74,10 @@ public void testHeaders() {
when(mockResponse.headers()).thenReturn(new HashMap<>());
Response response = new HttpResponse(mockResponse);
- assertEquals(1, response.headers().size());
+ assertEquals(0, response.headers().size());
response.header("a", "123");
- assertEquals(2, response.headers().size());
+ assertEquals(1, response.headers().size());
}
@Test
@@ -88,7 +88,7 @@ public void testHeader() {
when(mockResponse.headers()).thenReturn(Collections.singletonMap("Server", "Nginx"));
Response response = new HttpResponse(mockResponse);
- assertEquals(2, response.headers().size());
+ assertEquals(1, response.headers().size());
assertEquals("Nginx", response.headers().get("Server"));
}
diff --git a/src/test/java/com/blade/mvc/route/RouteMatcherDemoController.java b/src/test/java/com/blade/mvc/route/RouteMatcherDemoController.java
new file mode 100644
index 000000000..cf85968c7
--- /dev/null
+++ b/src/test/java/com/blade/mvc/route/RouteMatcherDemoController.java
@@ -0,0 +1,9 @@
+package com.blade.mvc.route;
+
+public class RouteMatcherDemoController {
+ public void index() {
+ }
+
+ public void remove() {
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/blade/mvc/route/RouteMatcherTest.java b/src/test/java/com/blade/mvc/route/RouteMatcherTest.java
index d81fe8873..14a419921 100644
--- a/src/test/java/com/blade/mvc/route/RouteMatcherTest.java
+++ b/src/test/java/com/blade/mvc/route/RouteMatcherTest.java
@@ -83,12 +83,4 @@ public void testAddMultiParameter() throws Exception {
}
- class RouteMatcherDemoController {
- public void index() {
- }
-
- public void remove() {
- }
- }
-
}
diff --git a/src/test/java/netty_hello/Hello.java b/src/test/java/netty_hello/Hello.java
index 1580fe053..fc4b2b7c9 100644
--- a/src/test/java/netty_hello/Hello.java
+++ b/src/test/java/netty_hello/Hello.java
@@ -5,6 +5,7 @@
import com.blade.mvc.http.EmptyBody;
import com.blade.mvc.http.ByteBody;
import com.blade.mvc.http.StreamBody;
+import com.blade.mvc.http.StringBody;
import java.io.*;
import java.util.Random;
@@ -15,11 +16,10 @@
* 2017/6/5
*/
public class Hello {
+ private static final StringBody hello = StringBody.of("Hello World.");
public static void main(String[] args) {
Blade.of()
-// .devMode(false)
-// .environment(Const.ENV_KEY_NETTY_WORKERS, Runtime.getRuntime().availableProcessors())
.get("/", ctx -> {
String[] chars = new String[]{"Here a special char \" that not escaped", "And Another \\ char"};
ctx.json(chars);
@@ -46,7 +46,11 @@ public static void main(String[] args) {
ctx.response().contentType("text/html");
ctx.response().body(ByteBody.of(str.getBytes()));
})
- .get("/hello", ctx -> ctx.text("Hello World."))
+ .get("/error", ctx -> {
+ int a = 1 / 0;
+ ctx.text("ok");
+ })
+ .get("/hello", ctx -> ctx.body(hello))
.get("/error", ctx -> {
int a = 1 / 0;
ctx.text("Hello World.");
@@ -64,9 +68,6 @@ public static void main(String[] args) {
e.printStackTrace();
}
})
-// .before("/*", ctx -> {
-// System.out.println("Before...");
-// })
.get("/rand", ctx -> {
try {
int timeout = ctx.fromInt("timeout", new Random().nextInt(1000));
@@ -77,16 +78,10 @@ public static void main(String[] args) {
}
})
-// .use(new XssMiddleware())
-// .use(new CsrfMiddleware())
.event(EventType.ENVIRONMENT_CHANGED, new ConfigChanged())
.event(EventType.SESSION_DESTROY, e -> {
System.out.println("session 失效了");
})
- .disableSession()
-// .showFileList(true)
-// .gzip(true)
-// .enableCors(true)
.start(Hello.class, args);
}
diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties
index 5d33599ee..d92e11aaa 100644
--- a/src/test/resources/application.properties
+++ b/src/test/resources/application.properties
@@ -7,9 +7,8 @@ app.maxMoney=38.1
app.sex=true
app.hits=199283818033
app.startDate=2017-08-02
+app.performance=true
list=hello,my,blade,word
map=user:blade,version:2.0.0
-#com.blade.logger.rootLevel=error
com.blade.logger.dir=./logs
-com.blade.logger.console=true
\ No newline at end of file
diff --git a/src/test/resources/templates/upload.html b/src/test/resources/templates/upload.html
index 982723d8e..93941e6e2 100644
--- a/src/test/resources/templates/upload.html
+++ b/src/test/resources/templates/upload.html
@@ -30,7 +30,6 @@
console.log(res);
if(res.success){
alert('上传成功.');
- window.location.href = '/upload/';
} else {
alert(res.msg || '上传失败');
}