diff --git a/src/main/java/org/redkale/boot/ApiDocCommand.java b/src/main/java/org/redkale/boot/ApiDocCommand.java index 97a55d7e2..d7b63da18 100644 --- a/src/main/java/org/redkale/boot/ApiDocCommand.java +++ b/src/main/java/org/redkale/boot/ApiDocCommand.java @@ -72,8 +72,8 @@ public final class ApiDocCommand { } List serverList = new ArrayList<>(); - Field __prefix = HttpServlet.class.getDeclaredField("_prefix"); - __prefix.setAccessible(true); + Field prefixField = HttpServlet.class.getDeclaredField("_prefix"); + prefixField.setAccessible(true); Map>> typesMap = new LinkedHashMap<>(); //https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md Map swaggerPathsMap = new LinkedHashMap<>(); @@ -117,7 +117,7 @@ public final class ApiDocCommand { } final String tag = ws.name().isEmpty() ? servlet.getClass().getSimpleName().replace("Servlet", "").toLowerCase() : ws.name(); final Map servletMap = new LinkedHashMap<>(); - String prefix = (String) __prefix.get(servlet); + String prefix = (String) prefixField.get(servlet); String[] urlregs = ws.value(); if (prefix != null && !prefix.isEmpty()) { for (int i = 0; i < urlregs.length; i++) { @@ -214,7 +214,7 @@ public final class ApiDocCommand { // typesMap.put(rtype.getName(), typeMap); // } mappingMap.put("results", results); - boolean hasbodyparam = false; + boolean hasBodyParam = false; Map swaggerRequestBody = new LinkedHashMap<>(); for (HttpParam param : method.getAnnotationsByType(HttpParam.class)) { final Map oldapisParamMap = new LinkedHashMap<>(); @@ -262,7 +262,7 @@ public final class ApiDocCommand { } } if (param.style() == HttpParam.HttpParameterStyle.BODY) { - hasbodyparam = true; + hasBodyParam = true; } if (ptype.isPrimitive() || ptype == String.class) { continue; @@ -354,7 +354,7 @@ public final class ApiDocCommand { String m = action.methods() == null || action.methods().length == 0 ? null : action.methods()[0].toLowerCase(); if (m == null) { - m = hasbodyparam || TYPE_RETRESULT_STRING.equals(resultType) || TYPE_RETRESULT_INTEGER.equals(resultType) + m = hasBodyParam || TYPE_RETRESULT_STRING.equals(resultType) || TYPE_RETRESULT_INTEGER.equals(resultType) || TYPE_RETRESULT_LONG.equals(resultType) || action.name().contains("create") || action.name().contains("insert") || action.name().contains("update") || action.name().contains("delete") || action.name().contains("send") ? "post" : "get"; } diff --git a/src/main/java/org/redkale/boot/LoggingFileHandler.java b/src/main/java/org/redkale/boot/LoggingFileHandler.java index 8ebbd0d10..20d3d2a44 100644 --- a/src/main/java/org/redkale/boot/LoggingFileHandler.java +++ b/src/main/java/org/redkale/boot/LoggingFileHandler.java @@ -71,7 +71,7 @@ public class LoggingFileHandler extends LoggingBaseHandler { } } - protected final LinkedBlockingQueue logqueue = new LinkedBlockingQueue(); + protected final LinkedBlockingQueue logQueue = new LinkedBlockingQueue(); protected String pattern; @@ -83,9 +83,9 @@ public class LoggingFileHandler extends LoggingBaseHandler { private int limit; //文件大小限制 - private final AtomicInteger logindex = new AtomicInteger(); + private final AtomicInteger logIndex = new AtomicInteger(); - private final AtomicInteger logunusualindex = new AtomicInteger(); + private final AtomicInteger logUnusualIndex = new AtomicInteger(); private int count = 1; //文件限制 @@ -93,19 +93,19 @@ public class LoggingFileHandler extends LoggingBaseHandler { protected boolean append; - protected Pattern denyregx; + protected Pattern denyRegx; private final AtomicLong logLength = new AtomicLong(); private final AtomicLong logUnusualLength = new AtomicLong(); - private File logfile; + private File logFile; - private File logunusualfile; + private File logUnusualFile; - private OutputStream logstream; + private OutputStream logStream; - private OutputStream logunusualstream; + private OutputStream logUnusualStream; public LoggingFileHandler() { updateTomorrow(); @@ -122,7 +122,7 @@ public class LoggingFileHandler extends LoggingBaseHandler { cal.add(Calendar.DAY_OF_YEAR, 1); long t = cal.getTimeInMillis(); if (this.tomorrow != t) { - logindex.set(0); + logIndex.set(0); } this.tomorrow = t; } @@ -139,68 +139,68 @@ public class LoggingFileHandler extends LoggingBaseHandler { public void run() { while (true) { try { - LogRecord log = logqueue.take(); + LogRecord log = logQueue.take(); final boolean bigger = (limit > 0 && limit <= logLength.get()); final boolean changeday = tomorrow <= log.getMillis(); if (bigger || changeday) { updateTomorrow(); - if (logstream != null) { - logstream.close(); + if (logStream != null) { + logStream.close(); if (bigger) { - for (int i = Math.min(count - 2, logindex.get() - 1); i > 0; i--) { - File greater = new File(logfile.getPath() + "." + i); + for (int i = Math.min(count - 2, logIndex.get() - 1); i > 0; i--) { + File greater = new File(logFile.getPath() + "." + i); if (greater.exists()) { - Files.move(greater.toPath(), new File(logfile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE); + Files.move(greater.toPath(), new File(logFile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE); } } - Files.move(logfile.toPath(), new File(logfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE); + Files.move(logFile.toPath(), new File(logFile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE); } else { - if (logfile.exists() && logfile.length() < 1) { - Files.delete(logfile.toPath()); + if (logFile.exists() && logFile.length() < 1) { + Files.delete(logFile.toPath()); } } - logstream = null; + logStream = null; } } - if (unusual != null && changeday && logunusualstream != null) { - logunusualstream.close(); + if (unusual != null && changeday && logUnusualStream != null) { + logUnusualStream.close(); if (limit > 0 && limit <= logUnusualLength.get()) { - for (int i = Math.min(count - 2, logunusualindex.get() - 1); i > 0; i--) { - File greater = new File(logunusualfile.getPath() + "." + i); + for (int i = Math.min(count - 2, logUnusualIndex.get() - 1); i > 0; i--) { + File greater = new File(logUnusualFile.getPath() + "." + i); if (greater.exists()) { - Files.move(greater.toPath(), new File(logunusualfile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE); + Files.move(greater.toPath(), new File(logUnusualFile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE); } } - Files.move(logunusualfile.toPath(), new File(logunusualfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE); + Files.move(logUnusualFile.toPath(), new File(logUnusualFile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE); } else { - if (logunusualfile.exists() && logunusualfile.length() < 1) { - Files.delete(logunusualfile.toPath()); + if (logUnusualFile.exists() && logUnusualFile.length() < 1) { + Files.delete(logUnusualFile.toPath()); } } - logunusualstream = null; + logUnusualStream = null; } - if (logstream == null) { - logindex.incrementAndGet(); - logfile = new File(patternDateFormat == null ? pattern : Times.formatTime(patternDateFormat, -1, System.currentTimeMillis())); - logfile.getParentFile().mkdirs(); - logLength.set(logfile.length()); - logstream = new FileOutputStream(logfile, append); + if (logStream == null) { + logIndex.incrementAndGet(); + logFile = new File(patternDateFormat == null ? pattern : Times.formatTime(patternDateFormat, -1, System.currentTimeMillis())); + logFile.getParentFile().mkdirs(); + logLength.set(logFile.length()); + logStream = new FileOutputStream(logFile, append); } - if (unusual != null && logunusualstream == null) { - logunusualindex.incrementAndGet(); - logunusualfile = new File(unusualDateFormat == null ? unusual : Times.formatTime(unusualDateFormat, -1, System.currentTimeMillis())); - logunusualfile.getParentFile().mkdirs(); - logUnusualLength.set(logunusualfile.length()); - logunusualstream = new FileOutputStream(logunusualfile, append); + if (unusual != null && logUnusualStream == null) { + logUnusualIndex.incrementAndGet(); + logUnusualFile = new File(unusualDateFormat == null ? unusual : Times.formatTime(unusualDateFormat, -1, System.currentTimeMillis())); + logUnusualFile.getParentFile().mkdirs(); + logUnusualLength.set(logUnusualFile.length()); + logUnusualStream = new FileOutputStream(logUnusualFile, append); } //----------------------写日志------------------------- String message = getFormatter().format(log); String encoding = getEncoding(); byte[] bytes = encoding == null ? message.getBytes() : message.getBytes(encoding); - logstream.write(bytes); + logStream.write(bytes); logLength.addAndGet(bytes.length); if (unusual != null && (log.getLevel() == Level.WARNING || log.getLevel() == Level.SEVERE)) { - logunusualstream.write(bytes); + logUnusualStream.write(bytes); logUnusualLength.addAndGet(bytes.length); } } catch (Exception e) { @@ -331,7 +331,7 @@ public class LoggingFileHandler extends LoggingBaseHandler { String denyregxstr = manager.getProperty(cname + ".denyregx"); try { if (denyregxstr != null && !denyregxstr.trim().isEmpty()) { - denyregx = Pattern.compile(denyregxstr); + denyRegx = Pattern.compile(denyregxstr); } } catch (Exception e) { //do nothing @@ -343,18 +343,18 @@ public class LoggingFileHandler extends LoggingBaseHandler { if (!isLoggable(log)) { return; } - if (denyregx != null && denyregx.matcher(log.getMessage()).find()) { + if (denyRegx != null && denyRegx.matcher(log.getMessage()).find()) { return; } fillLogRecord(log); - logqueue.offer(log); + logQueue.offer(log); } @Override public void flush() { try { - if (logstream != null) { - logstream.flush(); + if (logStream != null) { + logStream.flush(); } } catch (Exception e) { ErrorManager err = getErrorManager(); @@ -367,8 +367,8 @@ public class LoggingFileHandler extends LoggingBaseHandler { @Override public void close() throws SecurityException { try { - if (logstream != null) { - logstream.close(); + if (logStream != null) { + logStream.close(); } } catch (Exception e) { ErrorManager err = getErrorManager(); diff --git a/src/main/java/org/redkale/boot/PrepareCompiler.java b/src/main/java/org/redkale/boot/PrepareCompiler.java index 3c4cdac4f..5f09973c0 100644 --- a/src/main/java/org/redkale/boot/PrepareCompiler.java +++ b/src/main/java/org/redkale/boot/PrepareCompiler.java @@ -38,7 +38,7 @@ public class PrepareCompiler { listener.preCompile(application); } application.start(); - final boolean hasSncp = application.getNodeServers().stream().filter(v -> v instanceof NodeSncpServer).findFirst().isPresent(); + final boolean hasSncp = application.getNodeServers().stream().filter(NodeSncpServer.class::isInstance).findFirst().isPresent(); final ClassFilter entityFilter = new ClassFilter(application.getClassLoader(), Entity.class, Object.class, (Class[]) null); final ClassFilter entityFilter2 = new ClassFilter(application.getClassLoader(), javax.persistence.Entity.class, Object.class, (Class[]) null); diff --git a/src/main/java/org/redkale/mq/HttpMessageRequest.java b/src/main/java/org/redkale/mq/HttpMessageRequest.java index 42d1a49cc..92bfc562a 100644 --- a/src/main/java/org/redkale/mq/HttpMessageRequest.java +++ b/src/main/java/org/redkale/mq/HttpMessageRequest.java @@ -41,8 +41,8 @@ public class HttpMessageRequest extends HttpRequest { } @Override - public HttpMessageRequest setPath(String path) { - this.path = path; + public HttpMessageRequest setRequestPath(String path) { + this.requestPath = path; return this; } diff --git a/src/main/java/org/redkale/mq/HttpMessageResponse.java b/src/main/java/org/redkale/mq/HttpMessageResponse.java index e4846cae4..006d3971a 100644 --- a/src/main/java/org/redkale/mq/HttpMessageResponse.java +++ b/src/main/java/org/redkale/mq/HttpMessageResponse.java @@ -171,7 +171,7 @@ public class HttpMessageResponse extends HttpResponse { @Override public void finish(int status, String msg) { if (status > 400) { - messageClient.logger.log(Level.WARNING, "HttpMessageResponse.finish status: " + status + ", uri: " + this.request.getPath() + ", message: " + this.message); + messageClient.logger.log(Level.WARNING, "HttpMessageResponse.finish status: " + status + ", uri: " + this.request.getRequestPath() + ", message: " + this.message); } else if (messageClient.logger.isLoggable(Level.FINEST)) { messageClient.logger.log(Level.FINEST, "HttpMessageResponse.finish status: " + status); } diff --git a/src/main/java/org/redkale/net/client/ClientCodec.java b/src/main/java/org/redkale/net/client/ClientCodec.java index 4a6635c3c..11b34789a 100644 --- a/src/main/java/org/redkale/net/client/ClientCodec.java +++ b/src/main/java/org/redkale/net/client/ClientCodec.java @@ -42,6 +42,7 @@ public abstract class ClientCodec withMessageListener(ClientMessageListener listener) { diff --git a/src/main/java/org/redkale/net/http/HttpDispatcherServlet.java b/src/main/java/org/redkale/net/http/HttpDispatcherServlet.java index 0df932093..8c7b3a615 100644 --- a/src/main/java/org/redkale/net/http/HttpDispatcherServlet.java +++ b/src/main/java/org/redkale/net/http/HttpDispatcherServlet.java @@ -310,7 +310,7 @@ public class HttpDispatcherServlet extends DispatcherServlet @@ -132,7 +133,7 @@ public class HttpRequest extends Request { protected String protocol; - protected String path; + protected String requestPath; protected byte[] queryBytes; @@ -223,13 +224,9 @@ public class HttpRequest extends Request { this.contentType = req.getContentType(); this.remoteAddr = req.getRemoteAddr(); this.locale = req.getLocale(); - if (needPath) { - this.path = req.requestPath(); - } else { - this.path = req.getPath(); - } + this.requestPath = needPath ? req.requestPath() : req.getPath(); this.method = req.getMethod(); - if (req.getSessionid() != null && !req.getSessionid().isEmpty()) { + if (isNotEmpty(req.getSessionid())) { this.cookies = new HttpCookie[]{new HttpCookie(SESSIONID_NAME, req.getSessionid())}; } } @@ -255,8 +252,8 @@ public class HttpRequest extends Request { req.setContentType(getContentType()); req.setContextPath(prefixPath); req.setMethod(this.method); - String path0 = this.path; - if (prefixPath != null && !prefixPath.isEmpty() && path0.startsWith(prefixPath)) { + String path0 = this.requestPath; + if (isNotEmpty(prefixPath) && path0.startsWith(prefixPath)) { path0 = path0.substring(prefixPath.length()); } req.setPath(path0); @@ -565,7 +562,7 @@ public class HttpRequest extends Request { } //读uri - if (this.path == null) { + if (this.requestPath == null) { int qst = -1;//?的位置 boolean decodeable = false; boolean latin1 = true; @@ -589,7 +586,7 @@ public class HttpRequest extends Request { } size = bytes.length(); if (qst > 0) { //带?参数 - this.path = decodeable ? toDecodeString(bytes, 0, qst, charset) : context.loadUriPath(bytes, qst, latin1, charset);// bytes.toString(latin1, 0, qst, charset); + this.requestPath = decodeable ? toDecodeString(bytes, 0, qst, charset) : context.loadUriPath(bytes, qst, latin1, charset);// bytes.toString(latin1, 0, qst, charset); int qlen = size - qst - 1; this.queryBytes = bytes.getBytes(qst + 1, qlen); this.lastPathString = null; @@ -601,20 +598,20 @@ public class HttpRequest extends Request { } } else { if (decodeable) { //需要转义 - this.path = toDecodeString(bytes, 0, bytes.length(), charset); + this.requestPath = toDecodeString(bytes, 0, bytes.length(), charset); this.lastPathString = null; this.lastPathBytes = null; } else if (context.lazyHeaders) { byte[] lastURIBytes = lastPathBytes; if (lastURIBytes != null && lastURIBytes.length == size && bytes.deepEquals(lastURIBytes)) { - this.path = this.lastPathString; + this.requestPath = this.lastPathString; } else { - this.path = context.loadUriPath(bytes, latin1, charset);// bytes.toString(latin1, charset); - this.lastPathString = this.path; + this.requestPath = context.loadUriPath(bytes, latin1, charset);// bytes.toString(latin1, charset); + this.lastPathString = this.requestPath; this.lastPathBytes = bytes.getBytes(); } } else { - this.path = context.loadUriPath(bytes, latin1, charset); //bytes.toString(latin1, charset); + this.requestPath = context.loadUriPath(bytes, latin1, charset); //bytes.toString(latin1, charset); this.lastPathString = null; this.lastPathBytes = null; } @@ -984,7 +981,7 @@ public class HttpRequest extends Request { this.method = null; this.getmethod = false; this.protocol = null; - this.path = null; + this.requestPath = null; this.queryBytes = null; this.boundary = false; this.bodyParsed = false; @@ -1045,8 +1042,8 @@ public class HttpRequest extends Request { return this; } - protected HttpRequest setPath(String path) { - this.path = path; + protected HttpRequest setRequestPath(String path) { + this.requestPath = path; return this; } @@ -1534,7 +1531,7 @@ public class HttpRequest extends Request { @Override public String toString() { parseBody(); - return this.getClass().getSimpleName() + "{\r\n method: " + this.method + ", \r\n path: " + this.path + return this.getClass().getSimpleName() + "{\r\n method: " + this.method + ", \r\n path: " + this.requestPath + (this.reqConvertType != null ? (", \r\n reqConvertType: " + this.reqConvertType) : "") + (this.respConvertType != null ? (", \r\n respConvertType: " + this.respConvertType) : "") + (this.currentUserid != CURRUSERID_NIL ? (", \r\n currentUserid: " + (this.currentUserid == CURRUSERID_NIL ? null : this.currentUserid)) : "") @@ -1781,8 +1778,8 @@ public class HttpRequest extends Request { * * @return 请求的URL */ - public String getPath() { - return path; + public String getRequestPath() { + return requestPath; } /** @@ -1795,16 +1792,16 @@ public class HttpRequest extends Request { } /** - * 截取getPath最后的一个/后面的部分 + * 截取getRequestPath最后的一个/后面的部分 * * @return String */ @ConvertDisabled public String getPathLastParam() { - if (path == null) { + if (requestPath == null) { return ""; } - return path.substring(path.lastIndexOf('/') + 1); + return requestPath.substring(requestPath.lastIndexOf('/') + 1); } /** @@ -1969,10 +1966,10 @@ public class HttpRequest extends Request { * @return String[] */ public String[] getPathParams(String prefix) { - if (path == null || prefix == null) { + if (requestPath == null || prefix == null) { return new String[0]; } - return path.substring(path.indexOf(prefix) + prefix.length() + (prefix.endsWith("/") ? 0 : 1)).split("/"); + return requestPath.substring(requestPath.indexOf(prefix) + prefix.length() + (prefix.endsWith("/") ? 0 : 1)).split("/"); } /** @@ -1986,14 +1983,14 @@ public class HttpRequest extends Request { * @return prefix截断后的值 */ public String getPathParam(String prefix, String defvalue) { - if (path == null || prefix == null || prefix.isEmpty()) { + if (requestPath == null || prefix == null || prefix.isEmpty()) { return defvalue; } - int pos = path.indexOf(prefix); + int pos = requestPath.indexOf(prefix); if (pos < 0) { return defvalue; } - String sub = path.substring(pos + prefix.length()); + String sub = requestPath.substring(pos + prefix.length()); pos = sub.indexOf('/'); return pos < 0 ? sub : sub.substring(0, pos); } diff --git a/src/main/java/org/redkale/net/http/HttpResourceServlet.java b/src/main/java/org/redkale/net/http/HttpResourceServlet.java index 49a40c364..168d24fd9 100644 --- a/src/main/java/org/redkale/net/http/HttpResourceServlet.java +++ b/src/main/java/org/redkale/net/http/HttpResourceServlet.java @@ -212,7 +212,7 @@ public class HttpResourceServlet extends HttpServlet { @Override public void execute(HttpRequest request, HttpResponse response) throws IOException { - String uri = request.getPath(); + String uri = request.getRequestPath(); if (uri.contains("../")) { if (logger.isLoggable(Level.FINEST)) { logger.log(Level.FINEST, "Not found resource (404) be " + uri + ", request = " + request); @@ -254,7 +254,7 @@ public class HttpResourceServlet extends HttpServlet { } if (entry == null) { if (logger.isLoggable(Level.FINER)) { - logger.log(Level.FINER, "Not found resource (404), url = " + request.getPath()); + logger.log(Level.FINER, "Not found resource (404), url = " + request.getRequestPath()); } finish404(request, response); } else { diff --git a/src/main/java/org/redkale/net/http/HttpServlet.java b/src/main/java/org/redkale/net/http/HttpServlet.java index e5e380925..4864643e8 100644 --- a/src/main/java/org/redkale/net/http/HttpServlet.java +++ b/src/main/java/org/redkale/net/http/HttpServlet.java @@ -66,7 +66,7 @@ public class HttpServlet extends Servlet } } if (entry.cacheSeconds > 0) {//有缓存设置 - CacheEntry ce = entry.modeOneCache ? entry.oneCache : entry.cache.get(request.getPath()); + CacheEntry ce = entry.modeOneCache ? entry.oneCache : entry.cache.get(request.getRequestPath()); if (ce != null && ce.time + entry.cacheSeconds * 1000 > System.currentTimeMillis()) { //缓存有效 response.setStatus(ce.status); response.setContentType(ce.contentType); @@ -125,7 +125,7 @@ public class HttpServlet extends Servlet return; } for (Map.Entry en : mappings) { - if (request.getPath().startsWith(en.getKey())) { + if (request.getRequestPath().startsWith(en.getKey())) { ActionEntry entry = en.getValue(); if (!entry.checkMethod(request.getMethod())) { //response.finishJson(new RetResult(RET_METHOD_ERROR, "Method(" + request.getMethod() + ") Error")); @@ -146,7 +146,7 @@ public class HttpServlet extends Servlet } } finish404(request, response); - //throw new IOException(this.getClass().getName() + " not found method for URI(" + request.getPath() + ")"); + //throw new IOException(this.getClass().getName() + " not found method for URI(" + request.getRequestPath() + ")"); } }; @@ -411,7 +411,7 @@ public class HttpServlet extends Servlet return; } CacheEntry ce = new CacheEntry(response.getStatus(), response.getContentType(), content); - cache.put(response.getRequest().getPath(), ce); + cache.put(response.getRequest().getRequestPath(), ce); } : null; } else { //单一url this.modeOneCache = true; diff --git a/src/main/java/org/redkale/net/http/HttpSimpleClient.java b/src/main/java/org/redkale/net/http/HttpSimpleClient.java index 0c3175070..9a0a316e8 100644 --- a/src/main/java/org/redkale/net/http/HttpSimpleClient.java +++ b/src/main/java/org/redkale/net/http/HttpSimpleClient.java @@ -42,6 +42,8 @@ public class HttpSimpleClient extends Client { + protected static final Logger logger = Logger.getLogger(HttpSimpleCodec.class.getSimpleName()); + + private ByteArray recyclableArray; + + private ByteArray halfBytes; + + private HttpSimpleResult lastResult = null; + public HttpSimpleCodec(HttpSimpleConnection connection) { super(connection); } - @Override - public void decodeMessages(ByteBuffer buffer, ByteArray array) { + protected HttpSimpleResult pollResult(HttpSimpleRequest request) { + return new HttpSimpleResult(); + } + + protected void offerResult(HttpSimpleResult rs) { //do nothing } + private ByteArray pollArray(ByteArray array) { + if (recyclableArray == null) { + recyclableArray = new ByteArray(); + } + recyclableArray.clear(); + if (array != null) { + recyclableArray.put(array); + } + return recyclableArray; + } + + @Override + public void decodeMessages(final ByteBuffer realBuf, final ByteArray array) { + int rs; + HttpSimpleResult result = this.lastResult; + final ByteBuffer buffer = realBuf; + while (buffer.hasRemaining()) { + if (result == null) { + result = new HttpSimpleResult(); + this.lastResult = result; + } + array.clear(); + if (this.halfBytes != null) { + array.put(this.halfBytes); + this.halfBytes = null; + } + if (result.readState == READ_STATE_ROUTE) { + rs = readStatusLine(result, buffer, array); + if (rs > 0) { //数据不全 + this.halfBytes = pollArray(array); + return; + } else if (rs < 0) { //数据异常 + occurError(null, new HttpException("http data not valid")); + return; + } + result.readState = READ_STATE_HEADER; + } + if (result.readState == READ_STATE_HEADER) { + rs = readHeaderLines(result, buffer, array); + if (rs > 0) { //数据不全 + this.halfBytes = pollArray(array); + return; + } else if (rs < 0) { //数据异常 + occurError(null, new HttpException("http data not valid")); + return; + } + result.readState = READ_STATE_BODY; + } + if (result.readState == READ_STATE_BODY) { + rs = readBody(result, buffer, array); + if (rs > 0) { //数据不全 + this.halfBytes = pollArray(array); + return; + } else if (rs < 0) { //数据异常 + occurError(null, new HttpException("http data not valid")); + return; + } + result.readState = READ_STATE_END; + } + addMessage(nextRequest(), result); + lastResult = null; + } + } + + //解析 HTTP/1.1 200 OK + private int readStatusLine(final HttpSimpleResult result, final ByteBuffer buffer, final ByteArray array) { + int remain = buffer.remaining(); + if (array.length() > 0 && array.getLastByte() == '\r') { //array存在半截数据 + if (buffer.get() != '\n') { + return -1; + } + } else { + for (;;) { + if (remain-- < 1) { + return 1; + } + byte b = buffer.get(); + if (b == '\r') { + if (remain-- < 1) { + array.put((byte) '\r'); + return 1; + } + if (buffer.get() != '\n') { + return -1; + } + break; + } + array.put(b); + } + } + String value = array.toString(null); + int pos = value.indexOf(' '); + result.setStatus(Integer.decode(value.substring(pos + 1, value.indexOf(" ", pos + 2)))); + array.clear(); + return 0; + } + + //解析Header Connection: keep-alive + //返回0表示解析完整,非0表示还需继续读数据 + private int readHeaderLines(final HttpSimpleResult result, final ByteBuffer buffer, final ByteArray array) { + int remain = buffer.remaining(); + for (;;) { + array.clear(); + if (remain-- < 2) { + if (remain == 1) { + array.put(buffer.get()); + return 1; + } + return 1; + } + remain--; + byte b1 = buffer.get(); + byte b2 = buffer.get(); + if (b1 == '\r' && b2 == '\n') { + return 0; + } + boolean latin1 = true; + if (latin1 && (b1 < 0x20 || b1 >= 0x80)) { + latin1 = false; + } + if (latin1 && (b2 < 0x20 || b2 >= 0x80)) { + latin1 = false; + } + array.put(b1, b2); + for (;;) { // name + if (remain-- < 1) { + buffer.clear(); + buffer.put(array.content(), 0, array.length()); + return 1; + } + byte b = buffer.get(); + if (b == ':') { + break; + } else if (latin1 && (b < 0x20 || b >= 0x80)) { + latin1 = false; + } + array.put(b); + } + String name = parseHeaderName(latin1, array, null); + array.clear(); + boolean first = true; + int space = 0; + for (;;) { // value + if (remain-- < 1) { + buffer.clear(); + buffer.put(name.getBytes()); + buffer.put((byte) ':'); + if (space == 1) { + buffer.put((byte) ' '); + } else if (space > 0) { + for (int i = 0; i < space; i++) buffer.put((byte) ' '); + } + buffer.put(array.content(), 0, array.length()); + return 1; + } + byte b = buffer.get(); + if (b == '\r') { + if (remain-- < 1) { + buffer.clear(); + buffer.put(name.getBytes()); + buffer.put((byte) ':'); + if (space == 1) { + buffer.put((byte) ' '); + } else if (space > 0) { + for (int i = 0; i < space; i++) buffer.put((byte) ' '); + } + buffer.put(array.content(), 0, array.length()); + buffer.put((byte) '\r'); + return 1; + } + if (buffer.get() != '\n') { + return -1; + } + break; + } + if (first) { + if (b <= ' ') { + space++; + continue; + } + first = false; + } + array.put(b); + } + String value; + switch (name) { + case "Content-Length": + case "content-length": + value = array.toString(true, null); + result.contentLength = Integer.decode(value); + result.header(name, value); + break; + default: + value = array.toString(null); + result.header(name, value); + } + } + } + + private int readBody(final HttpSimpleResult result, final ByteBuffer buffer, final ByteArray array) { + return 0; + } } diff --git a/src/main/java/org/redkale/net/http/HttpSimpleRequest.java b/src/main/java/org/redkale/net/http/HttpSimpleRequest.java index 89fa0f4ed..e544f5a4f 100644 --- a/src/main/java/org/redkale/net/http/HttpSimpleRequest.java +++ b/src/main/java/org/redkale/net/http/HttpSimpleRequest.java @@ -15,6 +15,7 @@ import org.redkale.convert.*; import org.redkale.convert.json.JsonConvert; import org.redkale.net.client.ClientConnection; import org.redkale.net.client.ClientRequest; +import static org.redkale.net.http.HttpSimpleClient.*; import org.redkale.util.ByteArray; import org.redkale.util.RedkaleException; import org.redkale.util.Traces; @@ -109,13 +110,19 @@ public class HttpSimpleRequest extends ClientRequest implements java.io.Serializ @Override public void writeTo(ClientConnection conn, ByteArray array) { - array.put((method.toUpperCase() + " " + path + " HTTP/1.1\r\n" - + Rest.REST_HEADER_TRACEID + ": " + traceid + "\r\n" - + "Content-Length: " + (body == null ? 0 : body.length) + "\r\n").getBytes(StandardCharsets.UTF_8)); + array.put((method.toUpperCase() + " " + requestPath() + " HTTP/1.1\r\n").getBytes(StandardCharsets.UTF_8)); + if (traceid != null && !containsHeaderIgnoreCase(Rest.REST_HEADER_TRACEID)) { + array.put((Rest.REST_HEADER_TRACEID + ": " + traceid + "\r\n").getBytes(StandardCharsets.UTF_8)); + } + if (!containsHeaderIgnoreCase("User-Agent")) { + array.put(header_bytes_useragent); + } + if (!containsHeaderIgnoreCase("Connection")) { + array.put(header_bytes_connalive); + } + array.put(contentLengthBytes()); if (headers != null) { - headers.forEach((k, v) -> { - array.put((k + ": " + v + "\r\n").getBytes(StandardCharsets.UTF_8)); - }); + headers.forEach((k, v) -> array.put((k + ": " + v + "\r\n").getBytes(StandardCharsets.UTF_8))); } array.put((byte) '\r', (byte) '\n'); if (body != null) { @@ -123,6 +130,18 @@ public class HttpSimpleRequest extends ClientRequest implements java.io.Serializ } } + protected boolean containsHeaderIgnoreCase(String name) { + return headers != null && headers.containsIgnoreCase(name); + } + + protected byte[] contentLengthBytes() { + int len = body == null ? 0 : body.length; + if (len < contentLengthArray.length) { + return contentLengthArray[len]; + } + return ("Content-Length: " + len + "\r\n").getBytes(StandardCharsets.UTF_8); + } + @Nullable @ConvertDisabled public String getParametersToString() { @@ -493,4 +512,11 @@ public class HttpSimpleRequest extends ClientRequest implements java.io.Serializ return JsonConvert.root().convertTo(this); } + private static final byte[][] contentLengthArray = new byte[1000][]; + + static { + for (int i = 0; i < contentLengthArray.length; i++) { + contentLengthArray[i] = ("Content-Length: " + i + "\r\n").getBytes(); + } + } } diff --git a/src/main/java/org/redkale/net/http/HttpSimpleResult.java b/src/main/java/org/redkale/net/http/HttpSimpleResult.java index 00e05484f..21f632bb0 100644 --- a/src/main/java/org/redkale/net/http/HttpSimpleResult.java +++ b/src/main/java/org/redkale/net/http/HttpSimpleResult.java @@ -4,6 +4,7 @@ package org.redkale.net.http; import org.redkale.net.client.ClientResult; +import static org.redkale.net.http.HttpSimpleClient.ClientReadCompletionHandler.READ_STATE_ROUTE; /** * @@ -17,6 +18,14 @@ import org.redkale.net.client.ClientResult; */ class HttpSimpleResult extends HttpResult implements ClientResult { + int readState = READ_STATE_ROUTE; + + int contentLength = -1; + + byte[] headerBytes; + + boolean headerParsed = false; + @Override public boolean isKeepAlive() { return true; diff --git a/src/main/java/org/redkale/net/http/Rest.java b/src/main/java/org/redkale/net/http/Rest.java index 3c186a86f..8576982ff 100644 --- a/src/main/java/org/redkale/net/http/Rest.java +++ b/src/main/java/org/redkale/net/http/Rest.java @@ -1386,7 +1386,7 @@ public final class Rest { } else if (annlocale != null) { //HttpRequest.getLocale } else if (annbody != null) { //HttpRequest.getBodyUTF8 / HttpRequest.getBody } else if (annfile != null) { //MultiContext.partsFirstBytes / HttpRequest.partsFirstFile / HttpRequest.partsFiles - } else if (annpath != null) { //HttpRequest.getPath + } else if (annpath != null) { //HttpRequest.getRequestPath } else if (annuserid != null) { //HttpRequest.currentUserid } else if (pname != null && pname.charAt(0) == '#') { //从request.getPathParam 中去参数 } else if ("#".equals(pname)) { //从request.getRequstURI 中取参数 @@ -2590,9 +2590,9 @@ public final class Rest { mv.visitVarInsn(ALOAD, 4); mv.visitVarInsn(ASTORE, maxLocals); varInsns.add(new int[]{ALOAD, maxLocals}); - } else if (annpath != null) { //HttpRequest.getPath + } else if (annpath != null) { //HttpRequest.getRequestPath mv.visitVarInsn(ALOAD, 1); - mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getPath", "()Ljava/lang/String;", false); + mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequestPath", "()Ljava/lang/String;", false); mv.visitVarInsn(ASTORE, maxLocals); varInsns.add(new int[]{ALOAD, maxLocals}); } else if (userid != null) { //HttpRequest.currentUserid diff --git a/src/main/java/org/redkale/net/http/RestHeaders.java b/src/main/java/org/redkale/net/http/RestHeaders.java index af055d7ce..1023c42a6 100644 --- a/src/main/java/org/redkale/net/http/RestHeaders.java +++ b/src/main/java/org/redkale/net/http/RestHeaders.java @@ -34,5 +34,7 @@ public interface RestHeaders { public boolean contains(String name); + public boolean containsIgnoreCase(String name); + public Map map(); } diff --git a/src/main/java/org/redkale/net/http/RestPath.java b/src/main/java/org/redkale/net/http/RestPath.java index e0c7dd84e..5b3be62b7 100644 --- a/src/main/java/org/redkale/net/http/RestPath.java +++ b/src/main/java/org/redkale/net/http/RestPath.java @@ -12,7 +12,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; /** * 只能注解于Service类的方法的String参数或参数内的String字段 *

- * 用于获取HTTP请求URL HttpRequest.getPath + * 用于获取HTTP请求URL HttpRequest.getRequestPath *

* 详情见: https://redkale.org * diff --git a/src/main/java/org/redkale/net/sncp/SncpClientCodec.java b/src/main/java/org/redkale/net/sncp/SncpClientCodec.java index 82f6f5123..a7d91488b 100644 --- a/src/main/java/org/redkale/net/sncp/SncpClientCodec.java +++ b/src/main/java/org/redkale/net/sncp/SncpClientCodec.java @@ -22,8 +22,6 @@ public class SncpClientCodec extends ClientCodec resultPool = ObjectPool.createUnsafePool(256, t -> new SncpClientResult(), SncpClientResult::prepare, SncpClientResult::recycle); - private ByteArray recyclableArray; private ByteArray halfBodyBytes; @@ -41,12 +39,11 @@ public class SncpClientCodec extends ClientCodec onOpen(final HttpRequest request) { - String uri = request.getPath(); + String uri = request.getRequestPath(); int pos = uri.indexOf("/listen/"); uri = uri.substring(pos + "/listen/".length()); this.repeat = sessions.get(uri) != null;