优化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 io.netty.channel.ChannelFutureListener;
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.InternalLoggerFactory;
@ -180,8 +182,11 @@ public class WeixinMessageDispatcher {
if (alwaysResponse) {
context.write(BlankResponse.global);
} else {
context.writeAndFlush(HttpUtil.createHttpResponse(NOT_FOUND))
.addListener(ChannelFutureListener.CLOSE);
FullHttpResponse response = new DefaultFullHttpResponse(
request.getProtocolVersion(), NOT_FOUND);
HttpUtil.resolveHeaders(response);
context.writeAndFlush(response).addListener(
ChannelFutureListener.CLOSE);
}
}

View File

@ -1,5 +1,12 @@
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.util.List;
import java.util.Map;
@ -16,14 +23,21 @@ import com.foxinmy.weixin4j.util.AesToken;
* @since JDK 1.6
* @see
*/
public class WeixinRequest implements Serializable {
public class WeixinRequest implements Serializable, HttpMessage {
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
*/
private Map<String, List<String>> parameters;
private DecoderResult decoderResult;
private HttpVersion protocolVersion;
public WeixinRequest(String method, EncryptType encryptType,
String echoStr, String timeStamp, String nonce, String signature,
String msgSignature, String originalContent, String encryptContent,
AesToken aesToken, Map<String, List<String>> parameters) {
public WeixinRequest(HttpHeaders headers, HttpMethod method, String uri,
EncryptType encryptType, String echoStr, String timeStamp,
String nonce, String signature, String msgSignature,
String originalContent, String encryptContent, AesToken aesToken) {
this.headers = headers;
this.method = method;
this.uri = uri;
this.encryptType = encryptType;
this.echoStr = echoStr;
this.timeStamp = timeStamp;
@ -86,13 +104,16 @@ public class WeixinRequest implements Serializable {
this.originalContent = originalContent;
this.encryptContent = encryptContent;
this.aesToken = aesToken;
this.parameters = parameters;
}
public String getMethod() {
public HttpMethod getMethod() {
return method;
}
public String getUri() {
return uri;
}
public String getEchoStr() {
return echoStr;
}
@ -130,16 +151,47 @@ public class WeixinRequest implements Serializable {
}
public Map<String, List<String>> getParameters() {
if (parameters == null) {
this.parameters = new QueryStringDecoder(uri, true).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
public String toString() {
return "WeixinRequest [encryptContent=" + encryptContent
+ ", encryptType=" + encryptType + ", echoStr=" + echoStr
+ ", timeStamp=" + timeStamp + ", nonce=" + nonce
+ ", signature=" + signature + ", originalContent="
+ originalContent + ", method=" + method + ", aesToken="
+ aesToken + ", parameters=" + parameters + "]";
return "WeixinRequest [headers=" + headers + ", method=" + method
+ ", uri=" + uri + ", echoStr=" + echoStr + ", timeStamp="
+ timeStamp + ", nonce=" + nonce + ", signature=" + signature
+ ", msgSignature=" + msgSignature + ", encryptType="
+ encryptType + ", originalContent=" + originalContent
+ ", encryptContent=" + encryptContent + ", aesToken="
+ aesToken + ", decoderResult=" + decoderResult
+ ", protocolVersion=" + protocolVersion + "]";
}
}

View File

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

View File

@ -1,6 +1,5 @@
package com.foxinmy.weixin4j.socket;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import io.netty.util.internal.logging.InternalLogger;
@ -32,7 +31,7 @@ public class SingleResponseEncoder extends
protected void encode(ChannelHandlerContext ctx, SingleResponse response,
List<Object> out) throws WeixinException {
String content = response.toContent();
ctx.writeAndFlush(HttpUtil.createHttpResponse(content, OK,
ctx.writeAndFlush(HttpUtil.createHttpResponse(content,
ServerToolkits.CONTENTTYPE$TEXT_PLAIN));
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.handler.codec.MessageToMessageDecoder;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@ -46,9 +47,9 @@ public class WeixinMessageDecoder extends
String messageContent = req.content().toString(ServerToolkits.UTF_8);
QueryStringDecoder queryDecoder = new QueryStringDecoder(req.getUri(),
true);
String methodName = req.getMethod().name();
HttpMethod method = req.getMethod();
logger.info("decode request:{} use {} method invoking", req.getUri(),
methodName);
method);
Map<String, List<String>> parameters = queryDecoder.parameters();
EncryptType encryptType = parameters.containsKey("encrypt_type") ? EncryptType
.valueOf(parameters.get("encrypt_type").get(0).toUpperCase())
@ -86,8 +87,12 @@ public class WeixinMessageDecoder extends
messageContent = MessageUtil.aesDecrypt(aesToken.getWeixinId(),
aesToken.getAesKey(), encryptContent);
}
out.add(new WeixinRequest(methodName, encryptType, echoStr, timeStamp,
nonce, signature, msgSignature, messageContent, encryptContent,
aesToken, parameters));
WeixinRequest request = new WeixinRequest(req.headers(), method,
req.getUri(), encryptType, echoStr, timeStamp, nonce,
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.ChannelHandlerContext;
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.HttpResponseStatus;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@ -58,7 +61,7 @@ public class WeixinRequestHandler extends
if (aesToken == null
|| (ServerToolkits.isBlank(request.getSignature()) && ServerToolkits
.isBlank(request.getMsgSignature()))) {
ctx.writeAndFlush(HttpUtil.createHttpResponse(BAD_REQUEST))
ctx.writeAndFlush(resolveResponse(BAD_REQUEST, request))
.addListener(ChannelFutureListener.CLOSE);
return;
}
@ -66,7 +69,7 @@ public class WeixinRequestHandler extends
* 公众平台:无论Get,Post都带signature参数,当开启aes模式时带msg_signature参数
* 企业号:无论Get,Post都带msg_signature参数
**/
if (request.getMethod().equals(HttpMethod.GET.name())) {
if (request.getMethod() == HttpMethod.GET) {
if (!ServerToolkits.isBlank(request.getSignature())
&& MessageUtil.signature(aesToken.getToken(),
request.getTimeStamp(), request.getNonce()).equals(
@ -83,15 +86,15 @@ public class WeixinRequestHandler extends
aesToken.getAesKey(), request.getEchoStr())));
return;
}
ctx.writeAndFlush(HttpUtil.createHttpResponse(FORBIDDEN))
.addListener(ChannelFutureListener.CLOSE);
ctx.writeAndFlush(resolveResponse(FORBIDDEN, request)).addListener(
ChannelFutureListener.CLOSE);
return;
} else if (request.getMethod().equals(HttpMethod.POST.name())) {
} else if (request.getMethod() == HttpMethod.POST) {
if (!ServerToolkits.isBlank(request.getSignature())
&& !MessageUtil.signature(aesToken.getToken(),
request.getTimeStamp(), request.getNonce()).equals(
request.getSignature())) {
ctx.writeAndFlush(HttpUtil.createHttpResponse(FORBIDDEN))
ctx.writeAndFlush(resolveResponse(FORBIDDEN, request))
.addListener(ChannelFutureListener.CLOSE);
return;
}
@ -100,18 +103,27 @@ public class WeixinRequestHandler extends
request.getTimeStamp(), request.getNonce(),
request.getEncryptContent()).equals(
request.getMsgSignature())) {
ctx.writeAndFlush(HttpUtil.createHttpResponse(FORBIDDEN))
ctx.writeAndFlush(resolveResponse(FORBIDDEN, request))
.addListener(ChannelFutureListener.CLOSE);
return;
}
} else {
ctx.writeAndFlush(HttpUtil.createHttpResponse(METHOD_NOT_ALLOWED))
ctx.writeAndFlush(resolveResponse(METHOD_NOT_ALLOWED, request))
.addListener(ChannelFutureListener.CLOSE);
return;
}
WeixinMessageTransfer messageTransfer = MessageTransferHandler
.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);
}
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;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import io.netty.util.internal.logging.InternalLogger;
@ -74,7 +73,7 @@ public class WeixinResponseEncoder extends
encrtypt));
content.append("</xml>");
}
ctx.writeAndFlush(HttpUtil.createHttpResponse(content.toString(), OK,
ctx.writeAndFlush(HttpUtil.createHttpResponse(content.toString(),
ServerToolkits.CONTENTTYPE$APPLICATION_XML));
logger.info("{} encode weixin response:{}", encryptType, content);
}

View File

@ -1,6 +1,5 @@
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_TYPE;
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.handler.codec.http.DefaultFullHttpResponse;
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.HttpResponseStatus;
@ -32,20 +29,6 @@ public class HttpUtil {
private static String SERVER = "netty4";
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响应
*
@ -55,28 +38,34 @@ public class HttpUtil {
* 响应状态
* @param contentType
* 响应类型
* @param request
* 请求对象
* @return HttpResponse
*/
public static HttpResponse createHttpResponse(String content,
HttpResponseStatus status, String contentType) {
FullHttpResponse httpResponse = null;
httpResponse = new DefaultFullHttpResponse(HTTP_1_1, status,
Unpooled.copiedBuffer(content, ServerToolkits.UTF_8));
String contentType) {
FullHttpResponse httpResponse = new DefaultFullHttpResponse(HTTP_1_1,
HttpResponseStatus.OK, Unpooled.copiedBuffer(content,
ServerToolkits.UTF_8));
httpResponse.headers().set(
CONTENT_TYPE,
String.format("%s;encoding=%s", contentType,
ServerToolkits.UTF_8.displayName()));
httpResponse.headers().set(CONTENT_LENGTH,
content.getBytes(ServerToolkits.UTF_8).length);
createHeaders(httpResponse);
resolveHeaders(httpResponse);
return httpResponse;
}
private static void createHeaders(FullHttpResponse httpResponse) {
httpResponse.headers().set(CONNECTION, Values.KEEP_ALIVE);
public static void resolveHeaders(FullHttpResponse httpResponse) {
/*if (HttpHeaders.isKeepAlive(httpRequest)) {
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(HttpHeaders.Names.SERVER, SERVER);
httpResponse.headers().set(SERVER, SERVER);
httpResponse.headers()
.set(USER_AGENT,
String.format("%s/%s", WEIXIN4J,

View File

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