diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/WeixinMessageDispatcher.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/WeixinMessageDispatcher.java index 0d7e0e5e..642ddae2 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/WeixinMessageDispatcher.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/WeixinMessageDispatcher.java @@ -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); } } diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/request/WeixinRequest.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/request/WeixinRequest.java index 93121612..4c2a6f12 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/request/WeixinRequest.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/request/WeixinRequest.java @@ -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> 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> 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> 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 + "]"; } } diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/response/WeixinResponse.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/response/WeixinResponse.java index b76dacf3..1874fdef 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/response/WeixinResponse.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/response/WeixinResponse.java @@ -1,5 +1,6 @@ package com.foxinmy.weixin4j.response; + /** * 微信被动消息回复 * diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/SingleResponseEncoder.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/SingleResponseEncoder.java index 66a44122..71c82962 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/SingleResponseEncoder.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/SingleResponseEncoder.java @@ -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 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); } diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinMessageDecoder.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinMessageDecoder.java index f9da994a..3a776405 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinMessageDecoder.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinMessageDecoder.java @@ -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> 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); } } diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinRequestHandler.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinRequestHandler.java index 68f6ee0d..68d2848c 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinRequestHandler.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinRequestHandler.java @@ -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; + } } diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinResponseEncoder.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinResponseEncoder.java index 20c21427..c38c30a7 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinResponseEncoder.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinResponseEncoder.java @@ -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(""); } - ctx.writeAndFlush(HttpUtil.createHttpResponse(content.toString(), OK, + ctx.writeAndFlush(HttpUtil.createHttpResponse(content.toString(), ServerToolkits.CONTENTTYPE$APPLICATION_XML)); logger.info("{} encode weixin response:{}", encryptType, content); } diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/util/HttpUtil.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/util/HttpUtil.java index 597583cd..52498f58 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/util/HttpUtil.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/util/HttpUtil.java @@ -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,31 +38,37 @@ 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, WeixinServerBootstrap.VERSION)); } -} +} \ No newline at end of file diff --git a/weixin4j-server/src/test/java/com/foxinmy/weixin4j/server/test/MessagePush.java b/weixin4j-server/src/test/java/com/foxinmy/weixin4j/server/test/MessagePush.java index cf1159be..13c398c2 100644 --- a/weixin4j-server/src/test/java/com/foxinmy/weixin4j/server/test/MessagePush.java +++ b/weixin4j-server/src/test/java/com/foxinmy/weixin4j/server/test/MessagePush.java @@ -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;