add filter

This commit is contained in:
Looly 2021-01-07 21:06:05 +08:00
parent c9a180abce
commit 0a768ad2c6
7 changed files with 165 additions and 11 deletions

View File

@ -14,12 +14,12 @@
* 【setting】 新增setByGroup和putByGroupset和put标记为过期issue#I2C42H@Gitee * 【setting】 新增setByGroup和putByGroupset和put标记为过期issue#I2C42H@Gitee
* 【crypto 】 修改SymmetricAlgorithm注释issue#1360@Github * 【crypto 】 修改SymmetricAlgorithm注释issue#1360@Github
* 【all 】 pom中将META-INF/maven下全部excludepr#1355@Github * 【all 】 pom中将META-INF/maven下全部excludepr#1355@Github
* 【core 】 pom中将META-INF/maven下全部excludepr#1355@Github * 【http 】 SimpleServer中增加addFilter等方法并使用全局线程池
### Bug修复 ### Bug修复
* 【core 】 修复CsvReader读取双引号未转义问题issur#I2BMP1@Gitee * 【core 】 修复CsvReader读取双引号未转义问题issue#I2BMP1@Gitee
* 【json 】 JSONUtil.parse修复config无效问题issur#1363@Github * 【json 】 JSONUtil.parse修复config无效问题issue#1363@Github
* 【http 】 修复SimpleServer返回响应内容Content-Lenth不正确的问题issur#1358@Github * 【http 】 修复SimpleServer返回响应内容Content-Length不正确的问题issue#1358@Github
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------

View File

@ -1,6 +1,7 @@
package cn.hutool.http.server; package cn.hutool.http.server;
import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.CharsetUtil;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpExchange;
import java.nio.charset.Charset; import java.nio.charset.Charset;
@ -34,4 +35,14 @@ public class HttpServerBase {
public HttpExchange getHttpExchange() { public HttpExchange getHttpExchange() {
return this.httpExchange; return this.httpExchange;
} }
/**
* 获取{@link HttpContext}
*
* @return {@link HttpContext}
* @since 5.5.7
*/
public HttpContext getHttpContext() {
return getHttpExchange().getHttpContext();
}
} }

View File

@ -6,13 +6,22 @@ import cn.hutool.core.thread.GlobalThreadPool;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.http.server.action.Action; import cn.hutool.http.server.action.Action;
import cn.hutool.http.server.action.RootAction; import cn.hutool.http.server.action.RootAction;
import cn.hutool.http.server.filter.HttpFilter;
import cn.hutool.http.server.filter.SimpleFilter;
import cn.hutool.http.server.handler.ActionHandler; import cn.hutool.http.server.handler.ActionHandler;
import com.sun.net.httpserver.Filter;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer; import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
/** /**
@ -23,7 +32,8 @@ import java.util.concurrent.Executor;
*/ */
public class SimpleServer { public class SimpleServer {
HttpServer server; private final HttpServer server;
private final List<Filter> filters;
/** /**
* 构造 * 构造
@ -50,26 +60,105 @@ public class SimpleServer {
* @param address 监听地址 * @param address 监听地址
*/ */
public SimpleServer(InetSocketAddress address) { public SimpleServer(InetSocketAddress address) {
this(address, null);
}
/**
* 构造
*
* @param address 监听地址
* @param configurator https配置信息用于使用自定义SSLTLS证书等
*/
public SimpleServer(InetSocketAddress address, HttpsConfigurator configurator) {
try { try {
this.server = HttpServer.create(address, 0); if(null != configurator){
final HttpsServer server = HttpsServer.create(address, 0);
server.setHttpsConfigurator(configurator);
this.server = server;
} else{
this.server = HttpServer.create(address, 0);
}
} catch (IOException e) { } catch (IOException e) {
throw new IORuntimeException(e); throw new IORuntimeException(e);
} }
setExecutor(GlobalThreadPool.getExecutor()); setExecutor(GlobalThreadPool.getExecutor());
filters = new ArrayList<>();
}
/**
* 增加请求过滤器此过滤器对所有请求有效<br>
* 此方法需在以下方法前之前调用
*
* <ul>
* <li>{@link #setRoot(File)} </li>
* <li>{@link #setRoot(String)} </li>
* <li>{@link #createContext(String, HttpHandler)} </li>
* <li>{@link #addHandler(String, HttpHandler)}</li>
* <li>{@link #addAction(String, Action)} </li>
* </ul>
*
* @param filter {@link Filter} 请求过滤器
* @return this
* @since 5.5.7
*/
public SimpleServer addFilter(Filter filter) {
this.filters.add(filter);
return this;
}
/**
* 增加请求过滤器此过滤器对所有请求有效<br>
* 此方法需在以下方法前之前调用
*
* <ul>
* <li>{@link #setRoot(File)} </li>
* <li>{@link #setRoot(String)} </li>
* <li>{@link #createContext(String, HttpHandler)} </li>
* <li>{@link #addHandler(String, HttpHandler)}</li>
* <li>{@link #addAction(String, Action)} </li>
* </ul>
*
* @param filter {@link Filter} 请求过滤器
* @return this
* @since 5.5.7
*/
public SimpleServer addFilter(HttpFilter filter) {
return addFilter(new SimpleFilter() {
@Override
public void doFilter(HttpExchange httpExchange, Chain chain) throws IOException {
filter.doFilter(new HttpServerRequest(httpExchange), new HttpServerResponse(httpExchange), chain);
}
});
} }
/** /**
* 增加请求处理规则 * 增加请求处理规则
* *
* @param path 路径 * @param path 路径例如:/a/b 或者 a/b
* @param handler 处理器 * @param handler 处理器包括请求和响应处理
* @return this * @return this
* @see #createContext(String, HttpHandler)
*/ */
public SimpleServer addHandler(String path, HttpHandler handler) { public SimpleServer addHandler(String path, HttpHandler handler) {
createContext(path, handler);
return this;
}
/**
* 创建请求映射上下文创建后用户访问指定路径可使用{@link HttpHandler} 中的规则进行处理
*
* @param path 路径例如:/a/b 或者 a/b
* @param handler 处理器包括请求和响应处理
* @return {@link HttpContext}
* @since 5.5.7
*/
public HttpContext createContext(String path, HttpHandler handler) {
// /开头的路径会报错 // /开头的路径会报错
path = StrUtil.addPrefixIfNot(path, StrUtil.SLASH); path = StrUtil.addPrefixIfNot(path, StrUtil.SLASH);
this.server.createContext(path, handler); final HttpContext context = this.server.createContext(path, handler);
return this; // 增加整体过滤器
context.getFilters().addAll(this.filters);
return context;
} }
/** /**

View File

@ -0,0 +1,26 @@
package cn.hutool.http.server.filter;
import cn.hutool.http.server.HttpServerRequest;
import cn.hutool.http.server.HttpServerResponse;
import com.sun.net.httpserver.Filter;
import java.io.IOException;
/**
* 过滤器接口用于简化{@link Filter} 使用
*
* @author looly
* @since 5.5.7
*/
@FunctionalInterface
public interface HttpFilter {
/**
* 执行过滤
* @param req {@link HttpServerRequest} 请求对象用于获取请求内容
* @param res {@link HttpServerResponse} 响应对象用于写出内容
* @param chain {@link Filter.Chain}
* @throws IOException IO异常
*/
void doFilter(HttpServerRequest req, HttpServerResponse res, Filter.Chain chain) throws IOException;
}

View File

@ -0,0 +1,17 @@
package cn.hutool.http.server.filter;
import com.sun.net.httpserver.Filter;
/**
* 匿名简单过滤器跳过了描述
*
* @author looly
* @since 5.5.7
*/
public abstract class SimpleFilter extends Filter {
@Override
public String description() {
return "Anonymous Filter";
}
}

View File

@ -0,0 +1,4 @@
/**
* {@link com.sun.net.httpserver.Filter} 实现包装
*/
package cn.hutool.http.server.filter;

View File

@ -11,6 +11,10 @@ public class SimpleServerTest {
public static void main(String[] args) { public static void main(String[] args) {
HttpUtil.createServer(8888) HttpUtil.createServer(8888)
.addFilter(((req, res, chain) -> {
Console.log("Filter: " + req.getPath());
chain.doFilter(req.getHttpExchange());
}))
// 设置默认根目录classpath/html // 设置默认根目录classpath/html
.setRoot(FileUtil.file("html")) .setRoot(FileUtil.file("html"))
// get数据测试返回请求的PATH // get数据测试返回请求的PATH
@ -46,7 +50,10 @@ public class SimpleServerTest {
} }
) )
// 测试输出响应内容是否能正常返回Content-Length头信息 // 测试输出响应内容是否能正常返回Content-Length头信息
.addAction("test/zeroStr", (req, res)-> res.write("0")) .addAction("test/zeroStr", (req, res)-> {
res.write("0");
Console.log("Write 0 OK");
})
.start(); .start();
} }
} }