Files
IM-server-new/broker/src/main/java/com/xiaoleilu/loServer/handler/Request.java
T

517 lines
13 KiB
Java
Raw Normal View History

2019-03-16 17:04:23 +08:00
package com.xiaoleilu.loServer.handler;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
2024-02-27 11:27:56 +08:00
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
2019-03-16 17:04:23 +08:00
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.cookie.Cookie;
import io.netty.handler.codec.http.cookie.ServerCookieDecoder;
import io.netty.handler.codec.http.multipart.Attribute;
import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
import io.netty.handler.codec.http.multipart.FileUpload;
import io.netty.handler.codec.http.multipart.HttpDataFactory;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
import io.netty.handler.codec.http.multipart.InterfaceHttpData.HttpDataType;
import org.slf4j.LoggerFactory;
/**
* Http请求对象
*
* @author Looly
*
*/
public class Request {
private static final org.slf4j.Logger Logger = LoggerFactory.getLogger(Request.class);
public static final String METHOD_DELETE = HttpMethod.DELETE.name();
public static final String METHOD_HEAD = HttpMethod.HEAD.name();
public static final String METHOD_GET = HttpMethod.GET.name();
public static final String METHOD_OPTIONS = HttpMethod.OPTIONS.name();
public static final String METHOD_POST = HttpMethod.POST.name();
public static final String METHOD_PUT = HttpMethod.PUT.name();
public static final String METHOD_TRACE = HttpMethod.TRACE.name();
private static final HttpDataFactory HTTP_DATA_FACTORY = new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE);
private FullHttpRequest nettyRequest;
private String path;
private String ip;
private Map<String, String> headers = new HashMap<String, String>();
private Map<String, Object> params = new HashMap<String, Object>();
private Map<String, Cookie> cookies = new HashMap<String, Cookie>();
/**
* 构造
*
* @param ctx ChannelHandlerContext
* @param nettyRequest HttpRequest
*/
private Request(ChannelHandlerContext ctx, FullHttpRequest nettyRequest) {
this.nettyRequest = nettyRequest;
final String uri = nettyRequest.uri();
this.path = URLUtil.getPath(getUri());
this.putHeadersAndCookies(nettyRequest.headers());
// request URI parameters
this.putParams(new QueryStringDecoder(uri));
// IP
this.putIp(ctx);
}
/**
* @return Netty的HttpRequest
*/
public HttpRequest getNettyRequest() {
return this.nettyRequest;
}
/**
* 获得版本信息
*
* @return 版本
*/
public String getProtocolVersion() {
return nettyRequest.protocolVersion().text();
}
/**
* 获得URI(带参数的路径)
*
* @return URI
*/
public String getUri() {
return nettyRequest.uri();
}
/**
* @return 获得path(不带参数的路径)
*/
public String getPath() {
return path;
}
/**
* 获得Http方法
*
* @return Http method
*/
public String getMethod() {
return nettyRequest.method().name();
}
/**
* 获得IP地址
*
* @return IP地址
*/
public String getIp() {
return ip;
}
/**
* 获得所有头信息
*
* @return 头信息Map
*/
public Map<String, String> getHeaders() {
return headers;
}
/**
* 使用ISO8859_1字符集获得Header内容<br>
* 由于Header中很少有中文,故一般情况下无需转码
*
* @param headerKey 头信息的KEY
* @return 值
*/
public String getHeader(String headerKey) {
return headers.get(headerKey);
}
/**
* @return 是否为普通表单(application/x-www-form-urlencoded)
*/
public boolean isXWwwFormUrlencoded() {
return "application/x-www-form-urlencoded".equals(getHeader("Content-Type"));
}
/**
* 获得指定的Cookie
*
* @param name cookie名
* @return Cookie对象
*/
public Cookie getCookie(String name) {
return cookies.get(name);
}
/**
* @return 获得所有Cookie信息
*/
public Map<String, Cookie> getCookies() {
return this.cookies;
}
/**
* @return 客户浏览器是否为IE
*/
public boolean isIE() {
String userAgent = getHeader("User-Agent");
if (StrUtil.isNotBlank(userAgent)) {
userAgent = userAgent.toUpperCase();
if (userAgent.contains("MSIE") || userAgent.contains("TRIDENT")) {
return true;
}
}
return false;
}
/**
* @param name 参数名
* @return 获得请求参数
*/
public String getParam(String name) {
final Object value = params.get(name);
if(null == value){
return null;
}
if(value instanceof String){
return (String)value;
}
return value.toString();
}
/**
* @param name 参数名
* @return 获得请求参数
*/
public Object getObjParam(String name) {
return params.get(name);
}
/**
* 获得GET请求参数<br>
* 会根据浏览器类型自动识别GET请求的编码方式从而解码<br>
* charsetOfServlet为null则默认的ISO_8859_1
*
* @param name 参数名
* @param charset 字符集
* @return 获得请求参数
*/
public String getParam(String name, Charset charset) {
if (null == charset) {
charset = Charset.forName(CharsetUtil.ISO_8859_1);
}
String destCharset = CharsetUtil.UTF_8;
if (isIE()) {
// IE浏览器GET请求使用GBK编码
destCharset = CharsetUtil.GBK;
}
String value = getParam(name);
if (METHOD_GET.equalsIgnoreCase(getMethod())) {
value = CharsetUtil.convert(value, charset.toString(), destCharset);
}
return value;
}
/**
* @param name 参数名
* @param defaultValue 当客户端未传参的默认值
* @return 获得请求参数
*/
public String getParam(String name, String defaultValue) {
String param = getParam(name);
return StrUtil.isBlank(param) ? defaultValue : param;
}
/**
* @param name 参数名
* @param defaultValue 当客户端未传参的默认值
* @return 获得Integer类型请求参数
*/
public Integer getIntParam(String name, Integer defaultValue) {
2024-02-27 11:27:56 +08:00
return Convert.toInt(getParam(name), defaultValue);
2019-03-16 17:04:23 +08:00
}
/**
* @param name 参数名
* @param defaultValue 当客户端未传参的默认值
* @return 获得long类型请求参数
*/
public Long getLongParam(String name, Long defaultValue) {
2024-02-27 11:27:56 +08:00
return Convert.toLong(getParam(name), defaultValue);
2019-03-16 17:04:23 +08:00
}
/**
* @param name 参数名
* @param defaultValue 当客户端未传参的默认值
* @return 获得Double类型请求参数
*/
public Double getDoubleParam(String name, Double defaultValue) {
2024-02-27 11:27:56 +08:00
return Convert.toDouble(getParam(name), defaultValue);
2019-03-16 17:04:23 +08:00
}
/**
* @param name 参数名
* @param defaultValue 当客户端未传参的默认值
* @return 获得Float类型请求参数
*/
public Float getFloatParam(String name, Float defaultValue) {
2024-02-27 11:27:56 +08:00
return Convert.toFloat(getParam(name), defaultValue);
2019-03-16 17:04:23 +08:00
}
/**
* @param name 参数名
* @param defaultValue 当客户端未传参的默认值
* @return 获得Boolean类型请求参数
*/
public Boolean getBoolParam(String name, Boolean defaultValue) {
2024-02-27 11:27:56 +08:00
return Convert.toBool(getParam(name), defaultValue);
2019-03-16 17:04:23 +08:00
}
/**
* 格式:<br>
* 1、yyyy-MM-dd HH:mm:ss <br>
* 2、yyyy-MM-dd <br>
* 3、HH:mm:ss <br>
*
* @param name 参数名
* @param defaultValue 当客户端未传参的默认值
* @return 获得Date类型请求参数,默认格式:
*/
public Date getDateParam(String name, Date defaultValue) {
String param = getParam(name);
return StrUtil.isBlank(param) ? defaultValue : DateUtil.parse(param);
}
/**
* @param name 参数名
* @param format 格式
* @param defaultValue 当客户端未传参的默认值
* @return 获得Date类型请求参数
*/
public Date getDateParam(String name, String format, Date defaultValue) {
String param = getParam(name);
return StrUtil.isBlank(param) ? defaultValue : DateUtil.parse(param, format);
}
/**
* 获得请求参数<br>
* 列表类型值,常用于表单中的多选框
*
* @param name 参数名
* @return 数组
*/
@SuppressWarnings("unchecked")
public List<String> getArrayParam(String name) {
Object value = params.get(name);
if(null == value){
return null;
}
if(value instanceof List){
return (List<String>) value;
}else if(value instanceof String){
return StrUtil.split((String)value, ',');
}else{
throw new RuntimeException("Value is not a List type!");
}
}
/**
* 获得所有请求参数
*
* @return Map
*/
public Map<String, Object> getParams() {
return params;
}
/**
* @return 是否为长连接
*/
public boolean isKeepAlive() {
final String connectionHeader = getHeader(HttpHeaderNames.CONNECTION.toString());
// 无论任何版本Connection为close时都关闭连接
if (HttpHeaderValues.CLOSE.toString().equalsIgnoreCase(connectionHeader)) {
return false;
}
// HTTP/1.0只有Connection为Keep-Alive时才会保持连接
if (HttpVersion.HTTP_1_0.text().equals(getProtocolVersion())) {
if (false == HttpHeaderValues.KEEP_ALIVE.toString().equalsIgnoreCase(connectionHeader)) {
return false;
}
}
// HTTP/1.1默认打开Keep-Alive
return true;
}
// --------------------------------------------------------- Protected method start
/**
* 填充参数(GET请求的参数)
*
* @param decoder QueryStringDecoder
*/
protected void putParams(QueryStringDecoder decoder) {
if (null != decoder) {
List<String> valueList;
for (Entry<String, List<String>> entry : decoder.parameters().entrySet()) {
valueList = entry.getValue();
if(null != valueList){
this.putParam(entry.getKey(), 1 == valueList.size() ? valueList.get(0) : valueList);
}
}
}
}
/**
* 填充参数(POST请求的参数)
*
* @param decoder QueryStringDecoder
*/
protected void putParams(HttpPostRequestDecoder decoder) {
if (null == decoder) {
return;
}
for (InterfaceHttpData data : decoder.getBodyHttpDatas()) {
putParam(data);
}
}
/**
* 填充参数
*
* @param data InterfaceHttpData
*/
protected void putParam(InterfaceHttpData data) {
final HttpDataType dataType = data.getHttpDataType();
if (dataType == HttpDataType.Attribute) {
//普通参数
Attribute attribute = (Attribute) data;
try {
this.putParam(attribute.getName(), attribute.getValue());
} catch (IOException e) {
Logger.error(e.toString());
}
}else if(dataType == HttpDataType.FileUpload){
//文件
FileUpload fileUpload = (FileUpload) data;
if(fileUpload.isCompleted()){
try {
this.putParam(data.getName(), fileUpload.getFile());
} catch (IOException e) {
Logger.error(e.toString(), "Get file param [{}] error!", data.getName());
}
}
}
}
/**
* 填充参数
*
* @param key 参数名
* @param value 参数值
*/
protected void putParam(String key, Object value) {
this.params.put(key, value);
}
/**
* 填充头部信息和Cookie信息
*
* @param headers HttpHeaders
*/
protected void putHeadersAndCookies(HttpHeaders headers) {
for (Entry<String, String> entry : headers) {
this.headers.put(entry.getKey(), entry.getValue());
}
// Cookie
final String cookieString = this.headers.get(HttpHeaderNames.COOKIE);
if (StrUtil.isNotBlank(cookieString)) {
final Set<Cookie> cookies = ServerCookieDecoder.LAX.decode(cookieString);
for (Cookie cookie : cookies) {
this.cookies.put(cookie.name(), cookie);
}
}
}
/**
* 设置客户端IP
*
* @param ctx ChannelHandlerContext
*/
protected void putIp(ChannelHandlerContext ctx) {
String ip = getHeader("X-Forwarded-For");
if (StrUtil.isNotBlank(ip)) {
2024-02-27 11:27:56 +08:00
ip = NetUtil.getMultistageReverseProxyIp(ip);
2019-03-16 17:04:23 +08:00
} else {
final InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
ip = insocket.getAddress().getHostAddress();
}
this.ip = ip;
}
// --------------------------------------------------------- Protected method end
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("\r\nprotocolVersion: ").append(getProtocolVersion()).append("\r\n");
sb.append("uri: ").append(getUri()).append("\r\n");
sb.append("path: ").append(path).append("\r\n");
sb.append("method: ").append(getMethod()).append("\r\n");
sb.append("ip: ").append(ip).append("\r\n");
sb.append("headers:\r\n ");
for (Entry<String, String> entry : headers.entrySet()) {
sb.append(" ").append(entry.getKey()).append(": ").append(entry.getValue()).append("\r\n");
}
sb.append("params: \r\n");
for (Entry<String, Object> entry : params.entrySet()) {
sb.append(" ").append(entry.getKey()).append(": ").append(entry.getValue()).append("\r\n");
}
return sb.toString();
}
/**
* 构建Request对象
*
* @param ctx ChannelHandlerContext
* @param nettyRequest Netty的HttpRequest
* @return Request
*/
protected final static Request build(ChannelHandlerContext ctx, FullHttpRequest nettyRequest) {
return new Request(ctx, nettyRequest);
}
}