HttpRequest.path优化

This commit is contained in:
redkale
2023-11-23 15:14:07 +08:00
parent 0bb91186a8
commit 05e3046af8
23 changed files with 379 additions and 122 deletions

View File

@@ -72,8 +72,8 @@ public final class ApiDocCommand {
} }
List<Map> serverList = new ArrayList<>(); List<Map> serverList = new ArrayList<>();
Field __prefix = HttpServlet.class.getDeclaredField("_prefix"); Field prefixField = HttpServlet.class.getDeclaredField("_prefix");
__prefix.setAccessible(true); prefixField.setAccessible(true);
Map<String, Map<String, Map<String, Object>>> typesMap = new LinkedHashMap<>(); Map<String, Map<String, Map<String, Object>>> typesMap = new LinkedHashMap<>();
//https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md //https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md
Map<String, Object> swaggerPathsMap = new LinkedHashMap<>(); Map<String, Object> 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 String tag = ws.name().isEmpty() ? servlet.getClass().getSimpleName().replace("Servlet", "").toLowerCase() : ws.name();
final Map<String, Object> servletMap = new LinkedHashMap<>(); final Map<String, Object> servletMap = new LinkedHashMap<>();
String prefix = (String) __prefix.get(servlet); String prefix = (String) prefixField.get(servlet);
String[] urlregs = ws.value(); String[] urlregs = ws.value();
if (prefix != null && !prefix.isEmpty()) { if (prefix != null && !prefix.isEmpty()) {
for (int i = 0; i < urlregs.length; i++) { for (int i = 0; i < urlregs.length; i++) {
@@ -214,7 +214,7 @@ public final class ApiDocCommand {
// typesMap.put(rtype.getName(), typeMap); // typesMap.put(rtype.getName(), typeMap);
// } // }
mappingMap.put("results", results); mappingMap.put("results", results);
boolean hasbodyparam = false; boolean hasBodyParam = false;
Map<String, Object> swaggerRequestBody = new LinkedHashMap<>(); Map<String, Object> swaggerRequestBody = new LinkedHashMap<>();
for (HttpParam param : method.getAnnotationsByType(HttpParam.class)) { for (HttpParam param : method.getAnnotationsByType(HttpParam.class)) {
final Map<String, Object> oldapisParamMap = new LinkedHashMap<>(); final Map<String, Object> oldapisParamMap = new LinkedHashMap<>();
@@ -262,7 +262,7 @@ public final class ApiDocCommand {
} }
} }
if (param.style() == HttpParam.HttpParameterStyle.BODY) { if (param.style() == HttpParam.HttpParameterStyle.BODY) {
hasbodyparam = true; hasBodyParam = true;
} }
if (ptype.isPrimitive() || ptype == String.class) { if (ptype.isPrimitive() || ptype == String.class) {
continue; continue;
@@ -354,7 +354,7 @@ public final class ApiDocCommand {
String m = action.methods() == null || action.methods().length == 0 ? null : action.methods()[0].toLowerCase(); String m = action.methods() == null || action.methods().length == 0 ? null : action.methods()[0].toLowerCase();
if (m == null) { 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") || 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"; || action.name().contains("update") || action.name().contains("delete") || action.name().contains("send") ? "post" : "get";
} }

View File

@@ -71,7 +71,7 @@ public class LoggingFileHandler extends LoggingBaseHandler {
} }
} }
protected final LinkedBlockingQueue<LogRecord> logqueue = new LinkedBlockingQueue(); protected final LinkedBlockingQueue<LogRecord> logQueue = new LinkedBlockingQueue();
protected String pattern; protected String pattern;
@@ -83,9 +83,9 @@ public class LoggingFileHandler extends LoggingBaseHandler {
private int limit; //文件大小限制 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; //文件限制 private int count = 1; //文件限制
@@ -93,19 +93,19 @@ public class LoggingFileHandler extends LoggingBaseHandler {
protected boolean append; protected boolean append;
protected Pattern denyregx; protected Pattern denyRegx;
private final AtomicLong logLength = new AtomicLong(); private final AtomicLong logLength = new AtomicLong();
private final AtomicLong logUnusualLength = 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() { public LoggingFileHandler() {
updateTomorrow(); updateTomorrow();
@@ -122,7 +122,7 @@ public class LoggingFileHandler extends LoggingBaseHandler {
cal.add(Calendar.DAY_OF_YEAR, 1); cal.add(Calendar.DAY_OF_YEAR, 1);
long t = cal.getTimeInMillis(); long t = cal.getTimeInMillis();
if (this.tomorrow != t) { if (this.tomorrow != t) {
logindex.set(0); logIndex.set(0);
} }
this.tomorrow = t; this.tomorrow = t;
} }
@@ -139,68 +139,68 @@ public class LoggingFileHandler extends LoggingBaseHandler {
public void run() { public void run() {
while (true) { while (true) {
try { try {
LogRecord log = logqueue.take(); LogRecord log = logQueue.take();
final boolean bigger = (limit > 0 && limit <= logLength.get()); final boolean bigger = (limit > 0 && limit <= logLength.get());
final boolean changeday = tomorrow <= log.getMillis(); final boolean changeday = tomorrow <= log.getMillis();
if (bigger || changeday) { if (bigger || changeday) {
updateTomorrow(); updateTomorrow();
if (logstream != null) { if (logStream != null) {
logstream.close(); logStream.close();
if (bigger) { if (bigger) {
for (int i = Math.min(count - 2, logindex.get() - 1); i > 0; i--) { for (int i = Math.min(count - 2, logIndex.get() - 1); i > 0; i--) {
File greater = new File(logfile.getPath() + "." + i); File greater = new File(logFile.getPath() + "." + i);
if (greater.exists()) { 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 { } else {
if (logfile.exists() && logfile.length() < 1) { if (logFile.exists() && logFile.length() < 1) {
Files.delete(logfile.toPath()); Files.delete(logFile.toPath());
} }
} }
logstream = null; logStream = null;
} }
} }
if (unusual != null && changeday && logunusualstream != null) { if (unusual != null && changeday && logUnusualStream != null) {
logunusualstream.close(); logUnusualStream.close();
if (limit > 0 && limit <= logUnusualLength.get()) { if (limit > 0 && limit <= logUnusualLength.get()) {
for (int i = Math.min(count - 2, logunusualindex.get() - 1); i > 0; i--) { for (int i = Math.min(count - 2, logUnusualIndex.get() - 1); i > 0; i--) {
File greater = new File(logunusualfile.getPath() + "." + i); File greater = new File(logUnusualFile.getPath() + "." + i);
if (greater.exists()) { 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 { } else {
if (logunusualfile.exists() && logunusualfile.length() < 1) { if (logUnusualFile.exists() && logUnusualFile.length() < 1) {
Files.delete(logunusualfile.toPath()); Files.delete(logUnusualFile.toPath());
} }
} }
logunusualstream = null; logUnusualStream = null;
} }
if (logstream == null) { if (logStream == null) {
logindex.incrementAndGet(); logIndex.incrementAndGet();
logfile = new File(patternDateFormat == null ? pattern : Times.formatTime(patternDateFormat, -1, System.currentTimeMillis())); logFile = new File(patternDateFormat == null ? pattern : Times.formatTime(patternDateFormat, -1, System.currentTimeMillis()));
logfile.getParentFile().mkdirs(); logFile.getParentFile().mkdirs();
logLength.set(logfile.length()); logLength.set(logFile.length());
logstream = new FileOutputStream(logfile, append); logStream = new FileOutputStream(logFile, append);
} }
if (unusual != null && logunusualstream == null) { if (unusual != null && logUnusualStream == null) {
logunusualindex.incrementAndGet(); logUnusualIndex.incrementAndGet();
logunusualfile = new File(unusualDateFormat == null ? unusual : Times.formatTime(unusualDateFormat, -1, System.currentTimeMillis())); logUnusualFile = new File(unusualDateFormat == null ? unusual : Times.formatTime(unusualDateFormat, -1, System.currentTimeMillis()));
logunusualfile.getParentFile().mkdirs(); logUnusualFile.getParentFile().mkdirs();
logUnusualLength.set(logunusualfile.length()); logUnusualLength.set(logUnusualFile.length());
logunusualstream = new FileOutputStream(logunusualfile, append); logUnusualStream = new FileOutputStream(logUnusualFile, append);
} }
//----------------------写日志------------------------- //----------------------写日志-------------------------
String message = getFormatter().format(log); String message = getFormatter().format(log);
String encoding = getEncoding(); String encoding = getEncoding();
byte[] bytes = encoding == null ? message.getBytes() : message.getBytes(encoding); byte[] bytes = encoding == null ? message.getBytes() : message.getBytes(encoding);
logstream.write(bytes); logStream.write(bytes);
logLength.addAndGet(bytes.length); logLength.addAndGet(bytes.length);
if (unusual != null && (log.getLevel() == Level.WARNING || log.getLevel() == Level.SEVERE)) { if (unusual != null && (log.getLevel() == Level.WARNING || log.getLevel() == Level.SEVERE)) {
logunusualstream.write(bytes); logUnusualStream.write(bytes);
logUnusualLength.addAndGet(bytes.length); logUnusualLength.addAndGet(bytes.length);
} }
} catch (Exception e) { } catch (Exception e) {
@@ -331,7 +331,7 @@ public class LoggingFileHandler extends LoggingBaseHandler {
String denyregxstr = manager.getProperty(cname + ".denyregx"); String denyregxstr = manager.getProperty(cname + ".denyregx");
try { try {
if (denyregxstr != null && !denyregxstr.trim().isEmpty()) { if (denyregxstr != null && !denyregxstr.trim().isEmpty()) {
denyregx = Pattern.compile(denyregxstr); denyRegx = Pattern.compile(denyregxstr);
} }
} catch (Exception e) { } catch (Exception e) {
//do nothing //do nothing
@@ -343,18 +343,18 @@ public class LoggingFileHandler extends LoggingBaseHandler {
if (!isLoggable(log)) { if (!isLoggable(log)) {
return; return;
} }
if (denyregx != null && denyregx.matcher(log.getMessage()).find()) { if (denyRegx != null && denyRegx.matcher(log.getMessage()).find()) {
return; return;
} }
fillLogRecord(log); fillLogRecord(log);
logqueue.offer(log); logQueue.offer(log);
} }
@Override @Override
public void flush() { public void flush() {
try { try {
if (logstream != null) { if (logStream != null) {
logstream.flush(); logStream.flush();
} }
} catch (Exception e) { } catch (Exception e) {
ErrorManager err = getErrorManager(); ErrorManager err = getErrorManager();
@@ -367,8 +367,8 @@ public class LoggingFileHandler extends LoggingBaseHandler {
@Override @Override
public void close() throws SecurityException { public void close() throws SecurityException {
try { try {
if (logstream != null) { if (logStream != null) {
logstream.close(); logStream.close();
} }
} catch (Exception e) { } catch (Exception e) {
ErrorManager err = getErrorManager(); ErrorManager err = getErrorManager();

View File

@@ -38,7 +38,7 @@ public class PrepareCompiler {
listener.preCompile(application); listener.preCompile(application);
} }
application.start(); 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<?> 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); final ClassFilter<?> entityFilter2 = new ClassFilter(application.getClassLoader(), javax.persistence.Entity.class, Object.class, (Class[]) null);

View File

@@ -41,8 +41,8 @@ public class HttpMessageRequest extends HttpRequest {
} }
@Override @Override
public HttpMessageRequest setPath(String path) { public HttpMessageRequest setRequestPath(String path) {
this.path = path; this.requestPath = path;
return this; return this;
} }

View File

@@ -171,7 +171,7 @@ public class HttpMessageResponse extends HttpResponse {
@Override @Override
public void finish(int status, String msg) { public void finish(int status, String msg) {
if (status > 400) { 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)) { } else if (messageClient.logger.isLoggable(Level.FINEST)) {
messageClient.logger.log(Level.FINEST, "HttpMessageResponse.finish status: " + status); messageClient.logger.log(Level.FINEST, "HttpMessageResponse.finish status: " + status);
} }

View File

@@ -42,6 +42,7 @@ public abstract class ClientCodec<R extends ClientRequest, P extends ClientResul
this.connection = connection; this.connection = connection;
} }
//buffer之后会clear
public abstract void decodeMessages(ByteBuffer buffer, ByteArray array); public abstract void decodeMessages(ByteBuffer buffer, ByteArray array);
public ClientCodec<R, P> withMessageListener(ClientMessageListener listener) { public ClientCodec<R, P> withMessageListener(ClientMessageListener listener) {

View File

@@ -310,7 +310,7 @@ public class HttpDispatcherServlet extends DispatcherServlet<String, HttpContext
@Override @Override
public void execute(HttpRequest request, HttpResponse response) throws IOException { public void execute(HttpRequest request, HttpResponse response) throws IOException {
try { try {
final String uri = request.getPath(); final String uri = request.getRequestPath();
HttpServlet servlet; HttpServlet servlet;
if (response.isAutoOptions() && HttpRequest.METHOD_OPTIONS.equals(request.getMethod())) { if (response.isAutoOptions() && HttpRequest.METHOD_OPTIONS.equals(request.getMethod())) {
response.finish(200, null); response.finish(200, null);

View File

@@ -27,7 +27,7 @@ public abstract class HttpFilter extends Filter<HttpContext, HttpRequest, HttpRe
} }
protected void setPath(HttpRequest request, String path) { protected void setPath(HttpRequest request, String path) {
request.setPath(path); request.setRequestPath(path);
} }
protected void setRemoteAddr(HttpRequest request, String remoteAddr) { protected void setRemoteAddr(HttpRequest request, String remoteAddr) {

View File

@@ -130,6 +130,14 @@ public class HttpHeaders implements RestHeaders, Serializable {
return this.map != null && this.map.containsKey(name); return this.map != null && this.map.containsKey(name);
} }
@Override
public boolean containsIgnoreCase(String name) {
if (this.map == null || name == null) {
return false;
}
return !this.map.keySet().stream().filter(name::equalsIgnoreCase).findFirst().isEmpty();
}
public HttpHeaders addAll(HttpHeaders header) { public HttpHeaders addAll(HttpHeaders header) {
if (header.map != null) { if (header.map != null) {
if (this.map == null) { if (this.map == null) {

View File

@@ -20,6 +20,7 @@ import org.redkale.convert.json.JsonConvert;
import org.redkale.net.Request; import org.redkale.net.Request;
import org.redkale.util.*; import org.redkale.util.*;
import static org.redkale.util.Utility.isEmpty; import static org.redkale.util.Utility.isEmpty;
import static org.redkale.util.Utility.isNotEmpty;
/** /**
* Http请求包 与javax.servlet.http.HttpServletRequest 基本类似。 <br> * Http请求包 与javax.servlet.http.HttpServletRequest 基本类似。 <br>
@@ -132,7 +133,7 @@ public class HttpRequest extends Request<HttpContext> {
protected String protocol; protected String protocol;
protected String path; protected String requestPath;
protected byte[] queryBytes; protected byte[] queryBytes;
@@ -223,13 +224,9 @@ public class HttpRequest extends Request<HttpContext> {
this.contentType = req.getContentType(); this.contentType = req.getContentType();
this.remoteAddr = req.getRemoteAddr(); this.remoteAddr = req.getRemoteAddr();
this.locale = req.getLocale(); this.locale = req.getLocale();
if (needPath) { this.requestPath = needPath ? req.requestPath() : req.getPath();
this.path = req.requestPath();
} else {
this.path = req.getPath();
}
this.method = req.getMethod(); 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())}; this.cookies = new HttpCookie[]{new HttpCookie(SESSIONID_NAME, req.getSessionid())};
} }
} }
@@ -255,8 +252,8 @@ public class HttpRequest extends Request<HttpContext> {
req.setContentType(getContentType()); req.setContentType(getContentType());
req.setContextPath(prefixPath); req.setContextPath(prefixPath);
req.setMethod(this.method); req.setMethod(this.method);
String path0 = this.path; String path0 = this.requestPath;
if (prefixPath != null && !prefixPath.isEmpty() && path0.startsWith(prefixPath)) { if (isNotEmpty(prefixPath) && path0.startsWith(prefixPath)) {
path0 = path0.substring(prefixPath.length()); path0 = path0.substring(prefixPath.length());
} }
req.setPath(path0); req.setPath(path0);
@@ -565,7 +562,7 @@ public class HttpRequest extends Request<HttpContext> {
} }
//读uri //读uri
if (this.path == null) { if (this.requestPath == null) {
int qst = -1;//?的位置 int qst = -1;//?的位置
boolean decodeable = false; boolean decodeable = false;
boolean latin1 = true; boolean latin1 = true;
@@ -589,7 +586,7 @@ public class HttpRequest extends Request<HttpContext> {
} }
size = bytes.length(); size = bytes.length();
if (qst > 0) { //带?参数 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; int qlen = size - qst - 1;
this.queryBytes = bytes.getBytes(qst + 1, qlen); this.queryBytes = bytes.getBytes(qst + 1, qlen);
this.lastPathString = null; this.lastPathString = null;
@@ -601,20 +598,20 @@ public class HttpRequest extends Request<HttpContext> {
} }
} else { } else {
if (decodeable) { //需要转义 if (decodeable) { //需要转义
this.path = toDecodeString(bytes, 0, bytes.length(), charset); this.requestPath = toDecodeString(bytes, 0, bytes.length(), charset);
this.lastPathString = null; this.lastPathString = null;
this.lastPathBytes = null; this.lastPathBytes = null;
} else if (context.lazyHeaders) { } else if (context.lazyHeaders) {
byte[] lastURIBytes = lastPathBytes; byte[] lastURIBytes = lastPathBytes;
if (lastURIBytes != null && lastURIBytes.length == size && bytes.deepEquals(lastURIBytes)) { if (lastURIBytes != null && lastURIBytes.length == size && bytes.deepEquals(lastURIBytes)) {
this.path = this.lastPathString; this.requestPath = this.lastPathString;
} else { } 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 = this.path; this.lastPathString = this.requestPath;
this.lastPathBytes = bytes.getBytes(); this.lastPathBytes = bytes.getBytes();
} }
} else { } 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.lastPathString = null;
this.lastPathBytes = null; this.lastPathBytes = null;
} }
@@ -984,7 +981,7 @@ public class HttpRequest extends Request<HttpContext> {
this.method = null; this.method = null;
this.getmethod = false; this.getmethod = false;
this.protocol = null; this.protocol = null;
this.path = null; this.requestPath = null;
this.queryBytes = null; this.queryBytes = null;
this.boundary = false; this.boundary = false;
this.bodyParsed = false; this.bodyParsed = false;
@@ -1045,8 +1042,8 @@ public class HttpRequest extends Request<HttpContext> {
return this; return this;
} }
protected HttpRequest setPath(String path) { protected HttpRequest setRequestPath(String path) {
this.path = path; this.requestPath = path;
return this; return this;
} }
@@ -1534,7 +1531,7 @@ public class HttpRequest extends Request<HttpContext> {
@Override @Override
public String toString() { public String toString() {
parseBody(); 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.reqConvertType != null ? (", \r\n reqConvertType: " + this.reqConvertType) : "")
+ (this.respConvertType != null ? (", \r\n respConvertType: " + this.respConvertType) : "") + (this.respConvertType != null ? (", \r\n respConvertType: " + this.respConvertType) : "")
+ (this.currentUserid != CURRUSERID_NIL ? (", \r\n currentUserid: " + (this.currentUserid == CURRUSERID_NIL ? null : this.currentUserid)) : "") + (this.currentUserid != CURRUSERID_NIL ? (", \r\n currentUserid: " + (this.currentUserid == CURRUSERID_NIL ? null : this.currentUserid)) : "")
@@ -1781,8 +1778,8 @@ public class HttpRequest extends Request<HttpContext> {
* *
* @return 请求的URL * @return 请求的URL
*/ */
public String getPath() { public String getRequestPath() {
return path; return requestPath;
} }
/** /**
@@ -1795,16 +1792,16 @@ public class HttpRequest extends Request<HttpContext> {
} }
/** /**
* 截取getPath最后的一个/后面的部分 * 截取getRequestPath最后的一个/后面的部分
* *
* @return String * @return String
*/ */
@ConvertDisabled @ConvertDisabled
public String getPathLastParam() { public String getPathLastParam() {
if (path == null) { if (requestPath == null) {
return ""; return "";
} }
return path.substring(path.lastIndexOf('/') + 1); return requestPath.substring(requestPath.lastIndexOf('/') + 1);
} }
/** /**
@@ -1969,10 +1966,10 @@ public class HttpRequest extends Request<HttpContext> {
* @return String[] * @return String[]
*/ */
public String[] getPathParams(String prefix) { public String[] getPathParams(String prefix) {
if (path == null || prefix == null) { if (requestPath == null || prefix == null) {
return new String[0]; 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<HttpContext> {
* @return prefix截断后的值 * @return prefix截断后的值
*/ */
public String getPathParam(String prefix, String defvalue) { public String getPathParam(String prefix, String defvalue) {
if (path == null || prefix == null || prefix.isEmpty()) { if (requestPath == null || prefix == null || prefix.isEmpty()) {
return defvalue; return defvalue;
} }
int pos = path.indexOf(prefix); int pos = requestPath.indexOf(prefix);
if (pos < 0) { if (pos < 0) {
return defvalue; return defvalue;
} }
String sub = path.substring(pos + prefix.length()); String sub = requestPath.substring(pos + prefix.length());
pos = sub.indexOf('/'); pos = sub.indexOf('/');
return pos < 0 ? sub : sub.substring(0, pos); return pos < 0 ? sub : sub.substring(0, pos);
} }

View File

@@ -212,7 +212,7 @@ public class HttpResourceServlet extends HttpServlet {
@Override @Override
public void execute(HttpRequest request, HttpResponse response) throws IOException { public void execute(HttpRequest request, HttpResponse response) throws IOException {
String uri = request.getPath(); String uri = request.getRequestPath();
if (uri.contains("../")) { if (uri.contains("../")) {
if (logger.isLoggable(Level.FINEST)) { if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "Not found resource (404) be " + uri + ", request = " + request); 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 (entry == null) {
if (logger.isLoggable(Level.FINER)) { 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); finish404(request, response);
} else { } else {

View File

@@ -66,7 +66,7 @@ public class HttpServlet extends Servlet<HttpContext, HttpRequest, HttpResponse>
} }
} }
if (entry.cacheSeconds > 0) {//有缓存设置 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()) { //缓存有效 if (ce != null && ce.time + entry.cacheSeconds * 1000 > System.currentTimeMillis()) { //缓存有效
response.setStatus(ce.status); response.setStatus(ce.status);
response.setContentType(ce.contentType); response.setContentType(ce.contentType);
@@ -125,7 +125,7 @@ public class HttpServlet extends Servlet<HttpContext, HttpRequest, HttpResponse>
return; return;
} }
for (Map.Entry<String, ActionEntry> en : mappings) { for (Map.Entry<String, ActionEntry> en : mappings) {
if (request.getPath().startsWith(en.getKey())) { if (request.getRequestPath().startsWith(en.getKey())) {
ActionEntry entry = en.getValue(); ActionEntry entry = en.getValue();
if (!entry.checkMethod(request.getMethod())) { if (!entry.checkMethod(request.getMethod())) {
//response.finishJson(new RetResult(RET_METHOD_ERROR, "Method(" + request.getMethod() + ") Error")); //response.finishJson(new RetResult(RET_METHOD_ERROR, "Method(" + request.getMethod() + ") Error"));
@@ -146,7 +146,7 @@ public class HttpServlet extends Servlet<HttpContext, HttpRequest, HttpResponse>
} }
} }
finish404(request, response); 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<HttpContext, HttpRequest, HttpResponse>
return; return;
} }
CacheEntry ce = new CacheEntry(response.getStatus(), response.getContentType(), content); CacheEntry ce = new CacheEntry(response.getStatus(), response.getContentType(), content);
cache.put(response.getRequest().getPath(), ce); cache.put(response.getRequest().getRequestPath(), ce);
} : null; } : null;
} else { //单一url } else { //单一url
this.modeOneCache = true; this.modeOneCache = true;

View File

@@ -42,6 +42,8 @@ public class HttpSimpleClient extends Client<HttpSimpleConnection, HttpSimpleReq
static final byte[] header_bytes_connclose = ("Connection: close\r\n").getBytes(StandardCharsets.UTF_8); static final byte[] header_bytes_connclose = ("Connection: close\r\n").getBytes(StandardCharsets.UTF_8);
static final byte[] header_bytes_connalive = ("Connection: keep-alive\r\n").getBytes(StandardCharsets.UTF_8);
protected final AsyncGroup asyncGroup; protected final AsyncGroup asyncGroup;
protected ExecutorService workExecutor; protected ExecutorService workExecutor;
@@ -245,13 +247,13 @@ public class HttpSimpleClient extends Client<HttpSimpleConnection, HttpSimpleReq
array.put(("Host: " + uri.getHost() + "\r\n").getBytes(StandardCharsets.UTF_8)); array.put(("Host: " + uri.getHost() + "\r\n").getBytes(StandardCharsets.UTF_8));
array.put(("Content-Length: " + (body == null ? 0 : body.length) + "\r\n").getBytes(StandardCharsets.UTF_8)); array.put(("Content-Length: " + (body == null ? 0 : body.length) + "\r\n").getBytes(StandardCharsets.UTF_8));
if (headers == null || !headers.contains("User-Agent")) { if (headers == null || !headers.containsIgnoreCase("User-Agent")) {
array.put(header_bytes_useragent); array.put(header_bytes_useragent);
} }
if (headers == null || !headers.contains("Connection")) { if (headers == null || !headers.containsIgnoreCase("Connection")) {
array.put(header_bytes_connclose); array.put(header_bytes_connclose);
} }
if (headers == null || !headers.contains(Rest.REST_HEADER_TRACEID)) { if (headers == null || !headers.containsIgnoreCase(Rest.REST_HEADER_TRACEID)) {
array.put((Rest.REST_HEADER_TRACEID + ": " + traceid + "\r\n").getBytes(StandardCharsets.UTF_8)); array.put((Rest.REST_HEADER_TRACEID + ": " + traceid + "\r\n").getBytes(StandardCharsets.UTF_8));
} }
if (headers != null) { if (headers != null) {

View File

@@ -4,7 +4,9 @@
package org.redkale.net.http; package org.redkale.net.http;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.logging.Logger;
import org.redkale.net.client.ClientCodec; import org.redkale.net.client.ClientCodec;
import static org.redkale.net.http.HttpRequest.*;
import org.redkale.util.ByteArray; import org.redkale.util.ByteArray;
/** /**
@@ -13,13 +15,226 @@ import org.redkale.util.ByteArray;
*/ */
class HttpSimpleCodec extends ClientCodec<HttpSimpleRequest, HttpSimpleResult> { class HttpSimpleCodec extends ClientCodec<HttpSimpleRequest, HttpSimpleResult> {
protected static final Logger logger = Logger.getLogger(HttpSimpleCodec.class.getSimpleName());
private ByteArray recyclableArray;
private ByteArray halfBytes;
private HttpSimpleResult lastResult = null;
public HttpSimpleCodec(HttpSimpleConnection connection) { public HttpSimpleCodec(HttpSimpleConnection connection) {
super(connection); super(connection);
} }
@Override protected HttpSimpleResult pollResult(HttpSimpleRequest request) {
public void decodeMessages(ByteBuffer buffer, ByteArray array) { return new HttpSimpleResult();
}
protected void offerResult(HttpSimpleResult rs) {
//do nothing //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;
}
} }

View File

@@ -15,6 +15,7 @@ import org.redkale.convert.*;
import org.redkale.convert.json.JsonConvert; import org.redkale.convert.json.JsonConvert;
import org.redkale.net.client.ClientConnection; import org.redkale.net.client.ClientConnection;
import org.redkale.net.client.ClientRequest; import org.redkale.net.client.ClientRequest;
import static org.redkale.net.http.HttpSimpleClient.*;
import org.redkale.util.ByteArray; import org.redkale.util.ByteArray;
import org.redkale.util.RedkaleException; import org.redkale.util.RedkaleException;
import org.redkale.util.Traces; import org.redkale.util.Traces;
@@ -109,13 +110,19 @@ public class HttpSimpleRequest extends ClientRequest implements java.io.Serializ
@Override @Override
public void writeTo(ClientConnection conn, ByteArray array) { public void writeTo(ClientConnection conn, ByteArray array) {
array.put((method.toUpperCase() + " " + path + " HTTP/1.1\r\n" array.put((method.toUpperCase() + " " + requestPath() + " HTTP/1.1\r\n").getBytes(StandardCharsets.UTF_8));
+ Rest.REST_HEADER_TRACEID + ": " + traceid + "\r\n" if (traceid != null && !containsHeaderIgnoreCase(Rest.REST_HEADER_TRACEID)) {
+ "Content-Length: " + (body == null ? 0 : body.length) + "\r\n").getBytes(StandardCharsets.UTF_8)); 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) { if (headers != null) {
headers.forEach((k, v) -> { headers.forEach((k, v) -> array.put((k + ": " + v + "\r\n").getBytes(StandardCharsets.UTF_8)));
array.put((k + ": " + v + "\r\n").getBytes(StandardCharsets.UTF_8));
});
} }
array.put((byte) '\r', (byte) '\n'); array.put((byte) '\r', (byte) '\n');
if (body != null) { 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 @Nullable
@ConvertDisabled @ConvertDisabled
public String getParametersToString() { public String getParametersToString() {
@@ -493,4 +512,11 @@ public class HttpSimpleRequest extends ClientRequest implements java.io.Serializ
return JsonConvert.root().convertTo(this); 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();
}
}
} }

View File

@@ -4,6 +4,7 @@
package org.redkale.net.http; package org.redkale.net.http;
import org.redkale.net.client.ClientResult; 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<T> extends HttpResult<T> implements ClientResult { class HttpSimpleResult<T> extends HttpResult<T> implements ClientResult {
int readState = READ_STATE_ROUTE;
int contentLength = -1;
byte[] headerBytes;
boolean headerParsed = false;
@Override @Override
public boolean isKeepAlive() { public boolean isKeepAlive() {
return true; return true;

View File

@@ -1386,7 +1386,7 @@ public final class Rest {
} else if (annlocale != null) { //HttpRequest.getLocale } else if (annlocale != null) { //HttpRequest.getLocale
} else if (annbody != null) { //HttpRequest.getBodyUTF8 / HttpRequest.getBody } else if (annbody != null) { //HttpRequest.getBodyUTF8 / HttpRequest.getBody
} else if (annfile != null) { //MultiContext.partsFirstBytes / HttpRequest.partsFirstFile / HttpRequest.partsFiles } 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 (annuserid != null) { //HttpRequest.currentUserid
} else if (pname != null && pname.charAt(0) == '#') { //从request.getPathParam 中去参数 } else if (pname != null && pname.charAt(0) == '#') { //从request.getPathParam 中去参数
} else if ("#".equals(pname)) { //从request.getRequstURI 中取参数 } else if ("#".equals(pname)) { //从request.getRequstURI 中取参数
@@ -2590,9 +2590,9 @@ public final class Rest {
mv.visitVarInsn(ALOAD, 4); mv.visitVarInsn(ALOAD, 4);
mv.visitVarInsn(ASTORE, maxLocals); mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[]{ALOAD, maxLocals}); varInsns.add(new int[]{ALOAD, maxLocals});
} else if (annpath != null) { //HttpRequest.getPath } else if (annpath != null) { //HttpRequest.getRequestPath
mv.visitVarInsn(ALOAD, 1); 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); mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[]{ALOAD, maxLocals}); varInsns.add(new int[]{ALOAD, maxLocals});
} else if (userid != null) { //HttpRequest.currentUserid } else if (userid != null) { //HttpRequest.currentUserid

View File

@@ -34,5 +34,7 @@ public interface RestHeaders {
public boolean contains(String name); public boolean contains(String name);
public boolean containsIgnoreCase(String name);
public Map<String, Serializable> map(); public Map<String, Serializable> map();
} }

View File

@@ -12,7 +12,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
/** /**
* 只能注解于Service类的方法的String参数或参数内的String字段 * 只能注解于Service类的方法的String参数或参数内的String字段
* <p> * <p>
* 用于获取HTTP请求URL HttpRequest.getPath * 用于获取HTTP请求URL HttpRequest.getRequestPath
* <p> * <p>
* 详情见: https://redkale.org * 详情见: https://redkale.org
* *

View File

@@ -22,8 +22,6 @@ public class SncpClientCodec extends ClientCodec<SncpClientRequest, SncpClientRe
protected static final Logger logger = Logger.getLogger(SncpClientCodec.class.getSimpleName()); protected static final Logger logger = Logger.getLogger(SncpClientCodec.class.getSimpleName());
private final ObjectPool<SncpClientResult> resultPool = ObjectPool.createUnsafePool(256, t -> new SncpClientResult(), SncpClientResult::prepare, SncpClientResult::recycle);
private ByteArray recyclableArray; private ByteArray recyclableArray;
private ByteArray halfBodyBytes; private ByteArray halfBodyBytes;
@@ -41,12 +39,11 @@ public class SncpClientCodec extends ClientCodec<SncpClientRequest, SncpClientRe
} }
protected SncpClientResult pollResult(SncpClientRequest request) { protected SncpClientResult pollResult(SncpClientRequest request) {
SncpClientResult rs = resultPool.get(); return new SncpClientResult();
return rs;
} }
protected void offerResult(SncpClientResult rs) { protected void offerResult(SncpClientResult rs) {
resultPool.accept(rs); //do nothing
} }
protected ByteArray pollArray() { protected ByteArray pollArray() {

View File

@@ -25,9 +25,9 @@ public class SncpClientResult implements ClientResult {
private byte[] bodyContent; private byte[] bodyContent;
protected void prepare() { // protected void prepare() {
//do nothing // //do nothing
} // }
protected boolean recycle() { protected boolean recycle() {
this.header = null; this.header = null;

View File

@@ -17,7 +17,7 @@ public class UploadTestServlet extends HttpServlet {
@Override @Override
public void execute(HttpRequest request, HttpResponse response) throws IOException { public void execute(HttpRequest request, HttpResponse response) throws IOException {
if (request.getPath().contains("/uploadtest/send")) { if (request.getRequestPath().contains("/uploadtest/send")) {
send(request, response); send(request, response);
} else { } else {
form(request, response); form(request, response);

View File

@@ -53,7 +53,7 @@ public class VideoWebSocketServlet extends WebSocketServlet {
@Override @Override
public CompletableFuture<String> onOpen(final HttpRequest request) { public CompletableFuture<String> onOpen(final HttpRequest request) {
String uri = request.getPath(); String uri = request.getRequestPath();
int pos = uri.indexOf("/listen/"); int pos = uri.indexOf("/listen/");
uri = uri.substring(pos + "/listen/".length()); uri = uri.substring(pos + "/listen/".length());
this.repeat = sessions.get(uri) != null; this.repeat = sessions.get(uri) != null;