lazyHeader

This commit is contained in:
redkale
2024-08-16 09:37:50 +08:00
parent 60b4425a47
commit e7ed4ae9bc
5 changed files with 102 additions and 85 deletions

View File

@@ -43,14 +43,15 @@ public class HttpContext extends Context {
protected final AnyValue rpcAuthenticatorConfig; protected final AnyValue rpcAuthenticatorConfig;
// 所有Servlet方法都不需要读取http-header且RestBaseServlet不是自定义HttpServlet且不存在HttpFilter、WebSocket的情况下lazyHeaders=true // 延迟解析header
protected boolean lazyHeaders; // 存在动态改值 protected final boolean lazyHeaders; // 存在动态改值
// 不带通配符的mapping url的缓存对象 // 不带通配符的mapping url的缓存对象
final Map<ByteArray, String>[] uriPathCaches = new Map[100]; final Map<ByteArray, String>[] uriPathCaches = new Map[100];
public HttpContext(HttpContextConfig config) { public HttpContext(HttpContextConfig config) {
super(config); super(config);
this.lazyHeaders = config.lazyHeaders;
this.remoteAddrHeader = config.remoteAddrHeader; this.remoteAddrHeader = config.remoteAddrHeader;
this.remoteAddrHeaders = config.remoteAddrHeaders; this.remoteAddrHeaders = config.remoteAddrHeaders;
this.localHeader = config.localHeader; this.localHeader = config.localHeader;
@@ -232,6 +233,8 @@ public class HttpContext extends Context {
} }
public static class HttpContextConfig extends ContextConfig { public static class HttpContextConfig extends ContextConfig {
// 是否延迟解析http-header
public boolean lazyHeaders;
public String remoteAddrHeader; public String remoteAddrHeader;

View File

@@ -48,9 +48,6 @@ public class HttpDispatcherServlet
protected HttpContext context; protected HttpContext context;
// 所有Servlet方法都不需要读取http-header且不存在HttpFilter的情况下lazyHeaders=true
protected boolean lazyHeaders = true;
private Map<String, BiPredicate<String, String>> forbidURIMaps; // 禁用的URL的正则表达式, 必须与 forbidURIPredicates 保持一致 private Map<String, BiPredicate<String, String>> forbidURIMaps; // 禁用的URL的正则表达式, 必须与 forbidURIPredicates 保持一致
private BiPredicate<String, String>[] forbidURIPredicates; // 禁用的URL的Predicate, 必须与 forbidURIMaps 保持一致 private BiPredicate<String, String>[] forbidURIPredicates; // 禁用的URL的Predicate, 必须与 forbidURIMaps 保持一致
@@ -259,7 +256,6 @@ public class HttpDispatcherServlet
public void init(HttpContext context, AnyValue config) { public void init(HttpContext context, AnyValue config) {
super.init(context, config); // 必须要执行 super.init(context, config); // 必须要执行
this.context = context; this.context = context;
context.lazyHeaders = lazyHeaders;
Collection<HttpServlet> servlets = getServlets(); Collection<HttpServlet> servlets = getServlets();
servlets.forEach(s -> { servlets.forEach(s -> {
s.preInit(application, context, getServletConf(s)); s.preInit(application, context, getServletConf(s));
@@ -381,10 +377,6 @@ public class HttpDispatcherServlet
@Override @Override
public void addFilter(Filter<HttpContext, HttpRequest, HttpResponse> filter, AnyValue conf) { public void addFilter(Filter<HttpContext, HttpRequest, HttpResponse> filter, AnyValue conf) {
super.addFilter(filter, conf); super.addFilter(filter, conf);
this.lazyHeaders = false;
if (context != null) {
context.lazyHeaders = this.lazyHeaders; // 启动后运行过程中执行addFilter
}
} }
/** /**
@@ -409,12 +401,6 @@ public class HttpDispatcherServlet
} }
} }
} }
if (this.lazyHeaders && !Rest.isSimpleRestDyn(servlet)) {
this.lazyHeaders = false;
if (context != null) {
context.lazyHeaders = this.lazyHeaders; // 启动后运行过程中执行addServlet
}
}
allMapLock.lock(); allMapLock.lock();
try { // 需要整段锁住 try { // 需要整段锁住
for (String mappingPath : mappingPaths) { for (String mappingPath : mappingPaths) {

View File

@@ -123,6 +123,8 @@ public class HttpRequest extends Request<HttpContext> {
protected int chunkedLength = -1; protected int chunkedLength = -1;
protected int chunkedCurrOffset = -1;
protected byte[] chunkedHalfLenBytes; protected byte[] chunkedHalfLenBytes;
protected boolean rpc; protected boolean rpc;
@@ -172,11 +174,13 @@ public class HttpRequest extends Request<HttpContext> {
protected String locale; protected String locale;
private ByteArray array;
private String lastPathString; private String lastPathString;
private byte[] lastPathBytes; private byte[] lastPathBytes;
private final ByteArray array; private final ByteArray body;
private byte[] headerBytes; private byte[] headerBytes;
@@ -201,9 +205,9 @@ public class HttpRequest extends Request<HttpContext> {
this(context, new ByteArray()); this(context, new ByteArray());
} }
protected HttpRequest(HttpContext context, ByteArray array) { protected HttpRequest(HttpContext context, ByteArray body) {
super(context); super(context);
this.array = array; this.body = body;
this.remoteAddrHeader = context.remoteAddrHeader; this.remoteAddrHeader = context.remoteAddrHeader;
this.remoteAddrHeaders = context.remoteAddrHeaders; this.remoteAddrHeaders = context.remoteAddrHeaders;
this.localHeader = context.localHeader; this.localHeader = context.localHeader;
@@ -214,7 +218,7 @@ public class HttpRequest extends Request<HttpContext> {
@SuppressWarnings("OverridableMethodCallInConstructor") @SuppressWarnings("OverridableMethodCallInConstructor")
protected HttpRequest(HttpContext context, WebRequest req) { protected HttpRequest(HttpContext context, WebRequest req) {
super(context); super(context);
this.array = new ByteArray(); this.body = new ByteArray();
this.remoteAddrHeader = null; this.remoteAddrHeader = null;
this.remoteAddrHeaders = null; this.remoteAddrHeaders = null;
this.localHeader = null; this.localHeader = null;
@@ -230,7 +234,7 @@ public class HttpRequest extends Request<HttpContext> {
this.rpc = req.rpc; this.rpc = req.rpc;
this.traceid = req.getTraceid(); this.traceid = req.getTraceid();
if (req.getBody() != null) { if (req.getBody() != null) {
this.array.put(req.getBody()); this.body.put(req.getBody());
} }
if (req.getHeaders() != null) { if (req.getHeaders() != null) {
this.headers.setAll(req.getHeaders()); this.headers.setAll(req.getHeaders());
@@ -261,7 +265,7 @@ public class HttpRequest extends Request<HttpContext> {
public WebRequest createSimpleRequest(String contextPath) { public WebRequest createSimpleRequest(String contextPath) {
WebRequest req = new WebRequest(); WebRequest req = new WebRequest();
req.setBody(array.length() == 0 ? null : array.getBytes()); req.setBody(body.length() == 0 ? null : body.getBytes());
if (!getHeaders().isEmpty()) { if (!getHeaders().isEmpty()) {
req.setHeaders(headers); req.setHeaders(headers);
if (headers.contains(Rest.REST_HEADER_RPC)) { // 外部request不能包含RPC的header信息 if (headers.contains(Rest.REST_HEADER_RPC)) { // 外部request不能包含RPC的header信息
@@ -319,7 +323,7 @@ public class HttpRequest extends Request<HttpContext> {
@Override @Override
protected int readHeader(final ByteBuffer buf, final Request last) { protected int readHeader(final ByteBuffer buf, final Request last) {
final ByteBuffer buffer = buf; final ByteBuffer buffer = buf;
ByteArray bytes = array; ByteArray bytes = body;
if (this.readState == READ_STATE_ROUTE) { if (this.readState == READ_STATE_ROUTE) {
int rs = readMethodUriLine(buffer); int rs = readMethodUriLine(buffer);
if (rs != 0) { if (rs != 0) {
@@ -350,6 +354,7 @@ public class HttpRequest extends Request<HttpContext> {
this.expect = httpLast.expect; this.expect = httpLast.expect;
this.chunked = httpLast.chunked; this.chunked = httpLast.chunked;
this.chunkedLength = httpLast.chunkedLength; this.chunkedLength = httpLast.chunkedLength;
this.chunkedCurrOffset = httpLast.chunkedCurrOffset;
this.rpc = httpLast.rpc; this.rpc = httpLast.rpc;
this.traceid = httpLast.traceid; this.traceid = httpLast.traceid;
this.currentUserid = httpLast.currentUserid; this.currentUserid = httpLast.currentUserid;
@@ -362,7 +367,7 @@ public class HttpRequest extends Request<HttpContext> {
this.headerBytes = httpLast.headerBytes; this.headerBytes = httpLast.headerBytes;
this.headerParsed = httpLast.headerParsed; this.headerParsed = httpLast.headerParsed;
this.headers.setAll(httpLast.headers); this.headers.setAll(httpLast.headers);
} else if (context.lazyHeaders && getmethod) { // 非GET必须要读header会有Content-Length } else if (context.lazyHeaders) { // 非lazy必须要读header会有Content-Length
int rs = loadHeaderBytes(buffer); int rs = loadHeaderBytes(buffer);
if (rs != 0) { if (rs != 0) {
buffer.clear(); buffer.clear();
@@ -395,8 +400,7 @@ public class HttpRequest extends Request<HttpContext> {
} }
if (this.readState == READ_STATE_BODY) { if (this.readState == READ_STATE_BODY) {
if (this.chunked) { if (this.chunked) {
// TODO 待实现 return readChunkedBody(buffer);
return -1;
} }
if (this.contentLength > 0 && (this.contentType == null || !this.boundary)) { if (this.contentLength > 0 && (this.contentType == null || !this.boundary)) {
if (this.contentLength > context.getMaxBody()) { if (this.contentLength > context.getMaxBody()) {
@@ -432,9 +436,18 @@ public class HttpRequest extends Request<HttpContext> {
return 0; return 0;
} }
// TODO 待实现
private int readChunkedBody(final ByteBuffer buf) {
if (this.chunkedLength < 0) {
int size;
}
ByteArray bodyBytes = this.body;
return -1;
}
private int loadHeaderBytes(final ByteBuffer buf) { private int loadHeaderBytes(final ByteBuffer buf) {
final ByteBuffer buffer = buf; final ByteBuffer buffer = buf;
ByteArray bytes = array; ByteArray bytes = body; // body当temp buffer使用
int remain = buffer.remaining(); int remain = buffer.remaining();
byte b1, b2, b3, b4; byte b1, b2, b3, b4;
for (; ; ) { for (; ; ) {
@@ -507,7 +520,7 @@ public class HttpRequest extends Request<HttpContext> {
Charset charset = this.context.getCharset(); Charset charset = this.context.getCharset();
int remain = buffer.remaining(); int remain = buffer.remaining();
int size; int size;
ByteArray bytes = array; ByteArray bytes = body; // body当temp buffer使用
// 读method // 读method
if (this.method == null) { if (this.method == null) {
boolean flag = false; boolean flag = false;
@@ -954,10 +967,10 @@ public class HttpRequest extends Request<HttpContext> {
if (headerBytes == null) { if (headerBytes == null) {
return; return;
} }
if (array.isEmpty()) { if (body.isEmpty()) { // body当temp buffer使用
readHeaderLines(ByteBuffer.wrap(headerBytes), array); readHeaderLines(ByteBuffer.wrap(headerBytes), body);
array.clear(); body.clear();
} else { // array存有body数据 } else { // 存有body数据
readHeaderLines(ByteBuffer.wrap(headerBytes), new ByteArray()); readHeaderLines(ByteBuffer.wrap(headerBytes), new ByteArray());
} }
} }
@@ -1090,7 +1103,7 @@ public class HttpRequest extends Request<HttpContext> {
if (!PIPELINE_SAME_HEADERS || !context.lazyHeaders) { if (!PIPELINE_SAME_HEADERS || !context.lazyHeaders) {
return null; return null;
} }
HttpRequest req = new HttpRequest(context, this.array); HttpRequest req = new HttpRequest(context, this.body);
req.headerLength = this.headerLength; req.headerLength = this.headerLength;
req.headerBytes = this.headerBytes; req.headerBytes = this.headerBytes;
req.headerParsed = this.headerParsed; req.headerParsed = this.headerParsed;
@@ -1143,6 +1156,7 @@ public class HttpRequest extends Request<HttpContext> {
this.expect = false; this.expect = false;
this.chunked = false; this.chunked = false;
this.chunkedLength = -1; this.chunkedLength = -1;
this.chunkedCurrOffset = -1;
this.chunkedHalfLenBytes = null; this.chunkedHalfLenBytes = null;
this.rpc = false; this.rpc = false;
this.readState = READ_STATE_ROUTE; this.readState = READ_STATE_ROUTE;
@@ -1167,7 +1181,7 @@ public class HttpRequest extends Request<HttpContext> {
this.annotations = null; this.annotations = null;
this.remoteAddr = null; this.remoteAddr = null;
this.params.clear(); this.params.clear();
this.array.clear(); this.body.clear();
// 内部 // 内部
this.actionEntry = null; this.actionEntry = null;
super.recycle(); super.recycle();
@@ -1186,29 +1200,36 @@ public class HttpRequest extends Request<HttpContext> {
unzipEncoding(); unzipEncoding();
} }
if (this.getContentType() != null && this.contentType.toLowerCase().contains("x-www-form-urlencoded")) { if (this.getContentType() != null && this.contentType.toLowerCase().contains("x-www-form-urlencoded")) {
addParameter(array, true, 0, array.length()); addParameter(body, true, 0, body.length());
} }
} }
protected ByteArray array() {
if (array == null) {
array = new ByteArray();
}
return array;
}
protected void unzipEncoding() { protected void unzipEncoding() {
try { try {
if ("gzip".contains(this.contentEncoding)) { if ("gzip".equalsIgnoreCase(this.contentEncoding)) {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream(array.content(), 0, array.length()); ByteArrayInputStream in = new ByteArrayInputStream(body.content(), 0, body.length());
GZIPInputStream ungzip = new GZIPInputStream(in); GZIPInputStream ungzip = new GZIPInputStream(in);
int n; int n;
byte[] buffer = new byte[512]; byte[] buffer = array().content();
while ((n = ungzip.read(buffer)) >= 0) { while ((n = ungzip.read(buffer)) > 0) {
out.write(buffer, 0, n); out.write(buffer, 0, n);
} }
array.clear(); body.clear();
array.put(out.toByteArray()); body.put(out.toByteArray());
} else if ("deflate".contains(this.contentEncoding)) { } else if ("deflate".equalsIgnoreCase(this.contentEncoding)) {
Inflater infl = new Inflater(); Inflater infl = new Inflater();
infl.setInput(array.content(), 0, array.length()); infl.setInput(body.content(), 0, body.length());
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
int n; int n;
byte[] buffer = new byte[512]; byte[] buffer = array().content();
while (!infl.finished()) { while (!infl.finished()) {
n = infl.inflate(buffer); n = infl.inflate(buffer);
if (n == 0) { if (n == 0) {
@@ -1217,37 +1238,37 @@ public class HttpRequest extends Request<HttpContext> {
out.write(buffer, 0, n); out.write(buffer, 0, n);
} }
infl.end(); infl.end();
array.clear(); body.clear();
array.put(out.toByteArray()); body.put(out.toByteArray());
} }
} catch (Exception e) { } catch (Exception e) {
// do nothing // do nothing
} }
} }
private void addParameter(final ByteArray array, final boolean body, final int offset, final int len) { private void addParameter(final ByteArray bytes, final boolean body, final int offset, final int len) {
if (len < 1) { if (len < 1) {
return; return;
} }
Charset charset = this.context.getCharset(); Charset charset = this.context.getCharset();
int limit = offset + len; int limit = offset + len;
int keypos = array.indexOf(offset, limit, '='); int keypos = bytes.indexOf(offset, limit, '=');
int valpos = array.indexOf(offset, limit, '&'); int valpos = bytes.indexOf(offset, limit, '&');
if (keypos <= 0 || (valpos >= 0 && valpos < keypos)) { if (keypos <= 0 || (valpos >= 0 && valpos < keypos)) {
if (valpos > 0) { if (valpos > 0) {
addParameter(array, body, valpos + 1, limit - valpos - 1); addParameter(bytes, body, valpos + 1, limit - valpos - 1);
} }
return; return;
} }
String name = toDecodeString(array, offset, keypos - offset, charset); String name = toDecodeString(bytes, offset, keypos - offset, charset);
if (body && !name.isEmpty() && name.charAt(0) == '<') { if (body && !name.isEmpty() && name.charAt(0) == '<') {
return; // 内容可能是xml格式; 如: <?xml version="1.0" return; // 内容可能是xml格式; 如: <?xml version="1.0"
} }
++keypos; ++keypos;
String value = toDecodeString(array, keypos, (valpos < 0) ? (limit - keypos) : (valpos - keypos), charset); String value = toDecodeString(bytes, keypos, (valpos < 0) ? (limit - keypos) : (valpos - keypos), charset);
this.params.put(name, value); this.params.put(name, value);
if (valpos >= 0) { if (valpos >= 0) {
addParameter(array, body, valpos + 1, limit - valpos - 1); addParameter(bytes, body, valpos + 1, limit - valpos - 1);
} }
} }
@@ -1297,8 +1318,8 @@ public class HttpRequest extends Request<HttpContext> {
return this; return this;
} }
protected static String toDecodeString(ByteArray array, int offset, int len, final Charset charset) { protected static String toDecodeString(ByteArray bytes, int offset, int len, final Charset charset) {
byte[] content = array.content(); byte[] content = bytes.content();
if (len == 1) { if (len == 1) {
return Character.toString(content[offset]); return Character.toString(content[offset]);
} else if (len == 2 && content[offset] >= 0x20 && content[offset] < 0x80) { } else if (len == 2 && content[offset] >= 0x20 && content[offset] < 0x80) {
@@ -1672,7 +1693,7 @@ public class HttpRequest extends Request<HttpContext> {
* @return 内容 * @return 内容
*/ */
public String getBody(final Charset charset) { public String getBody(final Charset charset) {
return charset == null ? array.toString() : array.toString(charset); return charset == null ? body.toString() : body.toString(charset);
} }
/** /**
@@ -1682,7 +1703,7 @@ public class HttpRequest extends Request<HttpContext> {
*/ */
@ConvertDisabled @ConvertDisabled
public String getBodyUTF8() { public String getBodyUTF8() {
return array.toString(StandardCharsets.UTF_8); return body.toString(StandardCharsets.UTF_8);
} }
/** /**
@@ -1693,7 +1714,7 @@ public class HttpRequest extends Request<HttpContext> {
* @return 内容 * @return 内容
*/ */
public <T> T getBodyJson(java.lang.reflect.Type type) { public <T> T getBodyJson(java.lang.reflect.Type type) {
if (isEmpty(array)) { if (isEmpty(body)) {
return null; return null;
} }
Convert convert = this.reqConvert; Convert convert = this.reqConvert;
@@ -1701,9 +1722,9 @@ public class HttpRequest extends Request<HttpContext> {
convert = context.getJsonConvert(); convert = context.getJsonConvert();
} }
if (type == byte[].class) { if (type == byte[].class) {
return (T) array.getBytes(); return (T) body.getBytes();
} }
return (T) convert.convertFrom(type, array.content()); return (T) convert.convertFrom(type, body.content());
} }
/** /**
@@ -1715,13 +1736,13 @@ public class HttpRequest extends Request<HttpContext> {
* @return 内容 * @return 内容
*/ */
public <T> T getBodyJson(Convert convert, java.lang.reflect.Type type) { public <T> T getBodyJson(Convert convert, java.lang.reflect.Type type) {
if (isEmpty(array)) { if (isEmpty(body)) {
return null; return null;
} }
if (type == byte[].class) { if (type == byte[].class) {
return (T) array.getBytes(); return (T) body.getBytes();
} }
return (T) convert.convertFrom(type, array.content()); return (T) convert.convertFrom(type, body.content());
} }
/** /**
@@ -1730,7 +1751,7 @@ public class HttpRequest extends Request<HttpContext> {
* @return 内容 * @return 内容
*/ */
public byte[] getBody() { public byte[] getBody() {
return array.length() == 0 ? null : array.getBytes(); return body.length() == 0 ? null : body.getBytes();
} }
/** /**
@@ -1740,7 +1761,7 @@ public class HttpRequest extends Request<HttpContext> {
*/ */
@ConvertDisabled @ConvertDisabled
protected ByteArray getDirectBody() { protected ByteArray getDirectBody() {
return array; return body;
} }
@Override @Override
@@ -1761,8 +1782,8 @@ public class HttpRequest extends Request<HttpContext> {
+ (this.getHost() != null ? (", \r\n host: " + this.host) : "") + (this.getHost() != null ? (", \r\n host: " + this.host) : "")
+ (this.getContentLength() >= 0 ? (", \r\n contentLength: " + this.contentLength) : "") + (this.getContentLength() >= 0 ? (", \r\n contentLength: " + this.contentLength) : "")
+ (this.contentEncoding != null ? (", \r\n contentEncoding: " + this.contentEncoding) : "") + (this.contentEncoding != null ? (", \r\n contentEncoding: " + this.contentEncoding) : "")
+ (this.array.length() > 0 ? (", \r\n bodyLength: " + this.array.length()) : "") + (this.body.length() > 0 ? (", \r\n bodyLength: " + this.body.length()) : "")
+ (this.boundary || this.array.isEmpty() + (this.boundary || this.body.isEmpty()
? "" ? ""
: (", \r\n bodyContent: " : (", \r\n bodyContent: "
+ (this.respConvertType == null || this.respConvertType == ConvertType.JSON + (this.respConvertType == null || this.respConvertType == ConvertType.JSON
@@ -1815,10 +1836,10 @@ public class HttpRequest extends Request<HttpContext> {
context.getCharset(), context.getCharset(),
this.getContentType(), this.getContentType(),
this.params.map(), this.params.map(),
new BufferedInputStream(in, Math.max(array.length(), 8192)) { new BufferedInputStream(in, Math.max(body.length(), 8192)) {
{ {
array.copyTo(this.buf); body.copyTo(this.buf);
this.count = array.length(); this.count = body.length();
} }
}, },
null); null);

View File

@@ -398,6 +398,7 @@ public class HttpServer extends Server<String, HttpContext, HttpRequest, HttpRes
final List<String[]> defaultAddHeaders = new ArrayList<>(); final List<String[]> defaultAddHeaders = new ArrayList<>();
final List<String[]> defaultSetHeaders = new ArrayList<>(); final List<String[]> defaultSetHeaders = new ArrayList<>();
boolean autoOptions = false; boolean autoOptions = false;
boolean lazyHeader = false;
int datePeriod = 0; int datePeriod = 0;
String plainContentType = null; String plainContentType = null;
String jsonContentType = null; String jsonContentType = null;
@@ -408,10 +409,12 @@ public class HttpServer extends Server<String, HttpContext, HttpRequest, HttpRes
AnyValue rpcAuthenticatorConfig = null; AnyValue rpcAuthenticatorConfig = null;
if (config != null) { if (config != null) {
AnyValue reqs = config.getAnyValue("request"); lazyHeader = config.getBoolValue("lazy", false); // 兼容旧配置
if (reqs != null) { AnyValue reqConf = config.getAnyValue("request");
rpcAuthenticatorConfig = reqs.getAnyValue("rpc"); if (reqConf != null) {
AnyValue raddr = reqs.getAnyValue("remoteaddr"); lazyHeader = reqConf.getBoolValue("lazyHeader", lazyHeader);
rpcAuthenticatorConfig = reqConf.getAnyValue("rpc");
AnyValue raddr = reqConf.getAnyValue("remoteaddr");
remoteAddrHeader = raddr == null ? null : raddr.getValue("value"); remoteAddrHeader = raddr == null ? null : raddr.getValue("value");
if (remoteAddrHeader != null) { if (remoteAddrHeader != null) {
if (remoteAddrHeader.startsWith("request.headers.")) { if (remoteAddrHeader.startsWith("request.headers.")) {
@@ -420,7 +423,7 @@ public class HttpServer extends Server<String, HttpContext, HttpRequest, HttpRes
remoteAddrHeader = null; remoteAddrHeader = null;
} }
} }
AnyValue rlocale = reqs.getAnyValue("locale"); AnyValue rlocale = reqConf.getAnyValue("locale");
String vlocale = rlocale == null ? null : rlocale.getValue("value"); String vlocale = rlocale == null ? null : rlocale.getValue("value");
if (vlocale != null && !vlocale.isEmpty()) { if (vlocale != null && !vlocale.isEmpty()) {
if (vlocale.startsWith("request.headers.")) { if (vlocale.startsWith("request.headers.")) {
@@ -436,17 +439,17 @@ public class HttpServer extends Server<String, HttpContext, HttpRequest, HttpRes
} }
} }
AnyValue resps = config.getAnyValue("response"); AnyValue respConf = config.getAnyValue("response");
if (resps != null) { if (respConf != null) {
AnyValue contenttypes = resps.getAnyValue("content-type"); AnyValue contenttypes = respConf.getAnyValue("content-type");
if (contenttypes == null) { if (contenttypes == null) {
contenttypes = resps.getAnyValue("contenttype"); // 兼容旧的 contenttypes = respConf.getAnyValue("contenttype"); // 兼容旧的
} }
if (contenttypes != null) { if (contenttypes != null) {
plainContentType = contenttypes.getValue("plain"); plainContentType = contenttypes.getValue("plain");
jsonContentType = contenttypes.getValue("json"); jsonContentType = contenttypes.getValue("json");
} }
AnyValue[] addHeaders = resps.getAnyValues("addheader"); AnyValue[] addHeaders = respConf.getAnyValues("addheader");
if (addHeaders.length > 0) { if (addHeaders.length > 0) {
for (AnyValue addHeader : addHeaders) { for (AnyValue addHeader : addHeaders) {
String val = addHeader.getValue("value"); String val = addHeader.getValue("value");
@@ -471,7 +474,7 @@ public class HttpServer extends Server<String, HttpContext, HttpRequest, HttpRes
} }
} }
} }
AnyValue[] setHeaders = resps.getAnyValues("setheader"); AnyValue[] setHeaders = respConf.getAnyValues("setheader");
if (setHeaders.length > 0) { if (setHeaders.length > 0) {
for (AnyValue setHeader : setHeaders) { for (AnyValue setHeader : setHeaders) {
String val = setHeader.getValue("value"); String val = setHeader.getValue("value");
@@ -496,7 +499,7 @@ public class HttpServer extends Server<String, HttpContext, HttpRequest, HttpRes
} }
} }
} }
AnyValue defcookieValue = resps.getAnyValue("defcookie"); AnyValue defcookieValue = respConf.getAnyValue("defcookie");
if (defcookieValue != null) { if (defcookieValue != null) {
String domain = defcookieValue.getValue("domain"); String domain = defcookieValue.getValue("domain");
String path = defcookieValue.getValue("path"); String path = defcookieValue.getValue("path");
@@ -506,10 +509,10 @@ public class HttpServer extends Server<String, HttpContext, HttpRequest, HttpRes
defaultCookie.setPath(path); defaultCookie.setPath(path);
} }
} }
AnyValue options = resps.getAnyValue("options"); AnyValue options = respConf.getAnyValue("options");
autoOptions = options != null && options.getBoolValue("auto", false); autoOptions = options != null && options.getBoolValue("auto", false);
AnyValue dates = resps.getAnyValue("date"); AnyValue dates = respConf.getAnyValue("date");
datePeriod = dates == null ? 0 : dates.getIntValue("period", 0); datePeriod = dates == null ? 0 : dates.getIntValue("period", 0);
} }
} }
@@ -549,7 +552,7 @@ public class HttpServer extends Server<String, HttpContext, HttpRequest, HttpRes
} }
} }
HttpRender httpRender = null; HttpRender httpRender = null;
AnyValue renderConfig = null; AnyValue renderConfig;
{ // 设置TemplateEngine { // 设置TemplateEngine
renderConfig = config.getAnyValue("render"); renderConfig = config.getAnyValue("render");
if (renderConfig != null) { if (renderConfig != null) {
@@ -592,6 +595,7 @@ public class HttpServer extends Server<String, HttpContext, HttpRequest, HttpRes
contextConfig.remoteAddrHeader = addrHeader; contextConfig.remoteAddrHeader = addrHeader;
contextConfig.remoteAddrHeaders = null; contextConfig.remoteAddrHeaders = null;
} }
contextConfig.lazyHeaders = lazyHeader;
contextConfig.localHeader = localHeader; contextConfig.localHeader = localHeader;
contextConfig.localParameter = localParameter; contextConfig.localParameter = localParameter;
contextConfig.rpcAuthenticatorConfig = rpcAuthenticatorConfig; contextConfig.rpcAuthenticatorConfig = rpcAuthenticatorConfig;

View File

@@ -54,12 +54,15 @@ public class RestSleepTest {
OutputStream out = socket.getOutputStream(); OutputStream out = socket.getOutputStream();
out.write(("GET /test/sleep200 HTTP/1.1\r\n" out.write(("GET /test/sleep200 HTTP/1.1\r\n"
+ "Connection: Keep-Alive\r\n" + "Connection: Keep-Alive\r\n"
+ "Content-Length: 0\r\n"
+ "\r\n" + "\r\n"
+ "GET /test/sleep300 HTTP/1.1\r\n" + "GET /test/sleep300 HTTP/1.1\r\n"
+ "Connection: Keep-Alive\r\n" + "Connection: Keep-Alive\r\n"
+ "Content-Length: 0\r\n"
+ "\r\n" + "\r\n"
+ "GET /test/sleep500 HTTP/1.1\r\n" + "GET /test/sleep500 HTTP/1.1\r\n"
+ "Connection: Keep-Alive\r\n" + "Connection: Keep-Alive\r\n"
+ "Content-Length: 0\r\n"
+ "\r\n") + "\r\n")
.getBytes()); .getBytes());
InputStream in = socket.getInputStream(); InputStream in = socket.getInputStream();