优化HttpUtil

This commit is contained in:
jinyu 2016-02-05 09:05:54 +08:00
parent ebf0e4fef6
commit 07550a2287
9 changed files with 125 additions and 63 deletions

View File

@ -3,6 +3,8 @@ package com.foxinmy.weixin4j.dispatcher;
import static io.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND; import static io.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND;
import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
@ -180,8 +182,11 @@ public class WeixinMessageDispatcher {
if (alwaysResponse) { if (alwaysResponse) {
context.write(BlankResponse.global); context.write(BlankResponse.global);
} else { } else {
context.writeAndFlush(HttpUtil.createHttpResponse(NOT_FOUND)) FullHttpResponse response = new DefaultFullHttpResponse(
.addListener(ChannelFutureListener.CLOSE); request.getProtocolVersion(), NOT_FOUND);
HttpUtil.resolveHeaders(response);
context.writeAndFlush(response).addListener(
ChannelFutureListener.CLOSE);
} }
} }

View File

@ -1,5 +1,12 @@
package com.foxinmy.weixin4j.request; package com.foxinmy.weixin4j.request;
import io.netty.handler.codec.DecoderResult;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMessage;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.QueryStringDecoder;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -16,14 +23,21 @@ import com.foxinmy.weixin4j.util.AesToken;
* @since JDK 1.6 * @since JDK 1.6
* @see * @see
*/ */
public class WeixinRequest implements Serializable { public class WeixinRequest implements Serializable, HttpMessage {
private static final long serialVersionUID = -9157395300510879866L; private static final long serialVersionUID = -9157395300510879866L;
/**
* 请求的表头
*/
private HttpHeaders headers;
/** /**
* 请求的方式 * 请求的方式
*/ */
private String method; private HttpMethod method;
/**
* 请求的URI
*/
private String uri;
// 以下字段每次被动消息时都会带上 // 以下字段每次被动消息时都会带上
/** /**
@ -71,12 +85,16 @@ public class WeixinRequest implements Serializable {
* url parameter * url parameter
*/ */
private Map<String, List<String>> parameters; private Map<String, List<String>> parameters;
private DecoderResult decoderResult;
private HttpVersion protocolVersion;
public WeixinRequest(String method, EncryptType encryptType, public WeixinRequest(HttpHeaders headers, HttpMethod method, String uri,
String echoStr, String timeStamp, String nonce, String signature, EncryptType encryptType, String echoStr, String timeStamp,
String msgSignature, String originalContent, String encryptContent, String nonce, String signature, String msgSignature,
AesToken aesToken, Map<String, List<String>> parameters) { String originalContent, String encryptContent, AesToken aesToken) {
this.headers = headers;
this.method = method; this.method = method;
this.uri = uri;
this.encryptType = encryptType; this.encryptType = encryptType;
this.echoStr = echoStr; this.echoStr = echoStr;
this.timeStamp = timeStamp; this.timeStamp = timeStamp;
@ -86,13 +104,16 @@ public class WeixinRequest implements Serializable {
this.originalContent = originalContent; this.originalContent = originalContent;
this.encryptContent = encryptContent; this.encryptContent = encryptContent;
this.aesToken = aesToken; this.aesToken = aesToken;
this.parameters = parameters;
} }
public String getMethod() { public HttpMethod getMethod() {
return method; return method;
} }
public String getUri() {
return uri;
}
public String getEchoStr() { public String getEchoStr() {
return echoStr; return echoStr;
} }
@ -130,16 +151,47 @@ public class WeixinRequest implements Serializable {
} }
public Map<String, List<String>> getParameters() { public Map<String, List<String>> getParameters() {
if (parameters == null) {
this.parameters = new QueryStringDecoder(uri, true).parameters();
}
return parameters; return parameters;
} }
@Override
public DecoderResult getDecoderResult() {
return decoderResult;
}
@Override
public void setDecoderResult(DecoderResult decoderResult) {
this.decoderResult = decoderResult;
}
@Override
public HttpVersion getProtocolVersion() {
return protocolVersion;
}
@Override
public HttpMessage setProtocolVersion(HttpVersion protocolVersion) {
this.protocolVersion = protocolVersion;
return this;
}
@Override
public HttpHeaders headers() {
return headers;
}
@Override @Override
public String toString() { public String toString() {
return "WeixinRequest [encryptContent=" + encryptContent return "WeixinRequest [headers=" + headers + ", method=" + method
+ ", encryptType=" + encryptType + ", echoStr=" + echoStr + ", uri=" + uri + ", echoStr=" + echoStr + ", timeStamp="
+ ", timeStamp=" + timeStamp + ", nonce=" + nonce + timeStamp + ", nonce=" + nonce + ", signature=" + signature
+ ", signature=" + signature + ", originalContent=" + ", msgSignature=" + msgSignature + ", encryptType="
+ originalContent + ", method=" + method + ", aesToken=" + encryptType + ", originalContent=" + originalContent
+ aesToken + ", parameters=" + parameters + "]"; + ", encryptContent=" + encryptContent + ", aesToken="
+ aesToken + ", decoderResult=" + decoderResult
+ ", protocolVersion=" + protocolVersion + "]";
} }
} }

View File

@ -1,5 +1,6 @@
package com.foxinmy.weixin4j.response; package com.foxinmy.weixin4j.response;
/** /**
* 微信被动消息回复 * 微信被动消息回复
* *

View File

@ -1,6 +1,5 @@
package com.foxinmy.weixin4j.socket; package com.foxinmy.weixin4j.socket;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder; import io.netty.handler.codec.MessageToMessageEncoder;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
@ -32,7 +31,7 @@ public class SingleResponseEncoder extends
protected void encode(ChannelHandlerContext ctx, SingleResponse response, protected void encode(ChannelHandlerContext ctx, SingleResponse response,
List<Object> out) throws WeixinException { List<Object> out) throws WeixinException {
String content = response.toContent(); String content = response.toContent();
ctx.writeAndFlush(HttpUtil.createHttpResponse(content, OK, ctx.writeAndFlush(HttpUtil.createHttpResponse(content,
ServerToolkits.CONTENTTYPE$TEXT_PLAIN)); ServerToolkits.CONTENTTYPE$TEXT_PLAIN));
logger.info("encode single response:{}", content); logger.info("encode single response:{}", content);
} }

View File

@ -3,6 +3,7 @@ package com.foxinmy.weixin4j.socket;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder; import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.QueryStringDecoder; import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
@ -46,9 +47,9 @@ public class WeixinMessageDecoder extends
String messageContent = req.content().toString(ServerToolkits.UTF_8); String messageContent = req.content().toString(ServerToolkits.UTF_8);
QueryStringDecoder queryDecoder = new QueryStringDecoder(req.getUri(), QueryStringDecoder queryDecoder = new QueryStringDecoder(req.getUri(),
true); true);
String methodName = req.getMethod().name(); HttpMethod method = req.getMethod();
logger.info("decode request:{} use {} method invoking", req.getUri(), logger.info("decode request:{} use {} method invoking", req.getUri(),
methodName); method);
Map<String, List<String>> parameters = queryDecoder.parameters(); Map<String, List<String>> parameters = queryDecoder.parameters();
EncryptType encryptType = parameters.containsKey("encrypt_type") ? EncryptType EncryptType encryptType = parameters.containsKey("encrypt_type") ? EncryptType
.valueOf(parameters.get("encrypt_type").get(0).toUpperCase()) .valueOf(parameters.get("encrypt_type").get(0).toUpperCase())
@ -86,8 +87,12 @@ public class WeixinMessageDecoder extends
messageContent = MessageUtil.aesDecrypt(aesToken.getWeixinId(), messageContent = MessageUtil.aesDecrypt(aesToken.getWeixinId(),
aesToken.getAesKey(), encryptContent); aesToken.getAesKey(), encryptContent);
} }
out.add(new WeixinRequest(methodName, encryptType, echoStr, timeStamp, WeixinRequest request = new WeixinRequest(req.headers(), method,
nonce, signature, msgSignature, messageContent, encryptContent, req.getUri(), encryptType, echoStr, timeStamp, nonce,
aesToken, parameters)); signature, msgSignature, messageContent, encryptContent,
aesToken);
request.setDecoderResult(req.getDecoderResult());
request.setProtocolVersion(req.getProtocolVersion());
out.add(request);
} }
} }

View File

@ -6,7 +6,10 @@ import static io.netty.handler.codec.http.HttpResponseStatus.METHOD_NOT_ALLOWED;
import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
@ -58,7 +61,7 @@ public class WeixinRequestHandler extends
if (aesToken == null if (aesToken == null
|| (ServerToolkits.isBlank(request.getSignature()) && ServerToolkits || (ServerToolkits.isBlank(request.getSignature()) && ServerToolkits
.isBlank(request.getMsgSignature()))) { .isBlank(request.getMsgSignature()))) {
ctx.writeAndFlush(HttpUtil.createHttpResponse(BAD_REQUEST)) ctx.writeAndFlush(resolveResponse(BAD_REQUEST, request))
.addListener(ChannelFutureListener.CLOSE); .addListener(ChannelFutureListener.CLOSE);
return; return;
} }
@ -66,7 +69,7 @@ public class WeixinRequestHandler extends
* 公众平台:无论Get,Post都带signature参数,当开启aes模式时带msg_signature参数 * 公众平台:无论Get,Post都带signature参数,当开启aes模式时带msg_signature参数
* 企业号:无论Get,Post都带msg_signature参数 * 企业号:无论Get,Post都带msg_signature参数
**/ **/
if (request.getMethod().equals(HttpMethod.GET.name())) { if (request.getMethod() == HttpMethod.GET) {
if (!ServerToolkits.isBlank(request.getSignature()) if (!ServerToolkits.isBlank(request.getSignature())
&& MessageUtil.signature(aesToken.getToken(), && MessageUtil.signature(aesToken.getToken(),
request.getTimeStamp(), request.getNonce()).equals( request.getTimeStamp(), request.getNonce()).equals(
@ -83,15 +86,15 @@ public class WeixinRequestHandler extends
aesToken.getAesKey(), request.getEchoStr()))); aesToken.getAesKey(), request.getEchoStr())));
return; return;
} }
ctx.writeAndFlush(HttpUtil.createHttpResponse(FORBIDDEN)) ctx.writeAndFlush(resolveResponse(FORBIDDEN, request)).addListener(
.addListener(ChannelFutureListener.CLOSE); ChannelFutureListener.CLOSE);
return; return;
} else if (request.getMethod().equals(HttpMethod.POST.name())) { } else if (request.getMethod() == HttpMethod.POST) {
if (!ServerToolkits.isBlank(request.getSignature()) if (!ServerToolkits.isBlank(request.getSignature())
&& !MessageUtil.signature(aesToken.getToken(), && !MessageUtil.signature(aesToken.getToken(),
request.getTimeStamp(), request.getNonce()).equals( request.getTimeStamp(), request.getNonce()).equals(
request.getSignature())) { request.getSignature())) {
ctx.writeAndFlush(HttpUtil.createHttpResponse(FORBIDDEN)) ctx.writeAndFlush(resolveResponse(FORBIDDEN, request))
.addListener(ChannelFutureListener.CLOSE); .addListener(ChannelFutureListener.CLOSE);
return; return;
} }
@ -100,18 +103,27 @@ public class WeixinRequestHandler extends
request.getTimeStamp(), request.getNonce(), request.getTimeStamp(), request.getNonce(),
request.getEncryptContent()).equals( request.getEncryptContent()).equals(
request.getMsgSignature())) { request.getMsgSignature())) {
ctx.writeAndFlush(HttpUtil.createHttpResponse(FORBIDDEN)) ctx.writeAndFlush(resolveResponse(FORBIDDEN, request))
.addListener(ChannelFutureListener.CLOSE); .addListener(ChannelFutureListener.CLOSE);
return; return;
} }
} else { } else {
ctx.writeAndFlush(HttpUtil.createHttpResponse(METHOD_NOT_ALLOWED)) ctx.writeAndFlush(resolveResponse(METHOD_NOT_ALLOWED, request))
.addListener(ChannelFutureListener.CLOSE); .addListener(ChannelFutureListener.CLOSE);
return; return;
} }
WeixinMessageTransfer messageTransfer = MessageTransferHandler WeixinMessageTransfer messageTransfer = MessageTransferHandler
.parser(request); .parser(request);
ctx.channel().attr(ServerToolkits.MESSAGE_TRANSFER_KEY).set(messageTransfer); ctx.channel().attr(ServerToolkits.MESSAGE_TRANSFER_KEY)
.set(messageTransfer);
messageDispatcher.doDispatch(ctx, request, messageTransfer); messageDispatcher.doDispatch(ctx, request, messageTransfer);
} }
private FullHttpResponse resolveResponse(HttpResponseStatus responseStatus,
WeixinRequest request) {
FullHttpResponse response = new DefaultFullHttpResponse(
request.getProtocolVersion(), responseStatus);
HttpUtil.resolveHeaders(response);
return response;
}
} }

View File

@ -1,6 +1,5 @@
package com.foxinmy.weixin4j.socket; package com.foxinmy.weixin4j.socket;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder; import io.netty.handler.codec.MessageToMessageEncoder;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
@ -74,7 +73,7 @@ public class WeixinResponseEncoder extends
encrtypt)); encrtypt));
content.append("</xml>"); content.append("</xml>");
} }
ctx.writeAndFlush(HttpUtil.createHttpResponse(content.toString(), OK, ctx.writeAndFlush(HttpUtil.createHttpResponse(content.toString(),
ServerToolkits.CONTENTTYPE$APPLICATION_XML)); ServerToolkits.CONTENTTYPE$APPLICATION_XML));
logger.info("{} encode weixin response:{}", encryptType, content); logger.info("{} encode weixin response:{}", encryptType, content);
} }

View File

@ -1,6 +1,5 @@
package com.foxinmy.weixin4j.util; package com.foxinmy.weixin4j.util;
import static io.netty.handler.codec.http.HttpHeaders.Names.CONNECTION;
import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH; import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH;
import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE; import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
import static io.netty.handler.codec.http.HttpHeaders.Names.DATE; import static io.netty.handler.codec.http.HttpHeaders.Names.DATE;
@ -9,8 +8,6 @@ import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpHeaders.Values;
import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpResponseStatus;
@ -32,20 +29,6 @@ public class HttpUtil {
private static String SERVER = "netty4"; private static String SERVER = "netty4";
private static String WEIXIN4J = "weixin4j-server"; private static String WEIXIN4J = "weixin4j-server";
/**
* 创建只有状态的HttpResponse响应
*
* @param status
* 响应状态
* @return HttpResponse
*/
public static HttpResponse createHttpResponse(HttpResponseStatus status) {
FullHttpResponse httpResponse = new DefaultFullHttpResponse(HTTP_1_1,
status);
createHeaders(httpResponse);
return httpResponse;
}
/** /**
* 创建有内容的HttpResponse响应 * 创建有内容的HttpResponse响应
* *
@ -55,28 +38,34 @@ public class HttpUtil {
* 响应状态 * 响应状态
* @param contentType * @param contentType
* 响应类型 * 响应类型
* @param request
* 请求对象
* @return HttpResponse * @return HttpResponse
*/ */
public static HttpResponse createHttpResponse(String content, public static HttpResponse createHttpResponse(String content,
HttpResponseStatus status, String contentType) { String contentType) {
FullHttpResponse httpResponse = null; FullHttpResponse httpResponse = new DefaultFullHttpResponse(HTTP_1_1,
HttpResponseStatus.OK, Unpooled.copiedBuffer(content,
httpResponse = new DefaultFullHttpResponse(HTTP_1_1, status, ServerToolkits.UTF_8));
Unpooled.copiedBuffer(content, ServerToolkits.UTF_8));
httpResponse.headers().set( httpResponse.headers().set(
CONTENT_TYPE, CONTENT_TYPE,
String.format("%s;encoding=%s", contentType, String.format("%s;encoding=%s", contentType,
ServerToolkits.UTF_8.displayName())); ServerToolkits.UTF_8.displayName()));
httpResponse.headers().set(CONTENT_LENGTH, httpResponse.headers().set(CONTENT_LENGTH,
content.getBytes(ServerToolkits.UTF_8).length); content.getBytes(ServerToolkits.UTF_8).length);
createHeaders(httpResponse); resolveHeaders(httpResponse);
return httpResponse; return httpResponse;
} }
private static void createHeaders(FullHttpResponse httpResponse) { public static void resolveHeaders(FullHttpResponse httpResponse) {
/*if (HttpHeaders.isKeepAlive(httpRequest)) {
httpResponse.headers().set(CONNECTION, Values.KEEP_ALIVE); httpResponse.headers().set(CONNECTION, Values.KEEP_ALIVE);
}
if (HttpHeaders.isTransferEncodingChunked(httpRequest)) {
httpResponse.headers().set(TRANSFER_ENCODING, Values.CHUNKED);
}*/
httpResponse.headers().set(DATE, new Date()); httpResponse.headers().set(DATE, new Date());
httpResponse.headers().set(HttpHeaders.Names.SERVER, SERVER); httpResponse.headers().set(SERVER, SERVER);
httpResponse.headers() httpResponse.headers()
.set(USER_AGENT, .set(USER_AGENT,
String.format("%s/%s", WEIXIN4J, String.format("%s/%s", WEIXIN4J,

View File

@ -27,7 +27,7 @@ import com.foxinmy.weixin4j.util.ServerToolkits;
*/ */
public class MessagePush { public class MessagePush {
private final String server = "http://localhost:10003"; private final String server = "http://localhost:30000";
private final HttpClient httpClient; private final HttpClient httpClient;
private final HttpPost httpPost; private final HttpPost httpPost;
private final HttpGet httpGet; private final HttpGet httpGet;