From 39b0e0f318c14e183e5ab64aed61c795853981b3 Mon Sep 17 00:00:00 2001 From: redkale Date: Thu, 1 Jun 2023 21:46:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0removeHeader=E3=80=81removePa?= =?UTF-8?q?rameter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/redkale/net/http/HttpFilter.java | 112 +- .../org/redkale/net/http/HttpRequest.java | 6014 +++++++++-------- 2 files changed, 3076 insertions(+), 3050 deletions(-) diff --git a/src/main/java/org/redkale/net/http/HttpFilter.java b/src/main/java/org/redkale/net/http/HttpFilter.java index 09ae5c247..90d7cb968 100644 --- a/src/main/java/org/redkale/net/http/HttpFilter.java +++ b/src/main/java/org/redkale/net/http/HttpFilter.java @@ -1,48 +1,64 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkale.net.http; - -import org.redkale.net.Filter; -import org.redkale.util.AnyValue; - -/** - * HTTP 过滤器
- * - *

- * 详情见: https://redkale.org - * - * @author zhangjx - */ -public abstract class HttpFilter extends Filter { - - //Server执行start后运行此方法 - public void postStart(HttpContext context, AnyValue config) { - } - - protected void setMethod(HttpRequest request, String method) { - request.setMethod(method); - } - - protected void setRequestURI(HttpRequest request, String requestURI) { - request.setRequestURI(requestURI); - } - - protected void setRemoteAddr(HttpRequest request, String remoteAddr) { - request.setRemoteAddr(remoteAddr); - } - - protected void setLocale(HttpRequest request, String locale) { - request.setLocale(locale); - } - - protected void setParameter(HttpRequest request, String name, String value) { - request.setParameter(name, value); - } - - protected void setHeader(HttpRequest request, String name, String value) { - request.setHeader(name, value); - } -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkale.net.http; + +import org.redkale.net.Filter; +import org.redkale.util.AnyValue; + +/** + * HTTP 过滤器
+ * + *

+ * 详情见: https://redkale.org + * + * @author zhangjx + */ +public abstract class HttpFilter extends Filter { + + //Server执行start后运行此方法 + public void postStart(HttpContext context, AnyValue config) { + } + + protected void setMethod(HttpRequest request, String method) { + request.setMethod(method); + } + + protected void setRequestURI(HttpRequest request, String requestURI) { + request.setRequestURI(requestURI); + } + + protected void setRemoteAddr(HttpRequest request, String remoteAddr) { + request.setRemoteAddr(remoteAddr); + } + + protected void setLocale(HttpRequest request, String locale) { + request.setLocale(locale); + } + + protected void setParameter(HttpRequest request, String name, String value) { + request.setParameter(name, value); + } + + protected void setHeader(HttpRequest request, String name, String value) { + request.setHeader(name, value); + } + + protected void removeParameter(HttpRequest request, String name) { + request.removeParameter(name); + } + + protected void removeHeader(HttpRequest request, String name) { + request.removeHeader(name); + } + + protected void removeAttribute(HttpRequest request, String name) { + request.removeAttribute(name); + } + + protected void removeProperty(HttpRequest request, String name) { + request.removeProperty(name); + } +} diff --git a/src/main/java/org/redkale/net/http/HttpRequest.java b/src/main/java/org/redkale/net/http/HttpRequest.java index 908d02de6..bf331376d 100644 --- a/src/main/java/org/redkale/net/http/HttpRequest.java +++ b/src/main/java/org/redkale/net/http/HttpRequest.java @@ -1,3002 +1,3012 @@ -/* - * To change this license headers, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.redkale.net.http; - -import java.io.*; -import java.lang.annotation.Annotation; -import java.net.*; -import java.nio.ByteBuffer; -import java.nio.charset.*; -import java.util.*; -import java.util.function.Supplier; -import java.util.logging.Level; -import org.redkale.annotation.Comment; -import org.redkale.convert.*; -import org.redkale.convert.json.JsonConvert; -import org.redkale.net.Request; -import org.redkale.util.*; - -/** - * Http请求包 与javax.servlet.http.HttpServletRequest 基本类似。
- * 同时提供json的解析接口: public Object getJsonParameter(Type type, String name)
- * Redkale提倡带简单的参数的GET请求采用类似REST风格, 因此提供了 getRequstURIPath 系列接口。
- * 例如简单的翻页查询
- * /pipes/user/query/offset:0/limit:20
- * 获取页号: int offset = request.getRequstURIPath("offset:", 0);
- * 获取行数: int limit = request.getRequstURIPath("limit:", 10);
- *

- * 详情见: https://redkale.org - * - * @author zhangjx - */ -public class HttpRequest extends Request { - - private static final boolean pipelineSameHeaders = Boolean.getBoolean("redkale.http.request.pipeline.sameheaders"); - - protected static final Serializable CURRUSERID_NIL = new Serializable() { - }; - - protected static final int READ_STATE_ROUTE = 1; - - protected static final int READ_STATE_HEADER = 2; - - protected static final int READ_STATE_BODY = 3; - - protected static final int READ_STATE_END = 4; - - protected static final byte[] EMPTY_BYTES = new byte[0]; - - protected static final String METHOD_GET = "GET"; - - protected static final String METHOD_PUT = "PUT"; - - protected static final String METHOD_POST = "POST"; - - protected static final String METHOD_HEAD = "HEAD"; - - protected static final String METHOD_OPTIONS = "OPTIONS"; - - protected static final String HTTP_1_1 = "HTTP/1.1"; - - protected static final String HTTP_2_0 = "HTTP/2.0"; - - protected static final String HEAD_COOKIE = "Cookie"; - - protected static final String HEAD_CONNECTION = "Connection"; - - protected static final String HEAD_CONTENT_TYPE = "Content-Type"; - - protected static final String HEAD_CONTENT_LENGTH = "Content-Length"; - - protected static final String HEAD_ACCEPT = "Accept"; - - protected static final String HEAD_HOST = "Host"; - - protected static final String HEAD_UPGRADE = "Upgrade"; - - protected static final String HEAD_USER_AGENT = "User-Agent"; - - protected static final String HEAD_EXPECT = "Expect"; - - public static final String SESSIONID_NAME = "JSESSIONID"; - - //---------- header 相关参数 开始 ---------- - protected int headerLength; - - protected int headerHalfLen; - - protected String contentType; - - protected long contentLength = -1; - - protected String host; - - @Comment("原始的cookie字符串,解析后值赋给HttpCookie[] cookies") - protected String cookie; - - protected HttpCookie[] cookies; - - private boolean maybews = false; //是否可能是WebSocket - - private boolean expect = false; //是否Expect:100-continue - - protected boolean rpc; - - protected int readState = READ_STATE_ROUTE; - - // @since 2.1.0 - protected Serializable currentUserid = CURRUSERID_NIL; - - protected Supplier currentUserSupplier; - - protected boolean frombody; - - protected ConvertType reqConvertType; - - protected Convert reqConvert; - - protected ConvertType respConvertType; - - protected Convert respConvert; - - protected final Map headers = new HashMap<>(); - //---------- header 相关参数 结束 ---------- - - @Comment("Method GET/POST/...") - protected String method; - - protected boolean getmethod; - - protected String protocol; - - protected String requestURI; - - protected byte[] queryBytes; - - protected String newSessionid; - - protected final Map params = new HashMap<>(); - - protected boolean boundary = false; - - protected int moduleid; - - protected int actionid; - - protected Annotation[] annotations; - - protected String remoteAddr; - - protected String locale; - - private String lastRequestURIString; - - private byte[] lastRequestURIBytes; - - private final ByteArray array; - - private byte[] headerBytes; - - private boolean headerParsed = false; - - private boolean bodyParsed = false; - - private final String remoteAddrHeader; - - private final String localHeader; - - private final String localParameter; - - final HttpRpcAuthenticator rpcAuthenticator; - - HttpServlet.ActionEntry actionEntry; //仅供HttpServlet传递Entry使用 - - public HttpRequest(HttpContext context) { - this(context, new ByteArray()); - } - - protected HttpRequest(HttpContext context, ByteArray array) { - super(context); - this.array = array; - this.remoteAddrHeader = context.remoteAddrHeader; - this.localHeader = context.localHeader; - this.localParameter = context.localParameter; - this.rpcAuthenticator = context.rpcAuthenticator; - } - - @SuppressWarnings("OverridableMethodCallInConstructor") - protected HttpRequest(HttpContext context, HttpSimpleRequest req) { - super(context); - this.array = new ByteArray(); - this.remoteAddrHeader = null; - this.localHeader = null; - this.localParameter = null; - this.rpcAuthenticator = null; - if (req != null) { - initSimpleRequest(req, true); - } - } - - protected HttpRequest initSimpleRequest(HttpSimpleRequest req, boolean needPath) { - if (req != null) { - this.rpc = req.rpc; - this.traceid = req.traceid; - if (req.getBody() != null) { - this.array.put(req.getBody()); - } - if (req.getHeaders() != null) { - this.headers.putAll(req.getHeaders()); - } - this.frombody = req.isFrombody(); - this.reqConvertType = req.getReqConvertType(); - this.reqConvert = req.getReqConvertType() == null ? null : ConvertFactory.findConvert(req.getReqConvertType()); - this.respConvertType = req.getRespConvertType(); - this.respConvert = req.getRespConvertType() == null ? null : ConvertFactory.findConvert(req.getRespConvertType()); - if (req.getParams() != null) { - this.params.putAll(req.getParams()); - } - this.hashid = req.getHashid(); - if (req.getCurrentUserid() != null) { - this.currentUserid = req.getCurrentUserid(); - } - this.contentType = req.getContentType(); - this.remoteAddr = req.getRemoteAddr(); - this.locale = req.getLocale(); - if (needPath) { - this.requestURI = (req.getPath() == null || req.getPath().isEmpty()) ? req.getRequestURI() : (req.getPath() + req.getRequestURI()); - } else { - this.requestURI = req.getRequestURI(); - } - this.method = METHOD_POST; - if (req.getSessionid() != null && !req.getSessionid().isEmpty()) { - this.cookies = new HttpCookie[]{new HttpCookie(SESSIONID_NAME, req.getSessionid())}; - } - } - return this; - } - - public HttpSimpleRequest createSimpleRequest(String prefix) { - HttpSimpleRequest req = new HttpSimpleRequest(); - req.setBody(array.length() == 0 ? null : array.getBytes()); - if (!getHeaders().isEmpty()) { - if (headers.containsKey(Rest.REST_HEADER_RPC) - || headers.containsKey(Rest.REST_HEADER_CURRUSERID)) { //外部request不能包含RPC的header信息 - req.setHeaders(new HashMap<>(headers)); - req.removeHeader(Rest.REST_HEADER_RPC); - req.removeHeader(Rest.REST_HEADER_CURRUSERID); - } else { - req.setHeaders(headers); - } - } - parseBody(); - req.setParams(params.isEmpty() ? null : params); - req.setRemoteAddr(getRemoteAddr()); - req.setLocale(getLocale()); - req.setContentType(getContentType()); - req.setPath(prefix); - String uri = this.requestURI; - if (prefix != null && !prefix.isEmpty() && uri.startsWith(prefix)) { - uri = uri.substring(prefix.length()); - } - req.setHashid(this.hashid); - req.setRequestURI(uri); - req.setSessionid(getSessionid(false)); - req.setRpc(this.rpc); - req.setTraceid(this.traceid); - return req; - } - - protected boolean isWebSocket() { - return maybews && getmethod && "Upgrade".equalsIgnoreCase(getHeader("Connection")); - } - - protected boolean isExpect() { - return expect; - } - - protected void setKeepAlive(boolean keepAlive) { - this.keepAlive = keepAlive; - } - - protected boolean isKeepAlive() { - return this.keepAlive; - } - - protected ConvertType getRespConvertType() { - return this.respConvertType; - } - - protected Convert getRespConvert() { - return this.respConvert == null ? this.jsonConvert : this.respConvert; - } - - @Override - protected int readHeader(final ByteBuffer buf, final Request last) { - final ByteBuffer buffer = buf; - ByteArray bytes = array; - if (this.readState == READ_STATE_ROUTE) { - int rs = readMethodUriLine(buffer); - if (rs != 0) { - return rs; - } - this.readState = READ_STATE_HEADER; - } - if (this.readState == READ_STATE_HEADER) { - if (last != null && ((HttpRequest) last).headerLength > 0) { - final HttpRequest httplast = (HttpRequest) last; - int bufremain = buffer.remaining(); - int remainHalf = httplast.headerLength - this.headerHalfLen; - if (remainHalf > bufremain) { - bytes.put(buffer); - this.headerHalfLen += bufremain; - buffer.clear(); - return 1; - } - buffer.position(buffer.position() + remainHalf); - this.contentType = httplast.contentType; - this.contentLength = httplast.contentLength; - this.host = httplast.host; - this.cookie = httplast.cookie; - this.cookies = httplast.cookies; - this.keepAlive = httplast.keepAlive; - this.maybews = httplast.maybews; - this.expect = httplast.expect; - this.rpc = httplast.rpc; - this.traceid = httplast.traceid; - this.hashid = httplast.hashid; - this.currentUserid = httplast.currentUserid; - this.frombody = httplast.frombody; - this.reqConvertType = httplast.reqConvertType; - this.reqConvert = httplast.reqConvert; - this.respConvertType = httplast.respConvertType; - this.respConvert = httplast.respConvert; - this.headerLength = httplast.headerLength; - this.headerHalfLen = httplast.headerHalfLen; - this.headerBytes = httplast.headerBytes; - this.headerParsed = httplast.headerParsed; - this.headers.putAll(httplast.headers); - } else if (context.lazyHeaders && getmethod) { //非GET必须要读header,会有Content-Length - int rs = loadHeaderBytes(buffer); - if (rs != 0) { - return rs; - } - this.headerParsed = false; - } else { - int startpos = buffer.position(); - int rs = readHeaderLines(buffer, bytes); - if (rs != 0) { - this.headerHalfLen = bytes.length(); - return rs; - } - this.headerParsed = true; - this.headerLength = buffer.position() - startpos + this.headerHalfLen; - this.headerHalfLen = this.headerLength; - } - bytes.clear(); - this.readState = READ_STATE_BODY; - } - if (this.contentType != null && this.contentType.contains("boundary=")) { - this.boundary = true; - } - if (this.boundary) { - this.keepAlive = false; //文件上传必须设置keepAlive为false,因为文件过大时用户不一定会skip掉多余的数据 - } - if (this.readState == READ_STATE_BODY) { - if (this.contentLength > 0 && (this.contentType == null || !this.boundary)) { - if (this.contentLength > context.getMaxBody()) { - return -1; - } - bytes.put(buffer, Math.min((int) this.contentLength, buffer.remaining())); - int lr = (int) this.contentLength - bytes.length(); - if (lr == 0) { - this.readState = READ_STATE_END; - if (bytes.isEmpty()) { - this.bodyParsed = true; //no body data - } - } - return lr > 0 ? lr : 0; - } - if (buffer.hasRemaining() && (this.boundary || !this.keepAlive)) { - bytes.put(buffer, buffer.remaining()); //文件上传、HTTP1.0或Connection:close - } - this.readState = READ_STATE_END; - if (bytes.isEmpty()) { - this.bodyParsed = true; //no body data - } - } - //暂不考虑是keep-alive且存在body却没有指定Content-Length的情况 - return 0; - } - - private int loadHeaderBytes(final ByteBuffer buf) { - final ByteBuffer buffer = buf; - ByteArray bytes = array; - int remain = buffer.remaining(); - byte b1, b2, b3, b4; - for (;;) { - if (remain-- < 4) { //bytes不存放\r\n\r\n这4个字节 - bytes.put(buffer); - buffer.clear(); - if (bytes.length() > 0) { - byte rn1 = 0, rn2 = 0, rn3 = 0; - byte b = bytes.getLastByte(); - if (b == '\r' || b == '\n') { - rn3 = b; - bytes.backCount(); - if (bytes.length() > 0) { - b = bytes.getLastByte(); - if (b == '\r' || b == '\n') { - rn2 = b; - bytes.backCount(); - if (bytes.length() > 0) { - b = bytes.getLastByte(); - if (b == '\r' || b == '\n') { - rn1 = b; - bytes.backCount(); - } - } - } - } - } - if (rn1 != 0) { - buffer.put(rn1); - } - if (rn2 != 0) { - buffer.put(rn2); - } - if (rn3 != 0) { - buffer.put(rn3); - } - } - return 1; - } - b1 = buffer.get(); - bytes.put(b1); - if (b1 == '\r') { - remain--; - b2 = buffer.get(); - bytes.put(b2); - if (b2 == '\n') { - remain--; - b3 = buffer.get(); - bytes.put(b3); - if (b3 == '\r') { - remain--; - b4 = buffer.get(); - bytes.put(b4); - if (b4 == '\n') { - this.headerBytes = Utility.append(this.headerBytes, bytes.content(), 0, bytes.length()); - this.headerLength = this.headerBytes.length; - this.headerHalfLen = this.headerLength; - bytes.clear(); - return 0; - } - } - } - } - } - } - - //解析 GET /xxx HTTP/1.1 - private int readMethodUriLine(final ByteBuffer buf) { - final ByteBuffer buffer = buf; - Charset charset = this.context.getCharset(); - int remain = buffer.remaining(); - int size; - ByteArray bytes = array; - //读method - if (this.method == null) { - boolean flag = false; - if (remain >= 5) { - byte b1 = buffer.get(); - byte b2 = buffer.get(); - if (b2 == ' ') { - remain -= 2; - this.method = Character.toString(b1); - this.getmethod = false; - } else { - byte b3 = buffer.get(); - if (b3 == ' ') { - remain -= 3; - this.method = new String(new byte[]{b1, b2}); - this.getmethod = false; - } else { - byte b4 = buffer.get(); - if (b4 == ' ') { - remain -= 4; - if (b1 == 'G' && b2 == 'E' && b3 == 'T') { - this.method = METHOD_GET; - this.getmethod = true; - } else if (b1 == 'P' && b2 == 'U' && b3 == 'T') { - this.method = METHOD_PUT; - this.getmethod = false; - } else { - this.method = new String(new byte[]{b1, b2, b3}); - this.getmethod = false; - } - } else { - byte b5 = buffer.get(); - remain -= 5; - if (b5 == ' ') { - if (b1 == 'P' && b2 == 'O' && b3 == 'S' && b3 == 'T') { - this.method = METHOD_POST; - this.getmethod = false; - } else if (b1 == 'H' && b2 == 'E' && b3 == 'A' && b3 == 'D') { - this.method = METHOD_HEAD; - this.getmethod = false; - } else { - this.method = new String(new byte[]{b1, b2, b3, b4}); - this.getmethod = false; - } - } else { - flag = true; - bytes.put(b1, b2, b3, b4, b5); - } - } - } - } - } - if (flag) { - for (;;) { - if (remain-- < 1) { - buffer.clear(); - return 1; - } - byte b = buffer.get(); - if (b == ' ') { - break; - } - bytes.put(b); - } - size = bytes.length(); - byte[] content = bytes.content(); - if (size == 3) { - if (content[0] == 'G' && content[1] == 'E' && content[2] == 'T') { - this.method = METHOD_GET; - this.getmethod = true; - } else if (content[0] == 'P' && content[1] == 'U' && content[2] == 'T') { - this.method = METHOD_PUT; - this.getmethod = false; - } else { - this.method = bytes.toString(true, charset); - this.getmethod = false; - } - } else if (size == 4) { - this.getmethod = false; - if (content[0] == 'P' && content[1] == 'O' && content[2] == 'S' && content[3] == 'T') { - this.method = METHOD_POST; - } else if (content[0] == 'H' && content[1] == 'E' && content[2] == 'A' && content[3] == 'D') { - this.method = METHOD_HEAD; - } else { - this.method = bytes.toString(true, charset); - } - } else if (size == 7) { - this.getmethod = false; - if (content[0] == 'O' && content[1] == 'P' && content[2] == 'T' - && content[3] == 'I' && content[4] == 'O' && content[5] == 'N' && content[6] == 'S') { - this.method = METHOD_OPTIONS; - } else { - this.method = bytes.toString(true, charset); - } - } else { - this.method = bytes.toString(true, charset); - this.getmethod = false; - } - bytes.clear(); - } - } - - //读uri - if (this.requestURI == null) { - int qst = -1;//?的位置 - boolean decodeable = false; - boolean latin1 = true; - for (;;) { - if (remain-- < 1) { - buffer.clear(); - return 1; - } - byte b = buffer.get(); - if (b == ' ') { - break; - } - if (b == '?' && qst < 0) { - qst = bytes.length(); - } else if (!decodeable && (b == '+' || b == '%')) { - decodeable = true; - } else if (latin1 && (b < 0x20 || b >= 0x80)) { - latin1 = false; - } - bytes.put(b); - } - size = bytes.length(); - if (qst > 0) { //带?参数 - this.requestURI = 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.lastRequestURIString = null; - this.lastRequestURIBytes = null; - try { - addParameter(bytes, false, qst + 1, qlen); - } catch (Exception e) { - this.context.getLogger().log(Level.WARNING, "HttpRequest.addParameter error: " + bytes.toString(), e); - } - } else { - if (decodeable) { //需要转义 - this.requestURI = toDecodeString(bytes, 0, bytes.length(), charset); - this.lastRequestURIString = null; - this.lastRequestURIBytes = null; - } else if (context.lazyHeaders) { - byte[] lastURIBytes = lastRequestURIBytes; - if (lastURIBytes != null && lastURIBytes.length == size && bytes.deepEquals(lastURIBytes)) { - this.requestURI = this.lastRequestURIString; - } else { - this.requestURI = context.loadUriPath(bytes, latin1, charset);// bytes.toString(latin1, charset); - this.lastRequestURIString = this.requestURI; - this.lastRequestURIBytes = bytes.getBytes(); - } - } else { - this.requestURI = context.loadUriPath(bytes, latin1, charset); //bytes.toString(latin1, charset); - this.lastRequestURIString = null; - this.lastRequestURIBytes = null; - } - this.queryBytes = EMPTY_BYTES; - } - bytes.clear(); - } - //读protocol - for (;;) { - if (remain-- < 1) { - this.params.clear(); - buffer.clear(); - return 1; - } - byte b = buffer.get(); - if (b == '\r') { - if (remain-- < 1) { - this.params.clear(); - buffer.clear(); - buffer.put(b); - return 1; - } - if (buffer.get() != '\n') { - return -1; - } - break; - } - bytes.putWithoutCheck(b); - } - size = bytes.length(); - byte[] content = bytes.content(); - if (size == 8 && content[0] == 'H' && content[5] == '1' && content[7] == '1') { - this.protocol = HTTP_1_1; - } else if (size == 8 && content[0] == 'H' && content[5] == '2' && content[7] == '0') { - this.protocol = HTTP_2_0; - } else { - this.protocol = bytes.toString(true, charset); - } - bytes.clear(); - return 0; - } - - //解析Header Connection: keep-alive - private int readHeaderLines(final ByteBuffer buf, ByteArray bytes) { - final ByteBuffer buffer = buf; - Charset charset = this.context.getCharset(); - int remain = buffer.remaining(); - for (;;) { - bytes.clear(); - if (remain-- < 2) { - if (remain == 1) { - byte one = buffer.get(); - buffer.clear(); - buffer.put(one); - return 1; - } - buffer.clear(); - 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; - } - bytes.put(b1, b2); - for (;;) { // name - if (remain-- < 1) { - buffer.clear(); - buffer.put(bytes.content(), 0, bytes.length()); - return 1; - } - byte b = buffer.get(); - if (b == ':') { - break; - } else if (latin1 && (b < 0x20 || b >= 0x80)) { - latin1 = false; - } - bytes.put(b); - } - String name = parseHeaderName(latin1, bytes, charset); - bytes.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(bytes.content(), 0, bytes.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(bytes.content(), 0, bytes.length()); - buffer.put((byte) '\r'); - return 1; - } - if (buffer.get() != '\n') { - return -1; - } - break; - } - if (first) { - if (b <= ' ') { - space++; - continue; - } - first = false; - } - bytes.put(b); - } - String value; - int vlen = bytes.length(); - byte[] content = bytes.content(); - switch (name) { - case HEAD_CONTENT_TYPE: //Content-Type - this.contentType = bytes.toString(true, charset); - break; - case HEAD_CONTENT_LENGTH: //Content-Length - this.contentLength = Long.decode(bytes.toString(true, charset)); - break; - case HEAD_HOST: //Host - this.host = bytes.toString(charset); - break; - case HEAD_COOKIE: //Cookie - if (this.cookie == null || this.cookie.isEmpty()) { - this.cookie = bytes.toString(charset); - } else { - this.cookie += ";" + bytes.toString(charset); - } - break; - case HEAD_CONNECTION: //Connection - if (vlen > 0) { - if (vlen == 5 && content[0] == 'c' - && content[1] == 'l' && content[2] == 'o' - && content[3] == 's' && content[4] == 'e') { - value = "close"; - this.setKeepAlive(false); - } else if (vlen == 10 && content[0] == 'k' - && content[1] == 'e' && content[2] == 'e' - && content[3] == 'p' && content[4] == '-' - && content[5] == 'a' && content[6] == 'l' - && content[7] == 'i' && content[8] == 'v' - && content[9] == 'e') { - value = "keep-alive"; - this.setKeepAlive(true); - } else { - value = bytes.toString(charset); - this.setKeepAlive(true); - } - } else { - value = ""; - } - headers.put(HEAD_CONNECTION, value); - break; - case HEAD_UPGRADE: //Upgrade - this.maybews = vlen == 9 && content[0] == 'w' && content[1] == 'e' && content[2] == 'b' && content[3] == 's' - && content[4] == 'o' && content[5] == 'c' && content[6] == 'k' && content[7] == 'e' && content[8] == 't'; - headers.put(HEAD_UPGRADE, this.maybews ? "websocket" : bytes.toString(true, charset)); - break; - case HEAD_EXPECT: //Expect - this.expect = vlen == 12 && content[0] == '1' && content[1] == '0' && content[2] == '0' && content[3] == '-' - && content[4] == 'c' && content[5] == 'o' && content[6] == 'n' && content[7] == 't' && content[8] == 'i' - && content[9] == 'n' && content[10] == 'u' && content[11] == 'e'; - headers.put(HEAD_EXPECT, this.expect ? "100-continue" : bytes.toString(true, charset)); - break; - case Rest.REST_HEADER_RPC: //rest-rpc - this.rpc = vlen == 4 && content[0] == 't' && content[1] == 'r' && content[2] == 'u' && content[3] == 'e'; - headers.put(name, this.rpc ? "true" - : (vlen == 5 && content[0] == 'f' && content[1] == 'a' && content[2] == 'l' && content[3] == 's' && content[4] == 'e' - ? "false" : bytes.toString(true, charset))); - break; - case Rest.REST_HEADER_CURRUSERID: //rest-curruserid - value = bytes.toString(true, charset); - this.hashid = value.hashCode(); - this.currentUserid = value; - headers.put(name, value); - break; - case Rest.REST_HEADER_PARAM_FROM_BODY: //rest-param-from-body - this.frombody = vlen == 4 && content[0] == 't' && content[1] == 'r' && content[2] == 'u' && content[3] == 'e'; - headers.put(name, this.frombody ? "true" - : (vlen == 5 && content[0] == 'f' && content[1] == 'a' && content[2] == 'l' && content[3] == 's' && content[4] == 'e' - ? "false" : bytes.toString(true, charset))); - break; - case Rest.REST_HEADER_REQ_CONVERT_TYPE: //rest-req-convert-type - value = bytes.toString(true, charset); - reqConvertType = ConvertType.valueOf(value); - reqConvert = ConvertFactory.findConvert(reqConvertType); - headers.put(name, value); - break; - case Rest.REST_HEADER_RESP_CONVERT_TYPE: //rest-resp-convert-type - value = bytes.toString(true, charset); - respConvertType = ConvertType.valueOf(value); - respConvert = ConvertFactory.findConvert(respConvertType); - headers.put(name, value); - break; - default: - headers.put(name, bytes.toString(charset)); - } - } - } - - private void parseHeader() { - if (headerParsed) { - return; - } - headerParsed = true; - if (headerBytes == null) { - return; - } - if (array.isEmpty()) { - readHeaderLines(ByteBuffer.wrap(headerBytes), array); - array.clear(); - } else { //array存有body数据 - readHeaderLines(ByteBuffer.wrap(headerBytes), new ByteArray()); - } - } - - static String parseHeaderName(boolean latin1, ByteArray bytes, Charset charset) { - final int size = bytes.length(); - final byte[] bs = bytes.content(); - final byte first = bs[0]; - if ((first == 'H' || first == 'h') && size == 4) { //Host - if (bs[1] == 'o' && bs[2] == 's' && bs[3] == 't') { - return HEAD_HOST; - } - } else if ((first == 'A' || first == 'a') && size == 6) { //Accept - if (bs[1] == 'c' && bs[2] == 'c' && bs[3] == 'e' - && bs[4] == 'p' && bs[5] == 't') { - return HEAD_ACCEPT; - } - } else if (first == 'C' || first == 'c') { - if (size == 10) { //Connection - if (bs[1] == 'o' && bs[2] == 'n' && bs[3] == 'n' - && bs[4] == 'e' && bs[5] == 'c' && bs[6] == 't' - && bs[7] == 'i' && bs[8] == 'o' && bs[9] == 'n') { - return HEAD_CONNECTION; - } - } else if (size == 12) { //Content-Type - if (bs[1] == 'o' && bs[2] == 'n' && bs[3] == 't' - && bs[4] == 'e' && bs[5] == 'n' && bs[6] == 't' - && bs[7] == '-' && (bs[8] == 'T' || bs[8] == 't') - && bs[9] == 'y' && bs[10] == 'p' && bs[11] == 'e') { - return HEAD_CONTENT_TYPE; - } - } else if (size == 14) { //Content-Length - if (bs[1] == 'o' && bs[2] == 'n' && bs[3] == 't' - && bs[4] == 'e' && bs[5] == 'n' && bs[6] == 't' - && bs[7] == '-' && (bs[8] == 'L' || bs[8] == 'l') - && bs[9] == 'e' && bs[10] == 'n' && bs[11] == 'g' - && bs[12] == 't' - && bs[13] == 'h') { - return HEAD_CONTENT_LENGTH; - } - } else if (size == 6) { //Cookie - if (bs[1] == 'o' && bs[2] == 'o' && bs[3] == 'k' - && bs[4] == 'i' && bs[5] == 'e') { - return HEAD_COOKIE; - } - } - } else if (first == 'U' || first == 'u') { - if (size == 7) { //Upgrade - if (bs[1] == 'p' && bs[2] == 'g' && bs[3] == 'r' - && bs[4] == 'a' && bs[5] == 'd' && bs[6] == 'e') { - return HEAD_UPGRADE; - } - } else if (size == 10) { //User-Agent - if (bs[1] == 's' && bs[2] == 'e' && bs[3] == 'r' - && bs[4] == '-' && (bs[5] == 'A' || bs[5] == 'a') && bs[6] == 'g' - && bs[7] == 'e' && bs[8] == 'n' && bs[9] == 't') { - return HEAD_USER_AGENT; - } - } - } else if ((first == 'E' || first == 'e') && size == 6) { //Expect - if (bs[1] == 'x' && bs[2] == 'p' && bs[3] == 'e' - && bs[4] == 'c' && bs[5] == 't') { - return HEAD_EXPECT; - } - } - return bytes.toString(latin1, charset); - } - - @Override - protected HttpRequest copyHeader() { - if (!pipelineSameHeaders || !context.lazyHeaders) { - return null; - } - HttpRequest req = new HttpRequest(context, this.array); - req.headerLength = this.headerLength; - req.headerBytes = this.headerBytes; - req.headerParsed = this.headerParsed; - req.contentType = this.contentType; - req.contentLength = this.contentLength; - req.host = this.host; - req.cookie = this.cookie; - req.cookies = this.cookies; - req.keepAlive = this.keepAlive; - req.maybews = this.maybews; - req.expect = this.expect; - req.rpc = this.rpc; - req.traceid = this.traceid; - req.hashid = this.hashid; - req.currentUserid = this.currentUserid; - req.currentUserSupplier = this.currentUserSupplier; - req.frombody = this.frombody; - req.reqConvertType = this.reqConvertType; - req.reqConvert = this.reqConvert; - req.respConvert = this.respConvert; - req.respConvertType = this.respConvertType; - req.headers.putAll(this.headers); - return req; - } - - @Override - protected Serializable getRequestid() { - return null; - } - - @Override - protected void prepare() { - this.keepAlive = true; //默认HTTP/1.1 - } - - @Override - protected void recycle() { - //header - this.headerLength = 0; - this.headerHalfLen = 0; - this.headerBytes = null; - this.headerParsed = false; - this.contentType = null; - this.contentLength = -1; - this.host = null; - this.cookie = null; - this.cookies = null; - this.maybews = false; - this.expect = false; - this.rpc = false; - this.readState = READ_STATE_ROUTE; - this.currentUserid = CURRUSERID_NIL; - this.currentUserSupplier = null; - this.frombody = false; - this.reqConvertType = null; - this.reqConvert = null; - this.respConvert = jsonConvert; - this.respConvertType = null; - this.headers.clear(); - //其他 - this.newSessionid = null; - this.method = null; - this.getmethod = false; - this.protocol = null; - this.requestURI = null; - this.queryBytes = null; - this.boundary = false; - this.bodyParsed = false; - this.moduleid = 0; - this.actionid = 0; - this.annotations = null; - this.remoteAddr = null; - this.params.clear(); - this.array.clear(); - //内部 - this.actionEntry = null; - super.recycle(); - } - - protected void skipBodyParse() { - this.bodyParsed = true; - } - - private void parseBody() { - if (this.boundary || bodyParsed) { - return; - } - bodyParsed = true; - if (this.getContentType() != null && this.contentType.toLowerCase().contains("x-www-form-urlencoded")) { - addParameter(array, true, 0, array.length()); - } - } - - private void addParameter(final ByteArray array, final boolean body, final int offset, final int len) { - if (len < 1) { - return; - } - Charset charset = this.context.getCharset(); - int limit = offset + len; - int keypos = array.indexOf(offset, limit, '='); - int valpos = array.indexOf(offset, limit, '&'); - if (keypos <= 0 || (valpos >= 0 && valpos < keypos)) { - if (valpos > 0) { - addParameter(array, body, valpos + 1, limit - valpos - 1); - } - return; - } - String name = toDecodeString(array, offset, keypos - offset, charset); - if (body && !name.isEmpty() && name.charAt(0) == '<') { - return; //内容可能是xml格式; 如: = 0) { - addParameter(array, body, valpos + 1, limit - valpos - 1); - } - } - - protected HttpRequest setMethod(String method) { - this.method = method; - this.getmethod = METHOD_GET.equalsIgnoreCase(method); - return this; - } - - protected HttpRequest setRequestURI(String requestURI) { - this.requestURI = requestURI; - return this; - } - - protected HttpRequest setRemoteAddr(String remoteAddr) { - this.remoteAddr = remoteAddr; - return this; - } - - protected HttpRequest setLocale(String locale) { - this.locale = locale; - return this; - } - - protected HttpRequest setParameter(String name, String value) { - this.params.put(name, value); - return this; - } - - protected HttpRequest setHeader(String name, String value) { - this.headers.put(name, value); - return this; - } - - protected static String toDecodeString(ByteArray array, int offset, int len, final Charset charset) { - byte[] content = array.content(); - if (len == 1) { - return Character.toString(content[offset]); - } else if (len == 2 && content[offset] >= 0x20 && content[offset] < 0x80) { - return new String(content, 0, offset, len); - } else if (len == 3 && content[offset + 1] >= 0x20 && content[offset + 1] < 0x80) { - return new String(content, 0, offset, len); - } - int start = offset; - final int end = offset + len; - boolean flag = false; //是否需要转义 - byte[] bs = content; - for (int i = offset; i < end; i++) { - if (content[i] == '+' || content[i] == '%') { - flag = true; - break; - } - } - if (flag) { - int index = 0; - bs = new byte[len]; - for (int i = offset; i < end; i++) { - switch (content[i]) { - case '+': - bs[index] = ' '; - break; - case '%': - bs[index] = (byte) ((hexBit(content[++i]) * 16 + hexBit(content[++i]))); - break; - default: - bs[index] = content[i]; - break; - } - index++; - } - start = 0; - len = index; - } - return new String(bs, start, len, charset == null ? StandardCharsets.UTF_8 : charset); - } - - private static int hexBit(byte b) { - if ('0' <= b && '9' >= b) { - return b - '0'; - } - if ('a' <= b && 'z' >= b) { - return b - 'a' + 10; - } - if ('A' <= b && 'Z' >= b) { - return b - 'A' + 10; - } - return b; - } - - @Override - protected T setProperty(String name, T value) { - return super.setProperty(name, value); - } - - @Override - @SuppressWarnings("unchecked") - protected T getProperty(String name) { - return super.getProperty(name); - } - - @Override - protected T removeProperty(String name) { - return super.removeProperty(name); - } - - /** - * 设置当前用户ID, 通常在HttpServlet.preExecute方法里设置currentUserid
- * 数据类型只能是int、long、String、JavaBean - * - * @param 泛型 - * @param userid 用户ID - * - * @return HttpRequest - * - * @since 2.1.0 - */ - public HttpRequest setCurrentUserid(T userid) { - this.currentUserid = userid; - return this; - } - - /** - * 获取当前用户ID的int值
- * - * @return 用户ID - * - * @since 2.4.0 - */ - @SuppressWarnings("unchecked") - public int currentIntUserid() { - if (currentUserid == CURRUSERID_NIL || currentUserid == null) { - return 0; - } - if (this.currentUserid instanceof Number) { - return ((Number) this.currentUserid).intValue(); - } - String uid = this.currentUserid.toString(); - return uid.isEmpty() ? 0 : Integer.parseInt(uid); - } - - /** - * 获取当前用户ID的long值
- * - * @return 用户ID - * - * @since 2.7.0 - */ - @SuppressWarnings("unchecked") - public long currentLongUserid() { - if (currentUserid == CURRUSERID_NIL || currentUserid == null) { - return 0L; - } - if (this.currentUserid instanceof Number) { - return ((Number) this.currentUserid).longValue(); - } - String uid = this.currentUserid.toString(); - return uid.isEmpty() ? 0L : Long.parseLong(uid); - } - - /** - * 获取当前用户ID
- * - * @param 数据类型只能是int、long、String、JavaBean - * @param type 类型 - * - * @return 用户ID - * - * @since 2.1.0 - */ - @SuppressWarnings("unchecked") - public T currentUserid(Class type) { - if (currentUserid == CURRUSERID_NIL || currentUserid == null) { - if (type == int.class || type == Integer.class) { - return (T) (Integer) (int) 0; - } - if (type == long.class || type == Long.class) { - return (T) (Long) (long) 0; - } - return null; - } - if (type == int.class || type == Integer.class) { - if (this.currentUserid instanceof Number) { - return (T) (Integer) ((Number) this.currentUserid).intValue(); - } - String uid = this.currentUserid.toString(); - return (T) (Integer) (uid.isEmpty() ? 0 : Integer.parseInt(uid)); - } - if (type == long.class || type == Long.class) { - if (this.currentUserid instanceof Number) { - return (T) (Long) ((Number) this.currentUserid).longValue(); - } - String uid = this.currentUserid.toString(); - return (T) (Long) (uid.isEmpty() ? 0L : Long.parseLong(uid)); - } - if (type == String.class) { - return (T) this.currentUserid.toString(); - } - if (this.currentUserid instanceof CharSequence) { - return JsonConvert.root().convertFrom(type, this.currentUserid.toString()); - } - return (T) this.currentUserid; - } - - /** - * 建议使用 setCurrentUserid, 通过userid从Service或缓存中获取用户信息
- * 设置当前用户信息, 通常在HttpServlet.preExecute方法里设置currentUser
- * 数据类型由@HttpUserType指定 - * - * @param supplier currentUser对象方法 - * - * @since 2.4.0 - * - * @return HttpRequest - */ - public HttpRequest setCurrentUserSupplier(Supplier supplier) { - this.currentUserSupplier = supplier; - return this; - } - - /** - * 建议使用 currentUserid, 通过userid从Service或缓存中获取用户信息
- * 获取当前用户信息
- * 数据类型由@HttpUserType指定 - * - * @param @HttpUserType指定的用户信息类型 - * - * @return 用户信息 - */ - @SuppressWarnings("unchecked") - public T currentUser() { - Supplier supplier = this.currentUserSupplier; - return (T) (supplier == null ? null : supplier.get()); - } - - /** - * 获取模块ID,来自@HttpServlet.moduleid() - * - * @return 模块ID - */ - @ConvertDisabled - public int getModuleid() { - return this.moduleid; - } - - /** - * 获取操作ID,来自@HttpMapping.actionid() - * - * @return 模块ID - */ - @ConvertDisabled - public int getActionid() { - return this.actionid; - } - - /** - * 获取当前操作Method上的注解集合 - * - * @return Annotation[] - */ - @ConvertDisabled - public Annotation[] getAnnotations() { - if (this.annotations == null) { - return new Annotation[0]; - } - Annotation[] newanns = new Annotation[this.annotations.length]; - System.arraycopy(this.annotations, 0, newanns, 0, newanns.length); - return newanns; - } - - /** - * 获取当前操作Method上的注解 - * - * @param 注解泛型 - * @param annotationClass 注解类型 - * - * @return Annotation - */ - public T getAnnotation(Class annotationClass) { - if (this.annotations == null) { - return null; - } - for (Annotation ann : this.annotations) { - if (ann.getClass() == annotationClass) { - return (T) ann; - } - } - return null; - } - - /** - * 获取当前操作Method上的注解集合 - * - * @param 注解泛型 - * @param annotationClass 注解类型 - * - * @return Annotation[] - */ - public T[] getAnnotationsByType(Class annotationClass) { - if (this.annotations == null) { - return Creator.newArray(annotationClass, 0); - } - T[] news = Creator.newArray(annotationClass, this.annotations.length); - int index = 0; - for (Annotation ann : this.annotations) { - if (ann.getClass() == annotationClass) { - news[index++] = (T) ann; - } - } - if (index < 1) { - return Creator.newArray(annotationClass, 0); - } - return Arrays.copyOf(news, index); - } - - /** - * 获取客户端地址IP - * - * @return 地址 - */ - @ConvertDisabled - public SocketAddress getRemoteAddress() { - return this.channel == null || !this.channel.isOpen() ? null : this.channel.getRemoteAddress(); - } - - /** - * 获取客户端地址IP, 与getRemoteAddress() 的区别在于:本方法优先取header中指定为RemoteAddress名的值,没有则返回getRemoteAddress()的getHostAddress()。
- * 本方法适用于服务前端有如nginx的代理服务器进行中转,通过 getRemoteAddress()是获取不到客户端的真实IP。 - * - * @return 地址 - */ - public String getRemoteAddr() { - if (this.remoteAddr != null) { - return this.remoteAddr; - } - parseHeader(); - if (remoteAddrHeader != null) { - String val = getHeader(remoteAddrHeader); - if (val != null) { - this.remoteAddr = val; - return val; - } - } - SocketAddress addr = getRemoteAddress(); - if (addr == null) { - return ""; - } - if (addr instanceof InetSocketAddress) { - this.remoteAddr = ((InetSocketAddress) addr).getAddress().getHostAddress(); - return this.remoteAddr; - } - this.remoteAddr = String.valueOf(addr); - return this.remoteAddr; - } - - /** - * 获取国际化Locale,值可以取之于header或parameter - * - * @return 国际化Locale - */ - public String getLocale() { - if (this.locale != null) { - return this.locale; - } - if (localHeader != null) { - String val = getHeader(localHeader); - if (val != null) { - this.locale = val; - return val; - } - } - if (localParameter != null) { - String val = getParameter(localParameter); - if (val != null) { - this.locale = val; - return val; - } - } - return this.locale; - } - - /** - * 获取请求内容指定的编码字符串 - * - * @param charset 编码 - * - * @return 内容 - */ - public String getBody(final Charset charset) { - return charset == null ? array.toString() : array.toString(charset); - } - - /** - * 获取请求内容的UTF-8编码字符串 - * - * @return 内容 - */ - @ConvertDisabled - public String getBodyUTF8() { - return array.toString(StandardCharsets.UTF_8); - } - - /** - * 获取请求内容的JavaBean对象 - * - * @param 泛型 - * @param type 类型 - * - * @return 内容 - */ - public T getBodyJson(java.lang.reflect.Type type) { - if (array == null || array.isEmpty()) { - return null; - } - Convert convert = this.reqConvert; - if (convert == null) { - convert = context.getJsonConvert(); - } - if (type == byte[].class) { - return (T) array.getBytes(); - } - return (T) convert.convertFrom(type, array.content()); - } - - /** - * 获取请求内容的JavaBean对象 - * - * @param 泛型 - * @param convert Convert - * @param type 类型 - * - * @return 内容 - */ - public T getBodyJson(Convert convert, java.lang.reflect.Type type) { - if (array.isEmpty()) { - return null; - } - if (type == byte[].class) { - return (T) array.getBytes(); - } - return (T) convert.convertFrom(type, array.content()); - } - - /** - * 获取请求内容的byte[] - * - * @return 内容 - */ - public byte[] getBody() { - return array.length() == 0 ? null : array.getBytes(); - } - - /** - * 直接获取body对象 - * - * @return body对象 - */ - @ConvertDisabled - protected ByteArray getDirectBody() { - return array; - } - - @Override - public String toString() { - parseBody(); - return this.getClass().getSimpleName() + "{\r\n method: " + this.method + ", \r\n requestURI: " + this.requestURI - + (this.frombody ? (", \r\n frombody: " + this.frombody) : "") - + (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)) : "") - + (this.getRemoteAddr() != null ? (", \r\n remoteAddr: " + this.getRemoteAddr()) : "") - + (this.cookie != null ? (", \r\n cookies: " + this.cookie) : "") - + (this.getContentType() != null ? (", \r\n contentType: " + this.contentType) : "") - + (this.protocol != null ? (", \r\n protocol: " + this.protocol) : "") - + (this.getHost() != null ? (", \r\n host: " + this.host) : "") - + (this.getContentLength() >= 0 ? (", \r\n contentLength: " + this.contentLength) : "") - + (this.array.length() > 0 ? (", \r\n bodyLength: " + this.array.length()) : "") - + (this.boundary || this.array.isEmpty() ? "" : (", \r\n bodyContent: " + (this.respConvertType == null || this.respConvertType == ConvertType.JSON ? this.getBodyUTF8() : Arrays.toString(getBody())))) - + ", \r\n params: " + toMapString(this.params, 4) - + ", \r\n header: " + toMapString(this.headers, 4) - + "\r\n}"; //this.headers.toString(4) - } - - private static CharSequence toMapString(Map map, int indent) { - final String space = " ".repeat(indent); - StringBuilder sb = new StringBuilder(); - sb.append("{\r\n"); - for (Map.Entry en : map.entrySet()) { - sb.append(space).append(" '").append(en.getKey()).append("': '").append(en.getValue()).append("',\r\n"); - } - sb.append(space).append('}'); - return sb; - } - - /** - * 获取文件上传对象 - * - * @return 文件上传对象 - */ - @ConvertDisabled - public final MultiContext getMultiContext() { - final InputStream in = newInputStream(); - return new MultiContext(context.getCharset(), this.getContentType(), this.params, - new BufferedInputStream(in, Math.max(array.length(), 8192)) { - { - array.copyTo(this.buf); - this.count = array.length(); - } - }, null); - } - - /** - * 是否上传文件请求 - * - * @return boolean - */ - public final boolean isMultipart() { - return boundary; - } - - /** - * 获取文件上传信息列表 - * - * @return 文件上传对象集合 - * - * @throws IOException IO异常 - */ - @ConvertDisabled - public final Iterable multiParts() throws IOException { - return getMultiContext().parts(); - } - - /** - * 获取sessionid - * - * @param autoCreate 无sessionid是否自动创建 - * - * @return sessionid - */ - @ConvertDisabled - public String getSessionid(boolean autoCreate) { - String sessionid = getCookie(SESSIONID_NAME, null); - if (autoCreate && (sessionid == null || sessionid.isEmpty())) { - sessionid = context.createSessionid(); - this.newSessionid = sessionid; - } - return sessionid; - } - - /** - * 更新sessionid - * - * @return 新的sessionid值 - */ - public String changeSessionid() { - this.newSessionid = context.createSessionid(); - return newSessionid; - } - - /** - * 指定值更新sessionid - * - * @param newSessionid 新sessionid值 - * - * @return 新的sessionid值 - */ - public String changeSessionid(String newSessionid) { - this.newSessionid = newSessionid == null ? context.createSessionid() : newSessionid.trim(); - return newSessionid; - } - - /** - * 使sessionid失效 - */ - public void invalidateSession() { - this.newSessionid = ""; //为空表示删除sessionid - } - - /** - * 获取所有Cookie对象 - * - * @return cookie对象数组 - */ - public HttpCookie[] getCookies() { - parseHeader(); - if (this.cookies == null) { - this.cookies = parseCookies(this.cookie); - } - return this.cookies.length == 0 ? null : this.cookies; - } - - /** - * 获取Cookie值 - * - * @param name cookie名 - * - * @return cookie值 - */ - public String getCookie(String name) { - return getCookie(name, null); - } - - /** - * 获取Cookie值, 没有返回默认值 - * - * @param name cookie名 - * @param dfvalue 默认cookie值 - * - * @return cookie值 - */ - public String getCookie(String name, String dfvalue) { - HttpCookie[] cs = getCookies(); - if (cs == null) { - return dfvalue; - } - for (HttpCookie c : cs) { - if (name.equals(c.getName())) { - return c.getValue(); - } - } - return dfvalue; - } - - private static HttpCookie[] parseCookies(String cookiestr) { - if (cookiestr == null || cookiestr.isEmpty()) { - return new HttpCookie[0]; - } - String str = cookiestr.replaceAll("(^;)|(;$)", "").replaceAll(";+", ";"); - if (str.isEmpty()) { - return new HttpCookie[0]; - } - String[] strs = str.split(";"); - HttpCookie[] cookies = new HttpCookie[strs.length]; - for (int i = 0; i < strs.length; i++) { - String s = strs[i]; - int pos = s.indexOf('='); - String v = (pos < 0 ? "" : s.substring(pos + 1)); - if (v.indexOf('"') == 0 && v.lastIndexOf('"') == v.length() - 1) { - v = v.substring(1, v.length() - 1); - } - cookies[i] = new HttpCookie((pos < 0 ? s : s.substring(0, pos)), v); - } - return cookies; - } - - /** - * 获取协议名 http、https、ws、wss等 - * - * @return protocol - */ - public String getProtocol() { - return protocol; - } - - /** - * 获取请求方法 GET、POST等 - * - * @return method - */ - public String getMethod() { - return method; - } - - /** - * 获取Content-Type的header值 - * - * @return contentType - */ - public String getContentType() { - if (contentType == null) { - parseHeader(); - } - return contentType; - } - - /** - * 获取请求内容的长度, 为-1表示内容长度不确定 - * - * @return 内容长度 - */ - public long getContentLength() { - if (contentLength < 1) { - parseHeader(); - } - return contentLength; - } - - /** - * 获取Host的Header值 - * - * @return Host - */ - public String getHost() { - if (host == null) { - parseHeader(); - } - return host; - } - - /** - * 获取请求的URL - * - * @return 请求的URL - */ - public String getRequestURI() { - return requestURI; - } - - /** - * 获取请求参数的byte[] - * - * @return byte[] - */ - public byte[] getQueryBytes() { - return queryBytes; - } - - /** - * 截取getRequestURI最后的一个/后面的部分 - * - * @return String - */ - @ConvertDisabled - public String getRequstURILastPath() { - if (requestURI == null) { - return ""; - } - return requestURI.substring(requestURI.lastIndexOf('/') + 1); - } - - /** - * 获取请求URL最后的一个/后面的部分的short值
- * 例如请求URL /pipes/user/query/2
- * 获取type参数: short type = request.getRequstURILastPath((short)0); //type = 2 - * - * @param defvalue 默认short值 - * - * @return short值 - */ - public short getRequstURILastPath(short defvalue) { - String val = getRequstURILastPath(); - if (val.isEmpty()) { - return defvalue; - } - try { - return Short.parseShort(val); - } catch (NumberFormatException e) { - return defvalue; - } - } - - /** - * 获取请求URL最后的一个/后面的部分的short值
- * 例如请求URL /pipes/user/query/2
- * 获取type参数: short type = request.getRequstURILastPath(16, (short)0); //type = 2 - * - * @param radix 进制数 - * @param defvalue 默认short值 - * - * @return short值 - */ - public short getRequstURILastPath(int radix, short defvalue) { - String val = getRequstURILastPath(); - if (val.isEmpty()) { - return defvalue; - } - try { - return Short.parseShort(val, radix); - } catch (NumberFormatException e) { - return defvalue; - } - } - - /** - * 获取请求URL最后的一个/后面的部分的int值
- * 例如请求URL /pipes/user/query/2
- * 获取type参数: int type = request.getRequstURILastPath(0); //type = 2 - * - * @param defvalue 默认int值 - * - * @return int值 - */ - public int getRequstURILastPath(int defvalue) { - String val = getRequstURILastPath(); - try { - return val.isEmpty() ? defvalue : Integer.parseInt(val); - } catch (NumberFormatException e) { - return defvalue; - } - } - - /** - * 获取请求URL最后的一个/后面的部分的int值
- * 例如请求URL /pipes/user/query/2
- * 获取type参数: int type = request.getRequstURILastPath(16, 0); //type = 2 - * - * @param radix 进制数 - * @param defvalue 默认int值 - * - * @return int值 - */ - public int getRequstURILastPath(int radix, int defvalue) { - String val = getRequstURILastPath(); - try { - return val.isEmpty() ? defvalue : Integer.parseInt(val, radix); - } catch (NumberFormatException e) { - return defvalue; - } - } - - /** - * 获取请求URL最后的一个/后面的部分的float值
- * 例如请求URL /pipes/user/query/2
- * 获取type参数: float type = request.getRequstURILastPath(0.0f); //type = 2.0f - * - * @param defvalue 默认float值 - * - * @return float值 - */ - public float getRequstURILastPath(float defvalue) { - String val = getRequstURILastPath(); - try { - return val.isEmpty() ? defvalue : Float.parseFloat(val); - } catch (NumberFormatException e) { - return defvalue; - } - } - - /** - * 获取请求URL最后的一个/后面的部分的int值
- * 例如请求URL /pipes/user/query/2
- * 获取type参数: long type = request.getRequstURILastPath(0L); //type = 2 - * - * @param defvalue 默认long值 - * - * @return long值 - */ - public long getRequstURILastPath(long defvalue) { - String val = getRequstURILastPath(); - try { - return val.isEmpty() ? defvalue : Long.parseLong(val); - } catch (NumberFormatException e) { - return defvalue; - } - } - - /** - * 获取请求URL最后的一个/后面的部分的int值
- * 例如请求URL /pipes/user/query/2
- * 获取type参数: long type = request.getRequstURILastPath(16, 0L); //type = 2 - * - * @param radix 进制数 - * @param defvalue 默认long值 - * - * @return long值 - */ - public long getRequstURILastPath(int radix, long defvalue) { - String val = getRequstURILastPath(); - try { - return val.isEmpty() ? defvalue : Long.parseLong(val, radix); - } catch (NumberFormatException e) { - return defvalue; - } - } - - /** - * 获取请求URL最后的一个/后面的部分的double值
- * 例如请求URL /pipes/user/query/2
- * 获取type参数: double type = request.getRequstURILastPath(0.0); //type = 2.0 - * - * @param defvalue 默认double值 - * - * @return double值 - */ - public double getRequstURILastPath(double defvalue) { - String val = getRequstURILastPath(); - try { - return val.isEmpty() ? defvalue : Double.parseDouble(val); - } catch (NumberFormatException e) { - return defvalue; - } - } - - /** - * - * 从prefix之后截取getRequestURI再对"/"进行分隔 - *

- * @param prefix 前缀 - * - * @return String[] - */ - public String[] getRequstURIPaths(String prefix) { - if (requestURI == null || prefix == null) { - return new String[0]; - } - return requestURI.substring(requestURI.indexOf(prefix) + prefix.length() + (prefix.endsWith("/") ? 0 : 1)).split("/"); - } - - /** - * 获取请求URL分段中含prefix段的值
- * 例如请求URL /pipes/user/query/name:hello
- * 获取name参数: String name = request.getRequstURIPath("name:", "none"); - * - * @param prefix prefix段前缀 - * @param defvalue 默认值 - * - * @return prefix截断后的值 - */ - public String getRequstURIPath(String prefix, String defvalue) { - if (requestURI == null || prefix == null || prefix.isEmpty()) { - return defvalue; - } - int pos = requestURI.indexOf(prefix); - if (pos < 0) { - return defvalue; - } - String sub = requestURI.substring(pos + prefix.length()); - pos = sub.indexOf('/'); - return pos < 0 ? sub : sub.substring(0, pos); - } - - /** - * 获取请求URL分段中含prefix段的short值
- * 例如请求URL /pipes/user/query/type:10
- * 获取type参数: short type = request.getRequstURIPath("type:", (short)0); - * - * @param prefix prefix段前缀 - * @param defvalue 默认short值 - * - * @return short值 - */ - public short getRequstURIPath(String prefix, short defvalue) { - String val = getRequstURIPath(prefix, null); - try { - return val == null ? defvalue : Short.parseShort(val); - } catch (NumberFormatException e) { - return defvalue; - } - } - - /** - * 获取请求URL分段中含prefix段的short值
- * 例如请求URL /pipes/user/query/type:a
- * 获取type参数: short type = request.getRequstURIPath(16, "type:", (short)0); //type = 10 - * - * @param radix 进制数 - * @param prefix prefix段前缀 - * @param defvalue 默认short值 - * - * @return short值 - */ - public short getRequstURIPath(int radix, String prefix, short defvalue) { - String val = getRequstURIPath(prefix, null); - try { - return val == null ? defvalue : Short.parseShort(val, radix); - } catch (NumberFormatException e) { - return defvalue; - } - } - - /** - * 获取请求URL分段中含prefix段的int值
- * 例如请求URL /pipes/user/query/offset:0/limit:50
- * 获取offset参数: int offset = request.getRequstURIPath("offset:", 0);
- * 获取limit参数: int limit = request.getRequstURIPath("limit:", 20);
- * - * @param prefix prefix段前缀 - * @param defvalue 默认int值 - * - * @return int值 - */ - public int getRequstURIPath(String prefix, int defvalue) { - String val = getRequstURIPath(prefix, null); - try { - return val == null ? defvalue : Integer.parseInt(val); - } catch (NumberFormatException e) { - return defvalue; - } - } - - /** - * 获取请求URL分段中含prefix段的int值
- * 例如请求URL /pipes/user/query/offset:0/limit:50
- * 获取offset参数: int offset = request.getRequstURIPath("offset:", 0);
- * 获取limit参数: int limit = request.getRequstURIPath(16, "limit:", 20); // limit = 16
- * - * @param radix 进制数 - * @param prefix prefix段前缀 - * @param defvalue 默认int值 - * - * @return int值 - */ - public int getRequstURIPath(int radix, String prefix, int defvalue) { - String val = getRequstURIPath(prefix, null); - try { - return val == null ? defvalue : Integer.parseInt(val, radix); - } catch (NumberFormatException e) { - return defvalue; - } - } - - /** - * 获取请求URL分段中含prefix段的float值
- * 例如请求URL /pipes/user/query/point:40.0
- * 获取time参数: float point = request.getRequstURIPath("point:", 0.0f); - * - * @param prefix prefix段前缀 - * @param defvalue 默认float值 - * - * @return float值 - */ - public float getRequstURIPath(String prefix, float defvalue) { - String val = getRequstURIPath(prefix, null); - try { - return val == null ? defvalue : Float.parseFloat(val); - } catch (NumberFormatException e) { - return defvalue; - } - } - - /** - * 获取请求URL分段中含prefix段的long值
- * 例如请求URL /pipes/user/query/time:1453104341363/id:40
- * 获取time参数: long time = request.getRequstURIPath("time:", 0L); - * - * @param prefix prefix段前缀 - * @param defvalue 默认long值 - * - * @return long值 - */ - public long getRequstURIPath(String prefix, long defvalue) { - String val = getRequstURIPath(prefix, null); - try { - return val == null ? defvalue : Long.parseLong(val); - } catch (NumberFormatException e) { - return defvalue; - } - } - - /** - * 获取请求URL分段中含prefix段的long值
- * 例如请求URL /pipes/user/query/time:1453104341363/id:40
- * 获取time参数: long time = request.getRequstURIPath(16, "time:", 0L); - * - * @param radix 进制数 - * @param prefix prefix段前缀 - * @param defvalue 默认long值 - * - * @return long值 - */ - public long getRequstURIPath(int radix, String prefix, long defvalue) { - String val = getRequstURIPath(prefix, null); - try { - return val == null ? defvalue : Long.parseLong(val, radix); - } catch (NumberFormatException e) { - return defvalue; - } - } - - /** - * 获取请求URL分段中含prefix段的double值
- * 例如请求URL /pipes/user/query/point:40.0
- * 获取time参数: double point = request.getRequstURIPath("point:", 0.0); - * - * @param prefix prefix段前缀 - * @param defvalue 默认double值 - * - * @return double值 - */ - public double getRequstURIPath(String prefix, double defvalue) { - String val = getRequstURIPath(prefix, null); - try { - return val == null ? defvalue : Double.parseDouble(val); - } catch (NumberFormatException e) { - return defvalue; - } - } - - //------------------------------------------------------------------------------ - /** - * 获取请求Header总对象 - * - * @return AnyValue - */ - public Map getHeaders() { - parseHeader(); - return headers; - } - - /** - * 将请求Header转换成Map - * - * @param map Map - * - * @return Map - */ - @ConvertDisabled - public Map getHeadersToMap(Map map) { - parseHeader(); - if (map == null) { - map = new LinkedHashMap<>(); - } - final Map map0 = map; - headers.forEach((k, v) -> map0.put(k, v)); - return map0; - } - - /** - * 获取所有的header名 - * - * @return header名数组 - */ - @ConvertDisabled - public String[] getHeaderNames() { - parseHeader(); - Set names = headers.keySet(); - return names.toArray(new String[names.size()]); - } - - /** - * 获取指定的header值 - * - * @param name header名 - * - * @return header值 - */ - public String getHeader(String name) { - parseHeader(); - return headers.get(name); - } - - /** - * 获取指定的header值, 没有返回默认值 - * - * @param name header名 - * @param defaultValue 默认值 - * - * @return header值 - */ - public String getHeader(String name, String defaultValue) { - parseHeader(); - return headers.getOrDefault(name, defaultValue); - } - - /** - * 获取指定的header的json值 - * - * @param 泛型 - * @param type 反序列化的类名 - * @param name header名 - * - * @return header值 - */ - public T getJsonHeader(java.lang.reflect.Type type, String name) { - String v = getHeader(name); - return v == null || v.isEmpty() ? null : jsonConvert.convertFrom(type, v); - } - - /** - * 获取指定的header的json值 - * - * @param 泛型 - * @param convert JsonConvert对象 - * @param type 反序列化的类名 - * @param name header名 - * - * @return header值 - */ - public T getJsonHeader(JsonConvert convert, java.lang.reflect.Type type, String name) { - String v = getHeader(name); - return v == null || v.isEmpty() ? null : convert.convertFrom(type, v); - } - - /** - * 获取指定的header的boolean值, 没有返回默认boolean值 - * - * @param name header名 - * @param defaultValue 默认boolean值 - * - * @return header值 - */ - public boolean getBooleanHeader(String name, boolean defaultValue) { - //return headers.getBoolValue(name, defaultValue); - parseHeader(); - String value = headers.get(name); - return value == null || value.length() == 0 ? defaultValue : Boolean.parseBoolean(value); - } - - /** - * 获取指定的header的short值, 没有返回默认short值 - * - * @param name header名 - * @param defaultValue 默认short值 - * - * @return header值 - */ - public short getShortHeader(String name, short defaultValue) { - //return headers.getShortValue(name, defaultValue); - parseHeader(); - String value = headers.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return Short.decode(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * 获取指定的header的short值, 没有返回默认short值 - * - * @param radix 进制数 - * @param name header名 - * @param defaultValue 默认short值 - * - * @return header值 - */ - public short getShortHeader(int radix, String name, short defaultValue) { - //return headers.getShortValue(name, defaultValue); - parseHeader(); - String value = headers.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return (radix == 10 ? Short.decode(value) : Short.parseShort(value, radix)); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * 获取指定的header的short值, 没有返回默认short值 - * - * @param name header名 - * @param defaultValue 默认short值 - * - * @return header值 - */ - public short getShortHeader(String name, int defaultValue) { - //return headers.getShortValue(name, (short) defaultValue); - parseHeader(); - String value = headers.get(name); - if (value == null || value.length() == 0) { - return (short) defaultValue; - } - try { - return Short.decode(value); - } catch (NumberFormatException e) { - return (short) defaultValue; - } - } - - /** - * 获取指定的header的short值, 没有返回默认short值 - * - * @param radix 进制数 - * @param name header名 - * @param defaultValue 默认short值 - * - * @return header值 - */ - public short getShortHeader(int radix, String name, int defaultValue) { - //return headers.getShortValue(radix, name, (short) defaultValue); - parseHeader(); - String value = headers.get(name); - if (value == null || value.length() == 0) { - return (short) defaultValue; - } - try { - return (radix == 10 ? Short.decode(value) : Short.parseShort(value, radix)); - } catch (NumberFormatException e) { - return (short) defaultValue; - } - } - - /** - * 获取指定的header的int值, 没有返回默认int值 - * - * @param name header名 - * @param defaultValue 默认int值 - * - * @return header值 - */ - public int getIntHeader(String name, int defaultValue) { - //return headers.getIntValue(name, defaultValue); - parseHeader(); - String value = headers.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * 获取指定的header的int值, 没有返回默认int值 - * - * @param radix 进制数 - * @param name header名 - * @param defaultValue 默认int值 - * - * @return header值 - */ - public int getIntHeader(int radix, String name, int defaultValue) { - //return headers.getIntValue(radix, name, defaultValue); - parseHeader(); - String value = headers.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return (radix == 10 ? Integer.decode(value) : Integer.parseInt(value, radix)); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * 获取指定的header的long值, 没有返回默认long值 - * - * @param name header名 - * @param defaultValue 默认long值 - * - * @return header值 - */ - public long getLongHeader(String name, long defaultValue) { - //return headers.getLongValue(name, defaultValue); - parseHeader(); - String value = headers.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return Long.decode(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * 获取指定的header的long值, 没有返回默认long值 - * - * @param radix 进制数 - * @param name header名 - * @param defaultValue 默认long值 - * - * @return header值 - */ - public long getLongHeader(int radix, String name, long defaultValue) { - //return headers.getLongValue(radix, name, defaultValue); - parseHeader(); - String value = headers.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return (radix == 10 ? Long.decode(value) : Long.parseLong(value, radix)); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * 获取指定的header的float值, 没有返回默认float值 - * - * @param name header名 - * @param defaultValue 默认float值 - * - * @return header值 - */ - public float getFloatHeader(String name, float defaultValue) { - //return headers.getFloatValue(name, defaultValue); - parseHeader(); - String value = headers.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return Float.parseFloat(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * 获取指定的header的double值, 没有返回默认double值 - * - * @param name header名 - * @param defaultValue 默认double值 - * - * @return header值 - */ - public double getDoubleHeader(String name, double defaultValue) { - //return headers.getDoubleValue(name, defaultValue); - parseHeader(); - String value = headers.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return Double.parseDouble(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - //------------------------------------------------------------------------------ - /** - * 获取请求参数总对象 - * - * @return AnyValue - */ - public Map getParameters() { - parseBody(); - return params; - } - - /** - * 将请求参数转换成Map - * - * @param map Map - * - * @return Map - */ - @ConvertDisabled - public Map getParametersToMap(Map map) { - if (map == null) { - map = new LinkedHashMap<>(); - } - final Map map0 = map; - getParameters().forEach((k, v) -> map0.put(k, v)); - return map0; - } - - /** - * 将请求参数转换成String, 字符串格式为: bean1={}&id=13&name=xxx
- * 不会返回null,没有参数返回空字符串 - * - * - * @return String - */ - @ConvertDisabled - public String getParametersToString() { - return getParametersToString(null); - } - - /** - * 将请求参数转换成String, 字符串格式为: bean1={}&id=13&name=xxx
- * 不会返回null,没有参数返回空字符串 - * - * @param prefix 拼接前缀, 如果无参数,返回的字符串不会含有拼接前缀 - * - * @return String - */ - public String getParametersToString(String prefix) { - byte[] rbs = queryBytes; - if (rbs == null || rbs.length < 1) { - return ""; - } - Charset charset = this.context.getCharset(); - String str = charset == null ? new String(rbs, StandardCharsets.UTF_8) : new String(rbs, charset); - return (prefix == null) ? str : (prefix + str); - } - - /** - * 获取所有参数名 - * - * @return 参数名数组 - */ - @ConvertDisabled - public String[] getParameterNames() { - parseBody(); - Set names = params.keySet(); - return names.toArray(new String[names.size()]); - } - - /** - * 获取指定的参数值 - * - * @param name 参数名 - * - * @return 参数值 - */ - public String getParameter(String name) { - if (this.frombody) { - if (array.isEmpty()) { - return null; - } - Convert convert = this.reqConvert; - if (convert == null) { - convert = jsonConvert; - } - return (String) convert.convertFrom(String.class, array.content()); - } - parseBody(); - return params.get(name); - } - - /** - * 获取指定的参数值, 没有返回默认值 - * - * @param name 参数名 - * @param defaultValue 默认值 - * - * @return 参数值 - */ - public String getParameter(String name, String defaultValue) { - if (this.frombody) { - if (array.isEmpty()) { - return defaultValue; - } - Convert convert = this.reqConvert; - if (convert == null) { - convert = jsonConvert; - } - return (String) convert.convertFrom(String.class, array.content()); - } - parseBody(); - return params.getOrDefault(name, defaultValue); - } - - /** - * 获取指定的参数json值 - * - * @param 泛型 - * @param type 反序列化的类名 - * @param name 参数名 - * - * @return 参数值 - */ - public T getJsonParameter(java.lang.reflect.Type type, String name) { - if (this.frombody) { - if (array.isEmpty()) { - return null; - } - Convert convert = this.reqConvert; - if (convert == null) { - convert = jsonConvert; - } - if (type == byte[].class) { - return (T) array.getBytes(); - } - return (T) convert.convertFrom(type, array.content()); - } - String v = getParameter(name); - return v == null || v.isEmpty() ? null : jsonConvert.convertFrom(type, v); - } - - /** - * 获取指定的参数json值 - * - * @param 泛型 - * @param convert JsonConvert对象 - * @param type 反序列化的类名 - * @param name 参数名 - * - * @return 参数值 - */ - public T getJsonParameter(JsonConvert convert, java.lang.reflect.Type type, String name) { - String v = getParameter(name); - return v == null || v.isEmpty() ? null : convert.convertFrom(type, v); - } - - /** - * 获取指定的参数boolean值, 没有返回默认boolean值 - * - * @param name 参数名 - * @param defaultValue 默认boolean值 - * - * @return 参数值 - */ - public boolean getBooleanParameter(String name, boolean defaultValue) { - if (this.frombody) { - if (array.isEmpty()) { - return defaultValue; - } - Convert convert = this.reqConvert; - if (convert == null) { - convert = jsonConvert; - } - return (boolean) convert.convertFrom(boolean.class, array.content()); - } - parseBody(); - String value = params.get(name); - return value == null || value.length() == 0 ? defaultValue : Boolean.parseBoolean(value); - } - - /** - * 获取指定的参数short值, 没有返回默认short值 - * - * @param name 参数名 - * @param defaultValue 默认short值 - * - * @return 参数值 - */ - public short getShortParameter(String name, short defaultValue) { - if (this.frombody) { - if (array.isEmpty()) { - return defaultValue; - } - Convert convert = this.reqConvert; - if (convert == null) { - convert = jsonConvert; - } - return (short) convert.convertFrom(short.class, array.content()); - } - parseBody(); - String value = params.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return Short.decode(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * 获取指定的参数short值, 没有返回默认short值 - * - * @param radix 进制数 - * @param name 参数名 - * @param defaultValue 默认short值 - * - * @return 参数值 - */ - public short getShortParameter(int radix, String name, short defaultValue) { - if (this.frombody) { - if (array.isEmpty()) { - return (short) defaultValue; - } - Convert convert = this.reqConvert; - if (convert == null) { - convert = jsonConvert; - } - return (short) convert.convertFrom(short.class, array.content()); - } - parseBody(); - String value = params.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return (radix == 10 ? Short.decode(value) : Short.parseShort(value, radix)); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * 获取指定的参数short值, 没有返回默认short值 - * - * @param name 参数名 - * @param defaultValue 默认short值 - * - * @return 参数值 - */ - public short getShortParameter(String name, int defaultValue) { - if (this.frombody) { - if (array.isEmpty()) { - return (short) defaultValue; - } - Convert convert = this.reqConvert; - if (convert == null) { - convert = jsonConvert; - } - return (short) convert.convertFrom(short.class, array.content()); - } - parseBody(); - String value = params.get(name); - if (value == null || value.length() == 0) { - return (short) defaultValue; - } - try { - return Short.decode(value); - } catch (NumberFormatException e) { - return (short) defaultValue; - } - } - - /** - * 获取指定的参数int值, 没有返回默认int值 - * - * @param name 参数名 - * @param defaultValue 默认int值 - * - * @return 参数值 - */ - public int getIntParameter(String name, int defaultValue) { - if (this.frombody) { - if (array.isEmpty()) { - return defaultValue; - } - Convert convert = this.reqConvert; - if (convert == null) { - convert = jsonConvert; - } - return (int) convert.convertFrom(int.class, array.content()); - } - parseBody(); - String value = params.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return Integer.decode(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * 获取指定的参数int值, 没有返回默认int值 - * - * @param radix 进制数 - * @param name 参数名 - * @param defaultValue 默认int值 - * - * @return 参数值 - */ - public int getIntParameter(int radix, String name, int defaultValue) { - if (this.frombody) { - if (array.isEmpty()) { - return defaultValue; - } - Convert convert = this.reqConvert; - if (convert == null) { - convert = jsonConvert; - } - return (int) convert.convertFrom(int.class, array.content()); - } - parseBody(); - String value = params.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return (radix == 10 ? Integer.decode(value) : Integer.parseInt(value, radix)); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * 获取指定的参数long值, 没有返回默认long值 - * - * @param name 参数名 - * @param defaultValue 默认long值 - * - * @return 参数值 - */ - public long getLongParameter(String name, long defaultValue) { - if (this.frombody) { - if (array.isEmpty()) { - return defaultValue; - } - Convert convert = this.reqConvert; - if (convert == null) { - convert = jsonConvert; - } - return (long) convert.convertFrom(long.class, array.content()); - } - parseBody(); - String value = params.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return Long.decode(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * 获取指定的参数long值, 没有返回默认long值 - * - * @param radix 进制数 - * @param name 参数名 - * @param defaultValue 默认long值 - * - * @return 参数值 - */ - public long getLongParameter(int radix, String name, long defaultValue) { - if (this.frombody) { - if (array.isEmpty()) { - return defaultValue; - } - Convert convert = this.reqConvert; - if (convert == null) { - convert = jsonConvert; - } - return (long) convert.convertFrom(long.class, array.content()); - } - parseBody(); - String value = params.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return (radix == 10 ? Long.decode(value) : Long.parseLong(value, radix)); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * 获取指定的参数float值, 没有返回默认float值 - * - * @param name 参数名 - * @param defaultValue 默认float值 - * - * @return 参数值 - */ - public float getFloatParameter(String name, float defaultValue) { - if (this.frombody) { - if (array.isEmpty()) { - return defaultValue; - } - Convert convert = this.reqConvert; - if (convert == null) { - convert = jsonConvert; - } - return (float) convert.convertFrom(float.class, array.content()); - } - parseBody(); - String value = params.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return Float.parseFloat(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * 获取指定的参数double值, 没有返回默认double值 - * - * @param name 参数名 - * @param defaultValue 默认double值 - * - * @return 参数值 - */ - public double getDoubleParameter(String name, double defaultValue) { - if (this.frombody) { - if (array.isEmpty()) { - return defaultValue; - } - Convert convert = this.reqConvert; - if (convert == null) { - convert = jsonConvert; - } - return (double) convert.convertFrom(double.class, array.content()); - } - parseBody(); - String value = params.get(name); - if (value == null || value.length() == 0) { - return defaultValue; - } - try { - return Double.parseDouble(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * 获取翻页对象 同 getFlipper("flipper", false, 0); - * - * @return Flipper翻页对象 - */ - public org.redkale.source.Flipper getFlipper() { - return getFlipper(false, 0); - } - - /** - * 获取翻页对象 同 getFlipper("flipper", autoCreate, 0); - * - * @param autoCreate 无参数时是否创建新Flipper对象 - * - * @return Flipper翻页对象 - */ - public org.redkale.source.Flipper getFlipper(boolean autoCreate) { - return getFlipper(autoCreate, 0); - } - - /** - * 获取翻页对象 同 getFlipper("flipper", false, maxLimit); - * - * @param maxLimit 最大行数, 小于1则值为Flipper.DEFAULT_LIMIT - * - * @return Flipper翻页对象 - */ - public org.redkale.source.Flipper getFlipper(int maxLimit) { - return getFlipper(false, maxLimit); - } - - /** - * 获取翻页对象 同 getFlipper("flipper", autoCreate, maxLimit) - * - * @param autoCreate 无参数时是否创建新Flipper对象 - * @param maxLimit 最大行数, 小于1则值为Flipper.DEFAULT_LIMIT - * - * @return Flipper翻页对象 - */ - public org.redkale.source.Flipper getFlipper(boolean autoCreate, int maxLimit) { - return getFlipper("flipper", autoCreate, maxLimit); - } - - /** - * 获取翻页对象 https://redkale.org/pipes/users/list?flipper={'offset':0,'limit':20, 'sort':'createtime ASC'}
- * - * - * @param name Flipper对象的参数名,默认为 "flipper" - * @param autoCreate 无参数时是否创建新Flipper对象 - * @param maxLimit 最大行数, 小于1则值为Flipper.DEFAULT_LIMIT - * - * @return Flipper翻页对象 - */ - public org.redkale.source.Flipper getFlipper(String name, boolean autoCreate, int maxLimit) { - org.redkale.source.Flipper flipper = getJsonParameter(org.redkale.source.Flipper.class, name); - if (flipper == null) { -// if (maxLimit < 1) maxLimit = org.redkale.source.Flipper.DEFAULT_LIMIT; -// String limitstr = getParameter("limit"); -// if (limitstr != null && !limitstr.isEmpty()) { -// String offsetstr = getParameter("offset"); -// if (offsetstr != null && !offsetstr.isEmpty()) { -// int limit = Integer.parseInt(limitstr); -// int offset = Integer.parseInt(offsetstr); -// String sort = getParameter("sort"); -// if (limit > maxLimit) limit = maxLimit; -// flipper = new org.redkale.source.Flipper(limit, offset, sort); -// } -// } - } else if (flipper.getLimit() < 1 || (maxLimit > 0 && flipper.getLimit() > maxLimit)) { - flipper.setLimit(maxLimit); - } - if (flipper != null || !autoCreate) { - return flipper; - } - if (maxLimit < 1) { - maxLimit = org.redkale.source.Flipper.DEFAULT_LIMIT; - } - return new org.redkale.source.Flipper(maxLimit); - } -} +/* + * To change this license headers, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkale.net.http; + +import java.io.*; +import java.lang.annotation.Annotation; +import java.net.*; +import java.nio.ByteBuffer; +import java.nio.charset.*; +import java.util.*; +import java.util.function.Supplier; +import java.util.logging.Level; +import org.redkale.annotation.Comment; +import org.redkale.convert.*; +import org.redkale.convert.json.JsonConvert; +import org.redkale.net.Request; +import org.redkale.util.*; + +/** + * Http请求包 与javax.servlet.http.HttpServletRequest 基本类似。
+ * 同时提供json的解析接口: public Object getJsonParameter(Type type, String name)
+ * Redkale提倡带简单的参数的GET请求采用类似REST风格, 因此提供了 getRequstURIPath 系列接口。
+ * 例如简单的翻页查询
+ * /pipes/user/query/offset:0/limit:20
+ * 获取页号: int offset = request.getRequstURIPath("offset:", 0);
+ * 获取行数: int limit = request.getRequstURIPath("limit:", 10);
+ *

+ * 详情见: https://redkale.org + * + * @author zhangjx + */ +public class HttpRequest extends Request { + + private static final boolean pipelineSameHeaders = Boolean.getBoolean("redkale.http.request.pipeline.sameheaders"); + + protected static final Serializable CURRUSERID_NIL = new Serializable() { + }; + + protected static final int READ_STATE_ROUTE = 1; + + protected static final int READ_STATE_HEADER = 2; + + protected static final int READ_STATE_BODY = 3; + + protected static final int READ_STATE_END = 4; + + protected static final byte[] EMPTY_BYTES = new byte[0]; + + protected static final String METHOD_GET = "GET"; + + protected static final String METHOD_PUT = "PUT"; + + protected static final String METHOD_POST = "POST"; + + protected static final String METHOD_HEAD = "HEAD"; + + protected static final String METHOD_OPTIONS = "OPTIONS"; + + protected static final String HTTP_1_1 = "HTTP/1.1"; + + protected static final String HTTP_2_0 = "HTTP/2.0"; + + protected static final String HEAD_COOKIE = "Cookie"; + + protected static final String HEAD_CONNECTION = "Connection"; + + protected static final String HEAD_CONTENT_TYPE = "Content-Type"; + + protected static final String HEAD_CONTENT_LENGTH = "Content-Length"; + + protected static final String HEAD_ACCEPT = "Accept"; + + protected static final String HEAD_HOST = "Host"; + + protected static final String HEAD_UPGRADE = "Upgrade"; + + protected static final String HEAD_USER_AGENT = "User-Agent"; + + protected static final String HEAD_EXPECT = "Expect"; + + public static final String SESSIONID_NAME = "JSESSIONID"; + + //---------- header 相关参数 开始 ---------- + protected int headerLength; + + protected int headerHalfLen; + + protected String contentType; + + protected long contentLength = -1; + + protected String host; + + @Comment("原始的cookie字符串,解析后值赋给HttpCookie[] cookies") + protected String cookie; + + protected HttpCookie[] cookies; + + private boolean maybews = false; //是否可能是WebSocket + + private boolean expect = false; //是否Expect:100-continue + + protected boolean rpc; + + protected int readState = READ_STATE_ROUTE; + + // @since 2.1.0 + protected Serializable currentUserid = CURRUSERID_NIL; + + protected Supplier currentUserSupplier; + + protected boolean frombody; + + protected ConvertType reqConvertType; + + protected Convert reqConvert; + + protected ConvertType respConvertType; + + protected Convert respConvert; + + protected final Map headers = new HashMap<>(); + //---------- header 相关参数 结束 ---------- + + @Comment("Method GET/POST/...") + protected String method; + + protected boolean getmethod; + + protected String protocol; + + protected String requestURI; + + protected byte[] queryBytes; + + protected String newSessionid; + + protected final Map params = new HashMap<>(); + + protected boolean boundary = false; + + protected int moduleid; + + protected int actionid; + + protected Annotation[] annotations; + + protected String remoteAddr; + + protected String locale; + + private String lastRequestURIString; + + private byte[] lastRequestURIBytes; + + private final ByteArray array; + + private byte[] headerBytes; + + private boolean headerParsed = false; + + private boolean bodyParsed = false; + + private final String remoteAddrHeader; + + private final String localHeader; + + private final String localParameter; + + final HttpRpcAuthenticator rpcAuthenticator; + + HttpServlet.ActionEntry actionEntry; //仅供HttpServlet传递Entry使用 + + public HttpRequest(HttpContext context) { + this(context, new ByteArray()); + } + + protected HttpRequest(HttpContext context, ByteArray array) { + super(context); + this.array = array; + this.remoteAddrHeader = context.remoteAddrHeader; + this.localHeader = context.localHeader; + this.localParameter = context.localParameter; + this.rpcAuthenticator = context.rpcAuthenticator; + } + + @SuppressWarnings("OverridableMethodCallInConstructor") + protected HttpRequest(HttpContext context, HttpSimpleRequest req) { + super(context); + this.array = new ByteArray(); + this.remoteAddrHeader = null; + this.localHeader = null; + this.localParameter = null; + this.rpcAuthenticator = null; + if (req != null) { + initSimpleRequest(req, true); + } + } + + protected HttpRequest initSimpleRequest(HttpSimpleRequest req, boolean needPath) { + if (req != null) { + this.rpc = req.rpc; + this.traceid = req.traceid; + if (req.getBody() != null) { + this.array.put(req.getBody()); + } + if (req.getHeaders() != null) { + this.headers.putAll(req.getHeaders()); + } + this.frombody = req.isFrombody(); + this.reqConvertType = req.getReqConvertType(); + this.reqConvert = req.getReqConvertType() == null ? null : ConvertFactory.findConvert(req.getReqConvertType()); + this.respConvertType = req.getRespConvertType(); + this.respConvert = req.getRespConvertType() == null ? null : ConvertFactory.findConvert(req.getRespConvertType()); + if (req.getParams() != null) { + this.params.putAll(req.getParams()); + } + this.hashid = req.getHashid(); + if (req.getCurrentUserid() != null) { + this.currentUserid = req.getCurrentUserid(); + } + this.contentType = req.getContentType(); + this.remoteAddr = req.getRemoteAddr(); + this.locale = req.getLocale(); + if (needPath) { + this.requestURI = (req.getPath() == null || req.getPath().isEmpty()) ? req.getRequestURI() : (req.getPath() + req.getRequestURI()); + } else { + this.requestURI = req.getRequestURI(); + } + this.method = METHOD_POST; + if (req.getSessionid() != null && !req.getSessionid().isEmpty()) { + this.cookies = new HttpCookie[]{new HttpCookie(SESSIONID_NAME, req.getSessionid())}; + } + } + return this; + } + + public HttpSimpleRequest createSimpleRequest(String prefix) { + HttpSimpleRequest req = new HttpSimpleRequest(); + req.setBody(array.length() == 0 ? null : array.getBytes()); + if (!getHeaders().isEmpty()) { + if (headers.containsKey(Rest.REST_HEADER_RPC) + || headers.containsKey(Rest.REST_HEADER_CURRUSERID)) { //外部request不能包含RPC的header信息 + req.setHeaders(new HashMap<>(headers)); + req.removeHeader(Rest.REST_HEADER_RPC); + req.removeHeader(Rest.REST_HEADER_CURRUSERID); + } else { + req.setHeaders(headers); + } + } + parseBody(); + req.setParams(params.isEmpty() ? null : params); + req.setRemoteAddr(getRemoteAddr()); + req.setLocale(getLocale()); + req.setContentType(getContentType()); + req.setPath(prefix); + String uri = this.requestURI; + if (prefix != null && !prefix.isEmpty() && uri.startsWith(prefix)) { + uri = uri.substring(prefix.length()); + } + req.setHashid(this.hashid); + req.setRequestURI(uri); + req.setSessionid(getSessionid(false)); + req.setRpc(this.rpc); + req.setTraceid(this.traceid); + return req; + } + + protected boolean isWebSocket() { + return maybews && getmethod && "Upgrade".equalsIgnoreCase(getHeader("Connection")); + } + + protected boolean isExpect() { + return expect; + } + + protected void setKeepAlive(boolean keepAlive) { + this.keepAlive = keepAlive; + } + + protected boolean isKeepAlive() { + return this.keepAlive; + } + + protected ConvertType getRespConvertType() { + return this.respConvertType; + } + + protected Convert getRespConvert() { + return this.respConvert == null ? this.jsonConvert : this.respConvert; + } + + @Override + protected int readHeader(final ByteBuffer buf, final Request last) { + final ByteBuffer buffer = buf; + ByteArray bytes = array; + if (this.readState == READ_STATE_ROUTE) { + int rs = readMethodUriLine(buffer); + if (rs != 0) { + return rs; + } + this.readState = READ_STATE_HEADER; + } + if (this.readState == READ_STATE_HEADER) { + if (last != null && ((HttpRequest) last).headerLength > 0) { + final HttpRequest httplast = (HttpRequest) last; + int bufremain = buffer.remaining(); + int remainHalf = httplast.headerLength - this.headerHalfLen; + if (remainHalf > bufremain) { + bytes.put(buffer); + this.headerHalfLen += bufremain; + buffer.clear(); + return 1; + } + buffer.position(buffer.position() + remainHalf); + this.contentType = httplast.contentType; + this.contentLength = httplast.contentLength; + this.host = httplast.host; + this.cookie = httplast.cookie; + this.cookies = httplast.cookies; + this.keepAlive = httplast.keepAlive; + this.maybews = httplast.maybews; + this.expect = httplast.expect; + this.rpc = httplast.rpc; + this.traceid = httplast.traceid; + this.hashid = httplast.hashid; + this.currentUserid = httplast.currentUserid; + this.frombody = httplast.frombody; + this.reqConvertType = httplast.reqConvertType; + this.reqConvert = httplast.reqConvert; + this.respConvertType = httplast.respConvertType; + this.respConvert = httplast.respConvert; + this.headerLength = httplast.headerLength; + this.headerHalfLen = httplast.headerHalfLen; + this.headerBytes = httplast.headerBytes; + this.headerParsed = httplast.headerParsed; + this.headers.putAll(httplast.headers); + } else if (context.lazyHeaders && getmethod) { //非GET必须要读header,会有Content-Length + int rs = loadHeaderBytes(buffer); + if (rs != 0) { + return rs; + } + this.headerParsed = false; + } else { + int startpos = buffer.position(); + int rs = readHeaderLines(buffer, bytes); + if (rs != 0) { + this.headerHalfLen = bytes.length(); + return rs; + } + this.headerParsed = true; + this.headerLength = buffer.position() - startpos + this.headerHalfLen; + this.headerHalfLen = this.headerLength; + } + bytes.clear(); + this.readState = READ_STATE_BODY; + } + if (this.contentType != null && this.contentType.contains("boundary=")) { + this.boundary = true; + } + if (this.boundary) { + this.keepAlive = false; //文件上传必须设置keepAlive为false,因为文件过大时用户不一定会skip掉多余的数据 + } + if (this.readState == READ_STATE_BODY) { + if (this.contentLength > 0 && (this.contentType == null || !this.boundary)) { + if (this.contentLength > context.getMaxBody()) { + return -1; + } + bytes.put(buffer, Math.min((int) this.contentLength, buffer.remaining())); + int lr = (int) this.contentLength - bytes.length(); + if (lr == 0) { + this.readState = READ_STATE_END; + if (bytes.isEmpty()) { + this.bodyParsed = true; //no body data + } + } + return lr > 0 ? lr : 0; + } + if (buffer.hasRemaining() && (this.boundary || !this.keepAlive)) { + bytes.put(buffer, buffer.remaining()); //文件上传、HTTP1.0或Connection:close + } + this.readState = READ_STATE_END; + if (bytes.isEmpty()) { + this.bodyParsed = true; //no body data + } + } + //暂不考虑是keep-alive且存在body却没有指定Content-Length的情况 + return 0; + } + + private int loadHeaderBytes(final ByteBuffer buf) { + final ByteBuffer buffer = buf; + ByteArray bytes = array; + int remain = buffer.remaining(); + byte b1, b2, b3, b4; + for (;;) { + if (remain-- < 4) { //bytes不存放\r\n\r\n这4个字节 + bytes.put(buffer); + buffer.clear(); + if (bytes.length() > 0) { + byte rn1 = 0, rn2 = 0, rn3 = 0; + byte b = bytes.getLastByte(); + if (b == '\r' || b == '\n') { + rn3 = b; + bytes.backCount(); + if (bytes.length() > 0) { + b = bytes.getLastByte(); + if (b == '\r' || b == '\n') { + rn2 = b; + bytes.backCount(); + if (bytes.length() > 0) { + b = bytes.getLastByte(); + if (b == '\r' || b == '\n') { + rn1 = b; + bytes.backCount(); + } + } + } + } + } + if (rn1 != 0) { + buffer.put(rn1); + } + if (rn2 != 0) { + buffer.put(rn2); + } + if (rn3 != 0) { + buffer.put(rn3); + } + } + return 1; + } + b1 = buffer.get(); + bytes.put(b1); + if (b1 == '\r') { + remain--; + b2 = buffer.get(); + bytes.put(b2); + if (b2 == '\n') { + remain--; + b3 = buffer.get(); + bytes.put(b3); + if (b3 == '\r') { + remain--; + b4 = buffer.get(); + bytes.put(b4); + if (b4 == '\n') { + this.headerBytes = Utility.append(this.headerBytes, bytes.content(), 0, bytes.length()); + this.headerLength = this.headerBytes.length; + this.headerHalfLen = this.headerLength; + bytes.clear(); + return 0; + } + } + } + } + } + } + + //解析 GET /xxx HTTP/1.1 + private int readMethodUriLine(final ByteBuffer buf) { + final ByteBuffer buffer = buf; + Charset charset = this.context.getCharset(); + int remain = buffer.remaining(); + int size; + ByteArray bytes = array; + //读method + if (this.method == null) { + boolean flag = false; + if (remain >= 5) { + byte b1 = buffer.get(); + byte b2 = buffer.get(); + if (b2 == ' ') { + remain -= 2; + this.method = Character.toString(b1); + this.getmethod = false; + } else { + byte b3 = buffer.get(); + if (b3 == ' ') { + remain -= 3; + this.method = new String(new byte[]{b1, b2}); + this.getmethod = false; + } else { + byte b4 = buffer.get(); + if (b4 == ' ') { + remain -= 4; + if (b1 == 'G' && b2 == 'E' && b3 == 'T') { + this.method = METHOD_GET; + this.getmethod = true; + } else if (b1 == 'P' && b2 == 'U' && b3 == 'T') { + this.method = METHOD_PUT; + this.getmethod = false; + } else { + this.method = new String(new byte[]{b1, b2, b3}); + this.getmethod = false; + } + } else { + byte b5 = buffer.get(); + remain -= 5; + if (b5 == ' ') { + if (b1 == 'P' && b2 == 'O' && b3 == 'S' && b3 == 'T') { + this.method = METHOD_POST; + this.getmethod = false; + } else if (b1 == 'H' && b2 == 'E' && b3 == 'A' && b3 == 'D') { + this.method = METHOD_HEAD; + this.getmethod = false; + } else { + this.method = new String(new byte[]{b1, b2, b3, b4}); + this.getmethod = false; + } + } else { + flag = true; + bytes.put(b1, b2, b3, b4, b5); + } + } + } + } + } + if (flag) { + for (;;) { + if (remain-- < 1) { + buffer.clear(); + return 1; + } + byte b = buffer.get(); + if (b == ' ') { + break; + } + bytes.put(b); + } + size = bytes.length(); + byte[] content = bytes.content(); + if (size == 3) { + if (content[0] == 'G' && content[1] == 'E' && content[2] == 'T') { + this.method = METHOD_GET; + this.getmethod = true; + } else if (content[0] == 'P' && content[1] == 'U' && content[2] == 'T') { + this.method = METHOD_PUT; + this.getmethod = false; + } else { + this.method = bytes.toString(true, charset); + this.getmethod = false; + } + } else if (size == 4) { + this.getmethod = false; + if (content[0] == 'P' && content[1] == 'O' && content[2] == 'S' && content[3] == 'T') { + this.method = METHOD_POST; + } else if (content[0] == 'H' && content[1] == 'E' && content[2] == 'A' && content[3] == 'D') { + this.method = METHOD_HEAD; + } else { + this.method = bytes.toString(true, charset); + } + } else if (size == 7) { + this.getmethod = false; + if (content[0] == 'O' && content[1] == 'P' && content[2] == 'T' + && content[3] == 'I' && content[4] == 'O' && content[5] == 'N' && content[6] == 'S') { + this.method = METHOD_OPTIONS; + } else { + this.method = bytes.toString(true, charset); + } + } else { + this.method = bytes.toString(true, charset); + this.getmethod = false; + } + bytes.clear(); + } + } + + //读uri + if (this.requestURI == null) { + int qst = -1;//?的位置 + boolean decodeable = false; + boolean latin1 = true; + for (;;) { + if (remain-- < 1) { + buffer.clear(); + return 1; + } + byte b = buffer.get(); + if (b == ' ') { + break; + } + if (b == '?' && qst < 0) { + qst = bytes.length(); + } else if (!decodeable && (b == '+' || b == '%')) { + decodeable = true; + } else if (latin1 && (b < 0x20 || b >= 0x80)) { + latin1 = false; + } + bytes.put(b); + } + size = bytes.length(); + if (qst > 0) { //带?参数 + this.requestURI = 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.lastRequestURIString = null; + this.lastRequestURIBytes = null; + try { + addParameter(bytes, false, qst + 1, qlen); + } catch (Exception e) { + this.context.getLogger().log(Level.WARNING, "HttpRequest.addParameter error: " + bytes.toString(), e); + } + } else { + if (decodeable) { //需要转义 + this.requestURI = toDecodeString(bytes, 0, bytes.length(), charset); + this.lastRequestURIString = null; + this.lastRequestURIBytes = null; + } else if (context.lazyHeaders) { + byte[] lastURIBytes = lastRequestURIBytes; + if (lastURIBytes != null && lastURIBytes.length == size && bytes.deepEquals(lastURIBytes)) { + this.requestURI = this.lastRequestURIString; + } else { + this.requestURI = context.loadUriPath(bytes, latin1, charset);// bytes.toString(latin1, charset); + this.lastRequestURIString = this.requestURI; + this.lastRequestURIBytes = bytes.getBytes(); + } + } else { + this.requestURI = context.loadUriPath(bytes, latin1, charset); //bytes.toString(latin1, charset); + this.lastRequestURIString = null; + this.lastRequestURIBytes = null; + } + this.queryBytes = EMPTY_BYTES; + } + bytes.clear(); + } + //读protocol + for (;;) { + if (remain-- < 1) { + this.params.clear(); + buffer.clear(); + return 1; + } + byte b = buffer.get(); + if (b == '\r') { + if (remain-- < 1) { + this.params.clear(); + buffer.clear(); + buffer.put(b); + return 1; + } + if (buffer.get() != '\n') { + return -1; + } + break; + } + bytes.putWithoutCheck(b); + } + size = bytes.length(); + byte[] content = bytes.content(); + if (size == 8 && content[0] == 'H' && content[5] == '1' && content[7] == '1') { + this.protocol = HTTP_1_1; + } else if (size == 8 && content[0] == 'H' && content[5] == '2' && content[7] == '0') { + this.protocol = HTTP_2_0; + } else { + this.protocol = bytes.toString(true, charset); + } + bytes.clear(); + return 0; + } + + //解析Header Connection: keep-alive + private int readHeaderLines(final ByteBuffer buf, ByteArray bytes) { + final ByteBuffer buffer = buf; + Charset charset = this.context.getCharset(); + int remain = buffer.remaining(); + for (;;) { + bytes.clear(); + if (remain-- < 2) { + if (remain == 1) { + byte one = buffer.get(); + buffer.clear(); + buffer.put(one); + return 1; + } + buffer.clear(); + 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; + } + bytes.put(b1, b2); + for (;;) { // name + if (remain-- < 1) { + buffer.clear(); + buffer.put(bytes.content(), 0, bytes.length()); + return 1; + } + byte b = buffer.get(); + if (b == ':') { + break; + } else if (latin1 && (b < 0x20 || b >= 0x80)) { + latin1 = false; + } + bytes.put(b); + } + String name = parseHeaderName(latin1, bytes, charset); + bytes.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(bytes.content(), 0, bytes.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(bytes.content(), 0, bytes.length()); + buffer.put((byte) '\r'); + return 1; + } + if (buffer.get() != '\n') { + return -1; + } + break; + } + if (first) { + if (b <= ' ') { + space++; + continue; + } + first = false; + } + bytes.put(b); + } + String value; + int vlen = bytes.length(); + byte[] content = bytes.content(); + switch (name) { + case HEAD_CONTENT_TYPE: //Content-Type + this.contentType = bytes.toString(true, charset); + break; + case HEAD_CONTENT_LENGTH: //Content-Length + this.contentLength = Long.decode(bytes.toString(true, charset)); + break; + case HEAD_HOST: //Host + this.host = bytes.toString(charset); + break; + case HEAD_COOKIE: //Cookie + if (this.cookie == null || this.cookie.isEmpty()) { + this.cookie = bytes.toString(charset); + } else { + this.cookie += ";" + bytes.toString(charset); + } + break; + case HEAD_CONNECTION: //Connection + if (vlen > 0) { + if (vlen == 5 && content[0] == 'c' + && content[1] == 'l' && content[2] == 'o' + && content[3] == 's' && content[4] == 'e') { + value = "close"; + this.setKeepAlive(false); + } else if (vlen == 10 && content[0] == 'k' + && content[1] == 'e' && content[2] == 'e' + && content[3] == 'p' && content[4] == '-' + && content[5] == 'a' && content[6] == 'l' + && content[7] == 'i' && content[8] == 'v' + && content[9] == 'e') { + value = "keep-alive"; + this.setKeepAlive(true); + } else { + value = bytes.toString(charset); + this.setKeepAlive(true); + } + } else { + value = ""; + } + headers.put(HEAD_CONNECTION, value); + break; + case HEAD_UPGRADE: //Upgrade + this.maybews = vlen == 9 && content[0] == 'w' && content[1] == 'e' && content[2] == 'b' && content[3] == 's' + && content[4] == 'o' && content[5] == 'c' && content[6] == 'k' && content[7] == 'e' && content[8] == 't'; + headers.put(HEAD_UPGRADE, this.maybews ? "websocket" : bytes.toString(true, charset)); + break; + case HEAD_EXPECT: //Expect + this.expect = vlen == 12 && content[0] == '1' && content[1] == '0' && content[2] == '0' && content[3] == '-' + && content[4] == 'c' && content[5] == 'o' && content[6] == 'n' && content[7] == 't' && content[8] == 'i' + && content[9] == 'n' && content[10] == 'u' && content[11] == 'e'; + headers.put(HEAD_EXPECT, this.expect ? "100-continue" : bytes.toString(true, charset)); + break; + case Rest.REST_HEADER_RPC: //rest-rpc + this.rpc = vlen == 4 && content[0] == 't' && content[1] == 'r' && content[2] == 'u' && content[3] == 'e'; + headers.put(name, this.rpc ? "true" + : (vlen == 5 && content[0] == 'f' && content[1] == 'a' && content[2] == 'l' && content[3] == 's' && content[4] == 'e' + ? "false" : bytes.toString(true, charset))); + break; + case Rest.REST_HEADER_CURRUSERID: //rest-curruserid + value = bytes.toString(true, charset); + this.hashid = value.hashCode(); + this.currentUserid = value; + headers.put(name, value); + break; + case Rest.REST_HEADER_PARAM_FROM_BODY: //rest-param-from-body + this.frombody = vlen == 4 && content[0] == 't' && content[1] == 'r' && content[2] == 'u' && content[3] == 'e'; + headers.put(name, this.frombody ? "true" + : (vlen == 5 && content[0] == 'f' && content[1] == 'a' && content[2] == 'l' && content[3] == 's' && content[4] == 'e' + ? "false" : bytes.toString(true, charset))); + break; + case Rest.REST_HEADER_REQ_CONVERT_TYPE: //rest-req-convert-type + value = bytes.toString(true, charset); + reqConvertType = ConvertType.valueOf(value); + reqConvert = ConvertFactory.findConvert(reqConvertType); + headers.put(name, value); + break; + case Rest.REST_HEADER_RESP_CONVERT_TYPE: //rest-resp-convert-type + value = bytes.toString(true, charset); + respConvertType = ConvertType.valueOf(value); + respConvert = ConvertFactory.findConvert(respConvertType); + headers.put(name, value); + break; + default: + headers.put(name, bytes.toString(charset)); + } + } + } + + private void parseHeader() { + if (headerParsed) { + return; + } + headerParsed = true; + if (headerBytes == null) { + return; + } + if (array.isEmpty()) { + readHeaderLines(ByteBuffer.wrap(headerBytes), array); + array.clear(); + } else { //array存有body数据 + readHeaderLines(ByteBuffer.wrap(headerBytes), new ByteArray()); + } + } + + static String parseHeaderName(boolean latin1, ByteArray bytes, Charset charset) { + final int size = bytes.length(); + final byte[] bs = bytes.content(); + final byte first = bs[0]; + if ((first == 'H' || first == 'h') && size == 4) { //Host + if (bs[1] == 'o' && bs[2] == 's' && bs[3] == 't') { + return HEAD_HOST; + } + } else if ((first == 'A' || first == 'a') && size == 6) { //Accept + if (bs[1] == 'c' && bs[2] == 'c' && bs[3] == 'e' + && bs[4] == 'p' && bs[5] == 't') { + return HEAD_ACCEPT; + } + } else if (first == 'C' || first == 'c') { + if (size == 10) { //Connection + if (bs[1] == 'o' && bs[2] == 'n' && bs[3] == 'n' + && bs[4] == 'e' && bs[5] == 'c' && bs[6] == 't' + && bs[7] == 'i' && bs[8] == 'o' && bs[9] == 'n') { + return HEAD_CONNECTION; + } + } else if (size == 12) { //Content-Type + if (bs[1] == 'o' && bs[2] == 'n' && bs[3] == 't' + && bs[4] == 'e' && bs[5] == 'n' && bs[6] == 't' + && bs[7] == '-' && (bs[8] == 'T' || bs[8] == 't') + && bs[9] == 'y' && bs[10] == 'p' && bs[11] == 'e') { + return HEAD_CONTENT_TYPE; + } + } else if (size == 14) { //Content-Length + if (bs[1] == 'o' && bs[2] == 'n' && bs[3] == 't' + && bs[4] == 'e' && bs[5] == 'n' && bs[6] == 't' + && bs[7] == '-' && (bs[8] == 'L' || bs[8] == 'l') + && bs[9] == 'e' && bs[10] == 'n' && bs[11] == 'g' + && bs[12] == 't' + && bs[13] == 'h') { + return HEAD_CONTENT_LENGTH; + } + } else if (size == 6) { //Cookie + if (bs[1] == 'o' && bs[2] == 'o' && bs[3] == 'k' + && bs[4] == 'i' && bs[5] == 'e') { + return HEAD_COOKIE; + } + } + } else if (first == 'U' || first == 'u') { + if (size == 7) { //Upgrade + if (bs[1] == 'p' && bs[2] == 'g' && bs[3] == 'r' + && bs[4] == 'a' && bs[5] == 'd' && bs[6] == 'e') { + return HEAD_UPGRADE; + } + } else if (size == 10) { //User-Agent + if (bs[1] == 's' && bs[2] == 'e' && bs[3] == 'r' + && bs[4] == '-' && (bs[5] == 'A' || bs[5] == 'a') && bs[6] == 'g' + && bs[7] == 'e' && bs[8] == 'n' && bs[9] == 't') { + return HEAD_USER_AGENT; + } + } + } else if ((first == 'E' || first == 'e') && size == 6) { //Expect + if (bs[1] == 'x' && bs[2] == 'p' && bs[3] == 'e' + && bs[4] == 'c' && bs[5] == 't') { + return HEAD_EXPECT; + } + } + return bytes.toString(latin1, charset); + } + + @Override + protected HttpRequest copyHeader() { + if (!pipelineSameHeaders || !context.lazyHeaders) { + return null; + } + HttpRequest req = new HttpRequest(context, this.array); + req.headerLength = this.headerLength; + req.headerBytes = this.headerBytes; + req.headerParsed = this.headerParsed; + req.contentType = this.contentType; + req.contentLength = this.contentLength; + req.host = this.host; + req.cookie = this.cookie; + req.cookies = this.cookies; + req.keepAlive = this.keepAlive; + req.maybews = this.maybews; + req.expect = this.expect; + req.rpc = this.rpc; + req.traceid = this.traceid; + req.hashid = this.hashid; + req.currentUserid = this.currentUserid; + req.currentUserSupplier = this.currentUserSupplier; + req.frombody = this.frombody; + req.reqConvertType = this.reqConvertType; + req.reqConvert = this.reqConvert; + req.respConvert = this.respConvert; + req.respConvertType = this.respConvertType; + req.headers.putAll(this.headers); + return req; + } + + @Override + protected Serializable getRequestid() { + return null; + } + + @Override + protected void prepare() { + this.keepAlive = true; //默认HTTP/1.1 + } + + @Override + protected void recycle() { + //header + this.headerLength = 0; + this.headerHalfLen = 0; + this.headerBytes = null; + this.headerParsed = false; + this.contentType = null; + this.contentLength = -1; + this.host = null; + this.cookie = null; + this.cookies = null; + this.maybews = false; + this.expect = false; + this.rpc = false; + this.readState = READ_STATE_ROUTE; + this.currentUserid = CURRUSERID_NIL; + this.currentUserSupplier = null; + this.frombody = false; + this.reqConvertType = null; + this.reqConvert = null; + this.respConvert = jsonConvert; + this.respConvertType = null; + this.headers.clear(); + //其他 + this.newSessionid = null; + this.method = null; + this.getmethod = false; + this.protocol = null; + this.requestURI = null; + this.queryBytes = null; + this.boundary = false; + this.bodyParsed = false; + this.moduleid = 0; + this.actionid = 0; + this.annotations = null; + this.remoteAddr = null; + this.params.clear(); + this.array.clear(); + //内部 + this.actionEntry = null; + super.recycle(); + } + + protected void skipBodyParse() { + this.bodyParsed = true; + } + + private void parseBody() { + if (this.boundary || bodyParsed) { + return; + } + bodyParsed = true; + if (this.getContentType() != null && this.contentType.toLowerCase().contains("x-www-form-urlencoded")) { + addParameter(array, true, 0, array.length()); + } + } + + private void addParameter(final ByteArray array, final boolean body, final int offset, final int len) { + if (len < 1) { + return; + } + Charset charset = this.context.getCharset(); + int limit = offset + len; + int keypos = array.indexOf(offset, limit, '='); + int valpos = array.indexOf(offset, limit, '&'); + if (keypos <= 0 || (valpos >= 0 && valpos < keypos)) { + if (valpos > 0) { + addParameter(array, body, valpos + 1, limit - valpos - 1); + } + return; + } + String name = toDecodeString(array, offset, keypos - offset, charset); + if (body && !name.isEmpty() && name.charAt(0) == '<') { + return; //内容可能是xml格式; 如: = 0) { + addParameter(array, body, valpos + 1, limit - valpos - 1); + } + } + + protected HttpRequest setMethod(String method) { + this.method = method; + this.getmethod = METHOD_GET.equalsIgnoreCase(method); + return this; + } + + protected HttpRequest setRequestURI(String requestURI) { + this.requestURI = requestURI; + return this; + } + + protected HttpRequest setRemoteAddr(String remoteAddr) { + this.remoteAddr = remoteAddr; + return this; + } + + protected HttpRequest setLocale(String locale) { + this.locale = locale; + return this; + } + + protected HttpRequest setParameter(String name, String value) { + this.params.put(name, value); + return this; + } + + protected HttpRequest setHeader(String name, String value) { + this.headers.put(name, value); + return this; + } + + protected HttpRequest removeParameter(String name) { + this.params.remove(name); + return this; + } + + protected HttpRequest removeHeader(String name) { + this.headers.remove(name); + return this; + } + + protected static String toDecodeString(ByteArray array, int offset, int len, final Charset charset) { + byte[] content = array.content(); + if (len == 1) { + return Character.toString(content[offset]); + } else if (len == 2 && content[offset] >= 0x20 && content[offset] < 0x80) { + return new String(content, 0, offset, len); + } else if (len == 3 && content[offset + 1] >= 0x20 && content[offset + 1] < 0x80) { + return new String(content, 0, offset, len); + } + int start = offset; + final int end = offset + len; + boolean flag = false; //是否需要转义 + byte[] bs = content; + for (int i = offset; i < end; i++) { + if (content[i] == '+' || content[i] == '%') { + flag = true; + break; + } + } + if (flag) { + int index = 0; + bs = new byte[len]; + for (int i = offset; i < end; i++) { + switch (content[i]) { + case '+': + bs[index] = ' '; + break; + case '%': + bs[index] = (byte) ((hexBit(content[++i]) * 16 + hexBit(content[++i]))); + break; + default: + bs[index] = content[i]; + break; + } + index++; + } + start = 0; + len = index; + } + return new String(bs, start, len, charset == null ? StandardCharsets.UTF_8 : charset); + } + + private static int hexBit(byte b) { + if ('0' <= b && '9' >= b) { + return b - '0'; + } + if ('a' <= b && 'z' >= b) { + return b - 'a' + 10; + } + if ('A' <= b && 'Z' >= b) { + return b - 'A' + 10; + } + return b; + } + + @Override + protected T setProperty(String name, T value) { + return super.setProperty(name, value); + } + + @Override + @SuppressWarnings("unchecked") + protected T getProperty(String name) { + return super.getProperty(name); + } + + @Override + protected T removeProperty(String name) { + return super.removeProperty(name); + } + + /** + * 设置当前用户ID, 通常在HttpServlet.preExecute方法里设置currentUserid
+ * 数据类型只能是int、long、String、JavaBean + * + * @param 泛型 + * @param userid 用户ID + * + * @return HttpRequest + * + * @since 2.1.0 + */ + public HttpRequest setCurrentUserid(T userid) { + this.currentUserid = userid; + return this; + } + + /** + * 获取当前用户ID的int值
+ * + * @return 用户ID + * + * @since 2.4.0 + */ + @SuppressWarnings("unchecked") + public int currentIntUserid() { + if (currentUserid == CURRUSERID_NIL || currentUserid == null) { + return 0; + } + if (this.currentUserid instanceof Number) { + return ((Number) this.currentUserid).intValue(); + } + String uid = this.currentUserid.toString(); + return uid.isEmpty() ? 0 : Integer.parseInt(uid); + } + + /** + * 获取当前用户ID的long值
+ * + * @return 用户ID + * + * @since 2.7.0 + */ + @SuppressWarnings("unchecked") + public long currentLongUserid() { + if (currentUserid == CURRUSERID_NIL || currentUserid == null) { + return 0L; + } + if (this.currentUserid instanceof Number) { + return ((Number) this.currentUserid).longValue(); + } + String uid = this.currentUserid.toString(); + return uid.isEmpty() ? 0L : Long.parseLong(uid); + } + + /** + * 获取当前用户ID
+ * + * @param 数据类型只能是int、long、String、JavaBean + * @param type 类型 + * + * @return 用户ID + * + * @since 2.1.0 + */ + @SuppressWarnings("unchecked") + public T currentUserid(Class type) { + if (currentUserid == CURRUSERID_NIL || currentUserid == null) { + if (type == int.class || type == Integer.class) { + return (T) (Integer) (int) 0; + } + if (type == long.class || type == Long.class) { + return (T) (Long) (long) 0; + } + return null; + } + if (type == int.class || type == Integer.class) { + if (this.currentUserid instanceof Number) { + return (T) (Integer) ((Number) this.currentUserid).intValue(); + } + String uid = this.currentUserid.toString(); + return (T) (Integer) (uid.isEmpty() ? 0 : Integer.parseInt(uid)); + } + if (type == long.class || type == Long.class) { + if (this.currentUserid instanceof Number) { + return (T) (Long) ((Number) this.currentUserid).longValue(); + } + String uid = this.currentUserid.toString(); + return (T) (Long) (uid.isEmpty() ? 0L : Long.parseLong(uid)); + } + if (type == String.class) { + return (T) this.currentUserid.toString(); + } + if (this.currentUserid instanceof CharSequence) { + return JsonConvert.root().convertFrom(type, this.currentUserid.toString()); + } + return (T) this.currentUserid; + } + + /** + * 建议使用 setCurrentUserid, 通过userid从Service或缓存中获取用户信息
+ * 设置当前用户信息, 通常在HttpServlet.preExecute方法里设置currentUser
+ * 数据类型由@HttpUserType指定 + * + * @param supplier currentUser对象方法 + * + * @since 2.4.0 + * + * @return HttpRequest + */ + public HttpRequest setCurrentUserSupplier(Supplier supplier) { + this.currentUserSupplier = supplier; + return this; + } + + /** + * 建议使用 currentUserid, 通过userid从Service或缓存中获取用户信息
+ * 获取当前用户信息
+ * 数据类型由@HttpUserType指定 + * + * @param @HttpUserType指定的用户信息类型 + * + * @return 用户信息 + */ + @SuppressWarnings("unchecked") + public T currentUser() { + Supplier supplier = this.currentUserSupplier; + return (T) (supplier == null ? null : supplier.get()); + } + + /** + * 获取模块ID,来自@HttpServlet.moduleid() + * + * @return 模块ID + */ + @ConvertDisabled + public int getModuleid() { + return this.moduleid; + } + + /** + * 获取操作ID,来自@HttpMapping.actionid() + * + * @return 模块ID + */ + @ConvertDisabled + public int getActionid() { + return this.actionid; + } + + /** + * 获取当前操作Method上的注解集合 + * + * @return Annotation[] + */ + @ConvertDisabled + public Annotation[] getAnnotations() { + if (this.annotations == null) { + return new Annotation[0]; + } + Annotation[] newanns = new Annotation[this.annotations.length]; + System.arraycopy(this.annotations, 0, newanns, 0, newanns.length); + return newanns; + } + + /** + * 获取当前操作Method上的注解 + * + * @param 注解泛型 + * @param annotationClass 注解类型 + * + * @return Annotation + */ + public T getAnnotation(Class annotationClass) { + if (this.annotations == null) { + return null; + } + for (Annotation ann : this.annotations) { + if (ann.getClass() == annotationClass) { + return (T) ann; + } + } + return null; + } + + /** + * 获取当前操作Method上的注解集合 + * + * @param 注解泛型 + * @param annotationClass 注解类型 + * + * @return Annotation[] + */ + public T[] getAnnotationsByType(Class annotationClass) { + if (this.annotations == null) { + return Creator.newArray(annotationClass, 0); + } + T[] news = Creator.newArray(annotationClass, this.annotations.length); + int index = 0; + for (Annotation ann : this.annotations) { + if (ann.getClass() == annotationClass) { + news[index++] = (T) ann; + } + } + if (index < 1) { + return Creator.newArray(annotationClass, 0); + } + return Arrays.copyOf(news, index); + } + + /** + * 获取客户端地址IP + * + * @return 地址 + */ + @ConvertDisabled + public SocketAddress getRemoteAddress() { + return this.channel == null || !this.channel.isOpen() ? null : this.channel.getRemoteAddress(); + } + + /** + * 获取客户端地址IP, 与getRemoteAddress() 的区别在于:本方法优先取header中指定为RemoteAddress名的值,没有则返回getRemoteAddress()的getHostAddress()。
+ * 本方法适用于服务前端有如nginx的代理服务器进行中转,通过 getRemoteAddress()是获取不到客户端的真实IP。 + * + * @return 地址 + */ + public String getRemoteAddr() { + if (this.remoteAddr != null) { + return this.remoteAddr; + } + parseHeader(); + if (remoteAddrHeader != null) { + String val = getHeader(remoteAddrHeader); + if (val != null) { + this.remoteAddr = val; + return val; + } + } + SocketAddress addr = getRemoteAddress(); + if (addr == null) { + return ""; + } + if (addr instanceof InetSocketAddress) { + this.remoteAddr = ((InetSocketAddress) addr).getAddress().getHostAddress(); + return this.remoteAddr; + } + this.remoteAddr = String.valueOf(addr); + return this.remoteAddr; + } + + /** + * 获取国际化Locale,值可以取之于header或parameter + * + * @return 国际化Locale + */ + public String getLocale() { + if (this.locale != null) { + return this.locale; + } + if (localHeader != null) { + String val = getHeader(localHeader); + if (val != null) { + this.locale = val; + return val; + } + } + if (localParameter != null) { + String val = getParameter(localParameter); + if (val != null) { + this.locale = val; + return val; + } + } + return this.locale; + } + + /** + * 获取请求内容指定的编码字符串 + * + * @param charset 编码 + * + * @return 内容 + */ + public String getBody(final Charset charset) { + return charset == null ? array.toString() : array.toString(charset); + } + + /** + * 获取请求内容的UTF-8编码字符串 + * + * @return 内容 + */ + @ConvertDisabled + public String getBodyUTF8() { + return array.toString(StandardCharsets.UTF_8); + } + + /** + * 获取请求内容的JavaBean对象 + * + * @param 泛型 + * @param type 类型 + * + * @return 内容 + */ + public T getBodyJson(java.lang.reflect.Type type) { + if (array == null || array.isEmpty()) { + return null; + } + Convert convert = this.reqConvert; + if (convert == null) { + convert = context.getJsonConvert(); + } + if (type == byte[].class) { + return (T) array.getBytes(); + } + return (T) convert.convertFrom(type, array.content()); + } + + /** + * 获取请求内容的JavaBean对象 + * + * @param 泛型 + * @param convert Convert + * @param type 类型 + * + * @return 内容 + */ + public T getBodyJson(Convert convert, java.lang.reflect.Type type) { + if (array.isEmpty()) { + return null; + } + if (type == byte[].class) { + return (T) array.getBytes(); + } + return (T) convert.convertFrom(type, array.content()); + } + + /** + * 获取请求内容的byte[] + * + * @return 内容 + */ + public byte[] getBody() { + return array.length() == 0 ? null : array.getBytes(); + } + + /** + * 直接获取body对象 + * + * @return body对象 + */ + @ConvertDisabled + protected ByteArray getDirectBody() { + return array; + } + + @Override + public String toString() { + parseBody(); + return this.getClass().getSimpleName() + "{\r\n method: " + this.method + ", \r\n requestURI: " + this.requestURI + + (this.frombody ? (", \r\n frombody: " + this.frombody) : "") + + (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)) : "") + + (this.getRemoteAddr() != null ? (", \r\n remoteAddr: " + this.getRemoteAddr()) : "") + + (this.cookie != null ? (", \r\n cookies: " + this.cookie) : "") + + (this.getContentType() != null ? (", \r\n contentType: " + this.contentType) : "") + + (this.protocol != null ? (", \r\n protocol: " + this.protocol) : "") + + (this.getHost() != null ? (", \r\n host: " + this.host) : "") + + (this.getContentLength() >= 0 ? (", \r\n contentLength: " + this.contentLength) : "") + + (this.array.length() > 0 ? (", \r\n bodyLength: " + this.array.length()) : "") + + (this.boundary || this.array.isEmpty() ? "" : (", \r\n bodyContent: " + (this.respConvertType == null || this.respConvertType == ConvertType.JSON ? this.getBodyUTF8() : Arrays.toString(getBody())))) + + ", \r\n params: " + toMapString(this.params, 4) + + ", \r\n header: " + toMapString(this.headers, 4) + + "\r\n}"; //this.headers.toString(4) + } + + private static CharSequence toMapString(Map map, int indent) { + final String space = " ".repeat(indent); + StringBuilder sb = new StringBuilder(); + sb.append("{\r\n"); + for (Map.Entry en : map.entrySet()) { + sb.append(space).append(" '").append(en.getKey()).append("': '").append(en.getValue()).append("',\r\n"); + } + sb.append(space).append('}'); + return sb; + } + + /** + * 获取文件上传对象 + * + * @return 文件上传对象 + */ + @ConvertDisabled + public final MultiContext getMultiContext() { + final InputStream in = newInputStream(); + return new MultiContext(context.getCharset(), this.getContentType(), this.params, + new BufferedInputStream(in, Math.max(array.length(), 8192)) { + { + array.copyTo(this.buf); + this.count = array.length(); + } + }, null); + } + + /** + * 是否上传文件请求 + * + * @return boolean + */ + public final boolean isMultipart() { + return boundary; + } + + /** + * 获取文件上传信息列表 + * + * @return 文件上传对象集合 + * + * @throws IOException IO异常 + */ + @ConvertDisabled + public final Iterable multiParts() throws IOException { + return getMultiContext().parts(); + } + + /** + * 获取sessionid + * + * @param autoCreate 无sessionid是否自动创建 + * + * @return sessionid + */ + @ConvertDisabled + public String getSessionid(boolean autoCreate) { + String sessionid = getCookie(SESSIONID_NAME, null); + if (autoCreate && (sessionid == null || sessionid.isEmpty())) { + sessionid = context.createSessionid(); + this.newSessionid = sessionid; + } + return sessionid; + } + + /** + * 更新sessionid + * + * @return 新的sessionid值 + */ + public String changeSessionid() { + this.newSessionid = context.createSessionid(); + return newSessionid; + } + + /** + * 指定值更新sessionid + * + * @param newSessionid 新sessionid值 + * + * @return 新的sessionid值 + */ + public String changeSessionid(String newSessionid) { + this.newSessionid = newSessionid == null ? context.createSessionid() : newSessionid.trim(); + return newSessionid; + } + + /** + * 使sessionid失效 + */ + public void invalidateSession() { + this.newSessionid = ""; //为空表示删除sessionid + } + + /** + * 获取所有Cookie对象 + * + * @return cookie对象数组 + */ + public HttpCookie[] getCookies() { + parseHeader(); + if (this.cookies == null) { + this.cookies = parseCookies(this.cookie); + } + return this.cookies.length == 0 ? null : this.cookies; + } + + /** + * 获取Cookie值 + * + * @param name cookie名 + * + * @return cookie值 + */ + public String getCookie(String name) { + return getCookie(name, null); + } + + /** + * 获取Cookie值, 没有返回默认值 + * + * @param name cookie名 + * @param dfvalue 默认cookie值 + * + * @return cookie值 + */ + public String getCookie(String name, String dfvalue) { + HttpCookie[] cs = getCookies(); + if (cs == null) { + return dfvalue; + } + for (HttpCookie c : cs) { + if (name.equals(c.getName())) { + return c.getValue(); + } + } + return dfvalue; + } + + private static HttpCookie[] parseCookies(String cookiestr) { + if (cookiestr == null || cookiestr.isEmpty()) { + return new HttpCookie[0]; + } + String str = cookiestr.replaceAll("(^;)|(;$)", "").replaceAll(";+", ";"); + if (str.isEmpty()) { + return new HttpCookie[0]; + } + String[] strs = str.split(";"); + HttpCookie[] cookies = new HttpCookie[strs.length]; + for (int i = 0; i < strs.length; i++) { + String s = strs[i]; + int pos = s.indexOf('='); + String v = (pos < 0 ? "" : s.substring(pos + 1)); + if (v.indexOf('"') == 0 && v.lastIndexOf('"') == v.length() - 1) { + v = v.substring(1, v.length() - 1); + } + cookies[i] = new HttpCookie((pos < 0 ? s : s.substring(0, pos)), v); + } + return cookies; + } + + /** + * 获取协议名 http、https、ws、wss等 + * + * @return protocol + */ + public String getProtocol() { + return protocol; + } + + /** + * 获取请求方法 GET、POST等 + * + * @return method + */ + public String getMethod() { + return method; + } + + /** + * 获取Content-Type的header值 + * + * @return contentType + */ + public String getContentType() { + if (contentType == null) { + parseHeader(); + } + return contentType; + } + + /** + * 获取请求内容的长度, 为-1表示内容长度不确定 + * + * @return 内容长度 + */ + public long getContentLength() { + if (contentLength < 1) { + parseHeader(); + } + return contentLength; + } + + /** + * 获取Host的Header值 + * + * @return Host + */ + public String getHost() { + if (host == null) { + parseHeader(); + } + return host; + } + + /** + * 获取请求的URL + * + * @return 请求的URL + */ + public String getRequestURI() { + return requestURI; + } + + /** + * 获取请求参数的byte[] + * + * @return byte[] + */ + public byte[] getQueryBytes() { + return queryBytes; + } + + /** + * 截取getRequestURI最后的一个/后面的部分 + * + * @return String + */ + @ConvertDisabled + public String getRequstURILastPath() { + if (requestURI == null) { + return ""; + } + return requestURI.substring(requestURI.lastIndexOf('/') + 1); + } + + /** + * 获取请求URL最后的一个/后面的部分的short值
+ * 例如请求URL /pipes/user/query/2
+ * 获取type参数: short type = request.getRequstURILastPath((short)0); //type = 2 + * + * @param defvalue 默认short值 + * + * @return short值 + */ + public short getRequstURILastPath(short defvalue) { + String val = getRequstURILastPath(); + if (val.isEmpty()) { + return defvalue; + } + try { + return Short.parseShort(val); + } catch (NumberFormatException e) { + return defvalue; + } + } + + /** + * 获取请求URL最后的一个/后面的部分的short值
+ * 例如请求URL /pipes/user/query/2
+ * 获取type参数: short type = request.getRequstURILastPath(16, (short)0); //type = 2 + * + * @param radix 进制数 + * @param defvalue 默认short值 + * + * @return short值 + */ + public short getRequstURILastPath(int radix, short defvalue) { + String val = getRequstURILastPath(); + if (val.isEmpty()) { + return defvalue; + } + try { + return Short.parseShort(val, radix); + } catch (NumberFormatException e) { + return defvalue; + } + } + + /** + * 获取请求URL最后的一个/后面的部分的int值
+ * 例如请求URL /pipes/user/query/2
+ * 获取type参数: int type = request.getRequstURILastPath(0); //type = 2 + * + * @param defvalue 默认int值 + * + * @return int值 + */ + public int getRequstURILastPath(int defvalue) { + String val = getRequstURILastPath(); + try { + return val.isEmpty() ? defvalue : Integer.parseInt(val); + } catch (NumberFormatException e) { + return defvalue; + } + } + + /** + * 获取请求URL最后的一个/后面的部分的int值
+ * 例如请求URL /pipes/user/query/2
+ * 获取type参数: int type = request.getRequstURILastPath(16, 0); //type = 2 + * + * @param radix 进制数 + * @param defvalue 默认int值 + * + * @return int值 + */ + public int getRequstURILastPath(int radix, int defvalue) { + String val = getRequstURILastPath(); + try { + return val.isEmpty() ? defvalue : Integer.parseInt(val, radix); + } catch (NumberFormatException e) { + return defvalue; + } + } + + /** + * 获取请求URL最后的一个/后面的部分的float值
+ * 例如请求URL /pipes/user/query/2
+ * 获取type参数: float type = request.getRequstURILastPath(0.0f); //type = 2.0f + * + * @param defvalue 默认float值 + * + * @return float值 + */ + public float getRequstURILastPath(float defvalue) { + String val = getRequstURILastPath(); + try { + return val.isEmpty() ? defvalue : Float.parseFloat(val); + } catch (NumberFormatException e) { + return defvalue; + } + } + + /** + * 获取请求URL最后的一个/后面的部分的int值
+ * 例如请求URL /pipes/user/query/2
+ * 获取type参数: long type = request.getRequstURILastPath(0L); //type = 2 + * + * @param defvalue 默认long值 + * + * @return long值 + */ + public long getRequstURILastPath(long defvalue) { + String val = getRequstURILastPath(); + try { + return val.isEmpty() ? defvalue : Long.parseLong(val); + } catch (NumberFormatException e) { + return defvalue; + } + } + + /** + * 获取请求URL最后的一个/后面的部分的int值
+ * 例如请求URL /pipes/user/query/2
+ * 获取type参数: long type = request.getRequstURILastPath(16, 0L); //type = 2 + * + * @param radix 进制数 + * @param defvalue 默认long值 + * + * @return long值 + */ + public long getRequstURILastPath(int radix, long defvalue) { + String val = getRequstURILastPath(); + try { + return val.isEmpty() ? defvalue : Long.parseLong(val, radix); + } catch (NumberFormatException e) { + return defvalue; + } + } + + /** + * 获取请求URL最后的一个/后面的部分的double值
+ * 例如请求URL /pipes/user/query/2
+ * 获取type参数: double type = request.getRequstURILastPath(0.0); //type = 2.0 + * + * @param defvalue 默认double值 + * + * @return double值 + */ + public double getRequstURILastPath(double defvalue) { + String val = getRequstURILastPath(); + try { + return val.isEmpty() ? defvalue : Double.parseDouble(val); + } catch (NumberFormatException e) { + return defvalue; + } + } + + /** + * + * 从prefix之后截取getRequestURI再对"/"进行分隔 + *

+ * @param prefix 前缀 + * + * @return String[] + */ + public String[] getRequstURIPaths(String prefix) { + if (requestURI == null || prefix == null) { + return new String[0]; + } + return requestURI.substring(requestURI.indexOf(prefix) + prefix.length() + (prefix.endsWith("/") ? 0 : 1)).split("/"); + } + + /** + * 获取请求URL分段中含prefix段的值
+ * 例如请求URL /pipes/user/query/name:hello
+ * 获取name参数: String name = request.getRequstURIPath("name:", "none"); + * + * @param prefix prefix段前缀 + * @param defvalue 默认值 + * + * @return prefix截断后的值 + */ + public String getRequstURIPath(String prefix, String defvalue) { + if (requestURI == null || prefix == null || prefix.isEmpty()) { + return defvalue; + } + int pos = requestURI.indexOf(prefix); + if (pos < 0) { + return defvalue; + } + String sub = requestURI.substring(pos + prefix.length()); + pos = sub.indexOf('/'); + return pos < 0 ? sub : sub.substring(0, pos); + } + + /** + * 获取请求URL分段中含prefix段的short值
+ * 例如请求URL /pipes/user/query/type:10
+ * 获取type参数: short type = request.getRequstURIPath("type:", (short)0); + * + * @param prefix prefix段前缀 + * @param defvalue 默认short值 + * + * @return short值 + */ + public short getRequstURIPath(String prefix, short defvalue) { + String val = getRequstURIPath(prefix, null); + try { + return val == null ? defvalue : Short.parseShort(val); + } catch (NumberFormatException e) { + return defvalue; + } + } + + /** + * 获取请求URL分段中含prefix段的short值
+ * 例如请求URL /pipes/user/query/type:a
+ * 获取type参数: short type = request.getRequstURIPath(16, "type:", (short)0); //type = 10 + * + * @param radix 进制数 + * @param prefix prefix段前缀 + * @param defvalue 默认short值 + * + * @return short值 + */ + public short getRequstURIPath(int radix, String prefix, short defvalue) { + String val = getRequstURIPath(prefix, null); + try { + return val == null ? defvalue : Short.parseShort(val, radix); + } catch (NumberFormatException e) { + return defvalue; + } + } + + /** + * 获取请求URL分段中含prefix段的int值
+ * 例如请求URL /pipes/user/query/offset:0/limit:50
+ * 获取offset参数: int offset = request.getRequstURIPath("offset:", 0);
+ * 获取limit参数: int limit = request.getRequstURIPath("limit:", 20);
+ * + * @param prefix prefix段前缀 + * @param defvalue 默认int值 + * + * @return int值 + */ + public int getRequstURIPath(String prefix, int defvalue) { + String val = getRequstURIPath(prefix, null); + try { + return val == null ? defvalue : Integer.parseInt(val); + } catch (NumberFormatException e) { + return defvalue; + } + } + + /** + * 获取请求URL分段中含prefix段的int值
+ * 例如请求URL /pipes/user/query/offset:0/limit:50
+ * 获取offset参数: int offset = request.getRequstURIPath("offset:", 0);
+ * 获取limit参数: int limit = request.getRequstURIPath(16, "limit:", 20); // limit = 16
+ * + * @param radix 进制数 + * @param prefix prefix段前缀 + * @param defvalue 默认int值 + * + * @return int值 + */ + public int getRequstURIPath(int radix, String prefix, int defvalue) { + String val = getRequstURIPath(prefix, null); + try { + return val == null ? defvalue : Integer.parseInt(val, radix); + } catch (NumberFormatException e) { + return defvalue; + } + } + + /** + * 获取请求URL分段中含prefix段的float值
+ * 例如请求URL /pipes/user/query/point:40.0
+ * 获取time参数: float point = request.getRequstURIPath("point:", 0.0f); + * + * @param prefix prefix段前缀 + * @param defvalue 默认float值 + * + * @return float值 + */ + public float getRequstURIPath(String prefix, float defvalue) { + String val = getRequstURIPath(prefix, null); + try { + return val == null ? defvalue : Float.parseFloat(val); + } catch (NumberFormatException e) { + return defvalue; + } + } + + /** + * 获取请求URL分段中含prefix段的long值
+ * 例如请求URL /pipes/user/query/time:1453104341363/id:40
+ * 获取time参数: long time = request.getRequstURIPath("time:", 0L); + * + * @param prefix prefix段前缀 + * @param defvalue 默认long值 + * + * @return long值 + */ + public long getRequstURIPath(String prefix, long defvalue) { + String val = getRequstURIPath(prefix, null); + try { + return val == null ? defvalue : Long.parseLong(val); + } catch (NumberFormatException e) { + return defvalue; + } + } + + /** + * 获取请求URL分段中含prefix段的long值
+ * 例如请求URL /pipes/user/query/time:1453104341363/id:40
+ * 获取time参数: long time = request.getRequstURIPath(16, "time:", 0L); + * + * @param radix 进制数 + * @param prefix prefix段前缀 + * @param defvalue 默认long值 + * + * @return long值 + */ + public long getRequstURIPath(int radix, String prefix, long defvalue) { + String val = getRequstURIPath(prefix, null); + try { + return val == null ? defvalue : Long.parseLong(val, radix); + } catch (NumberFormatException e) { + return defvalue; + } + } + + /** + * 获取请求URL分段中含prefix段的double值
+ * 例如请求URL /pipes/user/query/point:40.0
+ * 获取time参数: double point = request.getRequstURIPath("point:", 0.0); + * + * @param prefix prefix段前缀 + * @param defvalue 默认double值 + * + * @return double值 + */ + public double getRequstURIPath(String prefix, double defvalue) { + String val = getRequstURIPath(prefix, null); + try { + return val == null ? defvalue : Double.parseDouble(val); + } catch (NumberFormatException e) { + return defvalue; + } + } + + //------------------------------------------------------------------------------ + /** + * 获取请求Header总对象 + * + * @return AnyValue + */ + public Map getHeaders() { + parseHeader(); + return headers; + } + + /** + * 将请求Header转换成Map + * + * @param map Map + * + * @return Map + */ + @ConvertDisabled + public Map getHeadersToMap(Map map) { + parseHeader(); + if (map == null) { + map = new LinkedHashMap<>(); + } + final Map map0 = map; + headers.forEach((k, v) -> map0.put(k, v)); + return map0; + } + + /** + * 获取所有的header名 + * + * @return header名数组 + */ + @ConvertDisabled + public String[] getHeaderNames() { + parseHeader(); + Set names = headers.keySet(); + return names.toArray(new String[names.size()]); + } + + /** + * 获取指定的header值 + * + * @param name header名 + * + * @return header值 + */ + public String getHeader(String name) { + parseHeader(); + return headers.get(name); + } + + /** + * 获取指定的header值, 没有返回默认值 + * + * @param name header名 + * @param defaultValue 默认值 + * + * @return header值 + */ + public String getHeader(String name, String defaultValue) { + parseHeader(); + return headers.getOrDefault(name, defaultValue); + } + + /** + * 获取指定的header的json值 + * + * @param 泛型 + * @param type 反序列化的类名 + * @param name header名 + * + * @return header值 + */ + public T getJsonHeader(java.lang.reflect.Type type, String name) { + String v = getHeader(name); + return v == null || v.isEmpty() ? null : jsonConvert.convertFrom(type, v); + } + + /** + * 获取指定的header的json值 + * + * @param 泛型 + * @param convert JsonConvert对象 + * @param type 反序列化的类名 + * @param name header名 + * + * @return header值 + */ + public T getJsonHeader(JsonConvert convert, java.lang.reflect.Type type, String name) { + String v = getHeader(name); + return v == null || v.isEmpty() ? null : convert.convertFrom(type, v); + } + + /** + * 获取指定的header的boolean值, 没有返回默认boolean值 + * + * @param name header名 + * @param defaultValue 默认boolean值 + * + * @return header值 + */ + public boolean getBooleanHeader(String name, boolean defaultValue) { + //return headers.getBoolValue(name, defaultValue); + parseHeader(); + String value = headers.get(name); + return value == null || value.length() == 0 ? defaultValue : Boolean.parseBoolean(value); + } + + /** + * 获取指定的header的short值, 没有返回默认short值 + * + * @param name header名 + * @param defaultValue 默认short值 + * + * @return header值 + */ + public short getShortHeader(String name, short defaultValue) { + //return headers.getShortValue(name, defaultValue); + parseHeader(); + String value = headers.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return Short.decode(value); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 获取指定的header的short值, 没有返回默认short值 + * + * @param radix 进制数 + * @param name header名 + * @param defaultValue 默认short值 + * + * @return header值 + */ + public short getShortHeader(int radix, String name, short defaultValue) { + //return headers.getShortValue(name, defaultValue); + parseHeader(); + String value = headers.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return (radix == 10 ? Short.decode(value) : Short.parseShort(value, radix)); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 获取指定的header的short值, 没有返回默认short值 + * + * @param name header名 + * @param defaultValue 默认short值 + * + * @return header值 + */ + public short getShortHeader(String name, int defaultValue) { + //return headers.getShortValue(name, (short) defaultValue); + parseHeader(); + String value = headers.get(name); + if (value == null || value.length() == 0) { + return (short) defaultValue; + } + try { + return Short.decode(value); + } catch (NumberFormatException e) { + return (short) defaultValue; + } + } + + /** + * 获取指定的header的short值, 没有返回默认short值 + * + * @param radix 进制数 + * @param name header名 + * @param defaultValue 默认short值 + * + * @return header值 + */ + public short getShortHeader(int radix, String name, int defaultValue) { + //return headers.getShortValue(radix, name, (short) defaultValue); + parseHeader(); + String value = headers.get(name); + if (value == null || value.length() == 0) { + return (short) defaultValue; + } + try { + return (radix == 10 ? Short.decode(value) : Short.parseShort(value, radix)); + } catch (NumberFormatException e) { + return (short) defaultValue; + } + } + + /** + * 获取指定的header的int值, 没有返回默认int值 + * + * @param name header名 + * @param defaultValue 默认int值 + * + * @return header值 + */ + public int getIntHeader(String name, int defaultValue) { + //return headers.getIntValue(name, defaultValue); + parseHeader(); + String value = headers.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 获取指定的header的int值, 没有返回默认int值 + * + * @param radix 进制数 + * @param name header名 + * @param defaultValue 默认int值 + * + * @return header值 + */ + public int getIntHeader(int radix, String name, int defaultValue) { + //return headers.getIntValue(radix, name, defaultValue); + parseHeader(); + String value = headers.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return (radix == 10 ? Integer.decode(value) : Integer.parseInt(value, radix)); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 获取指定的header的long值, 没有返回默认long值 + * + * @param name header名 + * @param defaultValue 默认long值 + * + * @return header值 + */ + public long getLongHeader(String name, long defaultValue) { + //return headers.getLongValue(name, defaultValue); + parseHeader(); + String value = headers.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return Long.decode(value); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 获取指定的header的long值, 没有返回默认long值 + * + * @param radix 进制数 + * @param name header名 + * @param defaultValue 默认long值 + * + * @return header值 + */ + public long getLongHeader(int radix, String name, long defaultValue) { + //return headers.getLongValue(radix, name, defaultValue); + parseHeader(); + String value = headers.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return (radix == 10 ? Long.decode(value) : Long.parseLong(value, radix)); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 获取指定的header的float值, 没有返回默认float值 + * + * @param name header名 + * @param defaultValue 默认float值 + * + * @return header值 + */ + public float getFloatHeader(String name, float defaultValue) { + //return headers.getFloatValue(name, defaultValue); + parseHeader(); + String value = headers.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return Float.parseFloat(value); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 获取指定的header的double值, 没有返回默认double值 + * + * @param name header名 + * @param defaultValue 默认double值 + * + * @return header值 + */ + public double getDoubleHeader(String name, double defaultValue) { + //return headers.getDoubleValue(name, defaultValue); + parseHeader(); + String value = headers.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return Double.parseDouble(value); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + //------------------------------------------------------------------------------ + /** + * 获取请求参数总对象 + * + * @return AnyValue + */ + public Map getParameters() { + parseBody(); + return params; + } + + /** + * 将请求参数转换成Map + * + * @param map Map + * + * @return Map + */ + @ConvertDisabled + public Map getParametersToMap(Map map) { + if (map == null) { + map = new LinkedHashMap<>(); + } + final Map map0 = map; + getParameters().forEach((k, v) -> map0.put(k, v)); + return map0; + } + + /** + * 将请求参数转换成String, 字符串格式为: bean1={}&id=13&name=xxx
+ * 不会返回null,没有参数返回空字符串 + * + * + * @return String + */ + @ConvertDisabled + public String getParametersToString() { + return getParametersToString(null); + } + + /** + * 将请求参数转换成String, 字符串格式为: bean1={}&id=13&name=xxx
+ * 不会返回null,没有参数返回空字符串 + * + * @param prefix 拼接前缀, 如果无参数,返回的字符串不会含有拼接前缀 + * + * @return String + */ + public String getParametersToString(String prefix) { + byte[] rbs = queryBytes; + if (rbs == null || rbs.length < 1) { + return ""; + } + Charset charset = this.context.getCharset(); + String str = charset == null ? new String(rbs, StandardCharsets.UTF_8) : new String(rbs, charset); + return (prefix == null) ? str : (prefix + str); + } + + /** + * 获取所有参数名 + * + * @return 参数名数组 + */ + @ConvertDisabled + public String[] getParameterNames() { + parseBody(); + Set names = params.keySet(); + return names.toArray(new String[names.size()]); + } + + /** + * 获取指定的参数值 + * + * @param name 参数名 + * + * @return 参数值 + */ + public String getParameter(String name) { + if (this.frombody) { + if (array.isEmpty()) { + return null; + } + Convert convert = this.reqConvert; + if (convert == null) { + convert = jsonConvert; + } + return (String) convert.convertFrom(String.class, array.content()); + } + parseBody(); + return params.get(name); + } + + /** + * 获取指定的参数值, 没有返回默认值 + * + * @param name 参数名 + * @param defaultValue 默认值 + * + * @return 参数值 + */ + public String getParameter(String name, String defaultValue) { + if (this.frombody) { + if (array.isEmpty()) { + return defaultValue; + } + Convert convert = this.reqConvert; + if (convert == null) { + convert = jsonConvert; + } + return (String) convert.convertFrom(String.class, array.content()); + } + parseBody(); + return params.getOrDefault(name, defaultValue); + } + + /** + * 获取指定的参数json值 + * + * @param 泛型 + * @param type 反序列化的类名 + * @param name 参数名 + * + * @return 参数值 + */ + public T getJsonParameter(java.lang.reflect.Type type, String name) { + if (this.frombody) { + if (array.isEmpty()) { + return null; + } + Convert convert = this.reqConvert; + if (convert == null) { + convert = jsonConvert; + } + if (type == byte[].class) { + return (T) array.getBytes(); + } + return (T) convert.convertFrom(type, array.content()); + } + String v = getParameter(name); + return v == null || v.isEmpty() ? null : jsonConvert.convertFrom(type, v); + } + + /** + * 获取指定的参数json值 + * + * @param 泛型 + * @param convert JsonConvert对象 + * @param type 反序列化的类名 + * @param name 参数名 + * + * @return 参数值 + */ + public T getJsonParameter(JsonConvert convert, java.lang.reflect.Type type, String name) { + String v = getParameter(name); + return v == null || v.isEmpty() ? null : convert.convertFrom(type, v); + } + + /** + * 获取指定的参数boolean值, 没有返回默认boolean值 + * + * @param name 参数名 + * @param defaultValue 默认boolean值 + * + * @return 参数值 + */ + public boolean getBooleanParameter(String name, boolean defaultValue) { + if (this.frombody) { + if (array.isEmpty()) { + return defaultValue; + } + Convert convert = this.reqConvert; + if (convert == null) { + convert = jsonConvert; + } + return (boolean) convert.convertFrom(boolean.class, array.content()); + } + parseBody(); + String value = params.get(name); + return value == null || value.length() == 0 ? defaultValue : Boolean.parseBoolean(value); + } + + /** + * 获取指定的参数short值, 没有返回默认short值 + * + * @param name 参数名 + * @param defaultValue 默认short值 + * + * @return 参数值 + */ + public short getShortParameter(String name, short defaultValue) { + if (this.frombody) { + if (array.isEmpty()) { + return defaultValue; + } + Convert convert = this.reqConvert; + if (convert == null) { + convert = jsonConvert; + } + return (short) convert.convertFrom(short.class, array.content()); + } + parseBody(); + String value = params.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return Short.decode(value); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 获取指定的参数short值, 没有返回默认short值 + * + * @param radix 进制数 + * @param name 参数名 + * @param defaultValue 默认short值 + * + * @return 参数值 + */ + public short getShortParameter(int radix, String name, short defaultValue) { + if (this.frombody) { + if (array.isEmpty()) { + return (short) defaultValue; + } + Convert convert = this.reqConvert; + if (convert == null) { + convert = jsonConvert; + } + return (short) convert.convertFrom(short.class, array.content()); + } + parseBody(); + String value = params.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return (radix == 10 ? Short.decode(value) : Short.parseShort(value, radix)); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 获取指定的参数short值, 没有返回默认short值 + * + * @param name 参数名 + * @param defaultValue 默认short值 + * + * @return 参数值 + */ + public short getShortParameter(String name, int defaultValue) { + if (this.frombody) { + if (array.isEmpty()) { + return (short) defaultValue; + } + Convert convert = this.reqConvert; + if (convert == null) { + convert = jsonConvert; + } + return (short) convert.convertFrom(short.class, array.content()); + } + parseBody(); + String value = params.get(name); + if (value == null || value.length() == 0) { + return (short) defaultValue; + } + try { + return Short.decode(value); + } catch (NumberFormatException e) { + return (short) defaultValue; + } + } + + /** + * 获取指定的参数int值, 没有返回默认int值 + * + * @param name 参数名 + * @param defaultValue 默认int值 + * + * @return 参数值 + */ + public int getIntParameter(String name, int defaultValue) { + if (this.frombody) { + if (array.isEmpty()) { + return defaultValue; + } + Convert convert = this.reqConvert; + if (convert == null) { + convert = jsonConvert; + } + return (int) convert.convertFrom(int.class, array.content()); + } + parseBody(); + String value = params.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return Integer.decode(value); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 获取指定的参数int值, 没有返回默认int值 + * + * @param radix 进制数 + * @param name 参数名 + * @param defaultValue 默认int值 + * + * @return 参数值 + */ + public int getIntParameter(int radix, String name, int defaultValue) { + if (this.frombody) { + if (array.isEmpty()) { + return defaultValue; + } + Convert convert = this.reqConvert; + if (convert == null) { + convert = jsonConvert; + } + return (int) convert.convertFrom(int.class, array.content()); + } + parseBody(); + String value = params.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return (radix == 10 ? Integer.decode(value) : Integer.parseInt(value, radix)); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 获取指定的参数long值, 没有返回默认long值 + * + * @param name 参数名 + * @param defaultValue 默认long值 + * + * @return 参数值 + */ + public long getLongParameter(String name, long defaultValue) { + if (this.frombody) { + if (array.isEmpty()) { + return defaultValue; + } + Convert convert = this.reqConvert; + if (convert == null) { + convert = jsonConvert; + } + return (long) convert.convertFrom(long.class, array.content()); + } + parseBody(); + String value = params.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return Long.decode(value); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 获取指定的参数long值, 没有返回默认long值 + * + * @param radix 进制数 + * @param name 参数名 + * @param defaultValue 默认long值 + * + * @return 参数值 + */ + public long getLongParameter(int radix, String name, long defaultValue) { + if (this.frombody) { + if (array.isEmpty()) { + return defaultValue; + } + Convert convert = this.reqConvert; + if (convert == null) { + convert = jsonConvert; + } + return (long) convert.convertFrom(long.class, array.content()); + } + parseBody(); + String value = params.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return (radix == 10 ? Long.decode(value) : Long.parseLong(value, radix)); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 获取指定的参数float值, 没有返回默认float值 + * + * @param name 参数名 + * @param defaultValue 默认float值 + * + * @return 参数值 + */ + public float getFloatParameter(String name, float defaultValue) { + if (this.frombody) { + if (array.isEmpty()) { + return defaultValue; + } + Convert convert = this.reqConvert; + if (convert == null) { + convert = jsonConvert; + } + return (float) convert.convertFrom(float.class, array.content()); + } + parseBody(); + String value = params.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return Float.parseFloat(value); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 获取指定的参数double值, 没有返回默认double值 + * + * @param name 参数名 + * @param defaultValue 默认double值 + * + * @return 参数值 + */ + public double getDoubleParameter(String name, double defaultValue) { + if (this.frombody) { + if (array.isEmpty()) { + return defaultValue; + } + Convert convert = this.reqConvert; + if (convert == null) { + convert = jsonConvert; + } + return (double) convert.convertFrom(double.class, array.content()); + } + parseBody(); + String value = params.get(name); + if (value == null || value.length() == 0) { + return defaultValue; + } + try { + return Double.parseDouble(value); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 获取翻页对象 同 getFlipper("flipper", false, 0); + * + * @return Flipper翻页对象 + */ + public org.redkale.source.Flipper getFlipper() { + return getFlipper(false, 0); + } + + /** + * 获取翻页对象 同 getFlipper("flipper", autoCreate, 0); + * + * @param autoCreate 无参数时是否创建新Flipper对象 + * + * @return Flipper翻页对象 + */ + public org.redkale.source.Flipper getFlipper(boolean autoCreate) { + return getFlipper(autoCreate, 0); + } + + /** + * 获取翻页对象 同 getFlipper("flipper", false, maxLimit); + * + * @param maxLimit 最大行数, 小于1则值为Flipper.DEFAULT_LIMIT + * + * @return Flipper翻页对象 + */ + public org.redkale.source.Flipper getFlipper(int maxLimit) { + return getFlipper(false, maxLimit); + } + + /** + * 获取翻页对象 同 getFlipper("flipper", autoCreate, maxLimit) + * + * @param autoCreate 无参数时是否创建新Flipper对象 + * @param maxLimit 最大行数, 小于1则值为Flipper.DEFAULT_LIMIT + * + * @return Flipper翻页对象 + */ + public org.redkale.source.Flipper getFlipper(boolean autoCreate, int maxLimit) { + return getFlipper("flipper", autoCreate, maxLimit); + } + + /** + * 获取翻页对象 https://redkale.org/pipes/users/list?flipper={'offset':0,'limit':20, 'sort':'createtime ASC'}
+ * + * + * @param name Flipper对象的参数名,默认为 "flipper" + * @param autoCreate 无参数时是否创建新Flipper对象 + * @param maxLimit 最大行数, 小于1则值为Flipper.DEFAULT_LIMIT + * + * @return Flipper翻页对象 + */ + public org.redkale.source.Flipper getFlipper(String name, boolean autoCreate, int maxLimit) { + org.redkale.source.Flipper flipper = getJsonParameter(org.redkale.source.Flipper.class, name); + if (flipper == null) { +// if (maxLimit < 1) maxLimit = org.redkale.source.Flipper.DEFAULT_LIMIT; +// String limitstr = getParameter("limit"); +// if (limitstr != null && !limitstr.isEmpty()) { +// String offsetstr = getParameter("offset"); +// if (offsetstr != null && !offsetstr.isEmpty()) { +// int limit = Integer.parseInt(limitstr); +// int offset = Integer.parseInt(offsetstr); +// String sort = getParameter("sort"); +// if (limit > maxLimit) limit = maxLimit; +// flipper = new org.redkale.source.Flipper(limit, offset, sort); +// } +// } + } else if (flipper.getLimit() < 1 || (maxLimit > 0 && flipper.getLimit() > maxLimit)) { + flipper.setLimit(maxLimit); + } + if (flipper != null || !autoCreate) { + return flipper; + } + if (maxLimit < 1) { + maxLimit = org.redkale.source.Flipper.DEFAULT_LIMIT; + } + return new org.redkale.source.Flipper(maxLimit); + } +}