diff --git a/src/main/java/com/corundumstudio/socketio/handler/AuthorizeHandler.java b/src/main/java/com/corundumstudio/socketio/handler/AuthorizeHandler.java index c8660fa..80bfe3f 100644 --- a/src/main/java/com/corundumstudio/socketio/handler/AuthorizeHandler.java +++ b/src/main/java/com/corundumstudio/socketio/handler/AuthorizeHandler.java @@ -35,6 +35,7 @@ import com.corundumstudio.socketio.HandshakeData; import com.corundumstudio.socketio.SocketIOClient; import com.corundumstudio.socketio.Transport; import com.corundumstudio.socketio.ack.AckManager; +import com.corundumstudio.socketio.messages.HttpErrorMessage; import com.corundumstudio.socketio.namespace.Namespace; import com.corundumstudio.socketio.namespace.NamespacesHub; import com.corundumstudio.socketio.protocol.AuthPacket; @@ -164,7 +165,7 @@ public class AuthorizeHandler extends ChannelInboundHandlerAdapter implements Di List transportValue = params.get("transport"); if (transportValue == null) { - log.warn("Got no transports for request {}", req.uri()); + log.error("Got no transports for request {}", req.uri()); HttpResponse res = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.UNAUTHORIZED); channel.writeAndFlush(res).addListener(ChannelFutureListener.CLOSE); @@ -172,11 +173,20 @@ public class AuthorizeHandler extends ChannelInboundHandlerAdapter implements Di } Transport transport = Transport.byName(transportValue.get(0)); + if (!configuration.getTransports().contains(transport)) { + Map errorData = new HashMap(); + errorData.put("code", 0); + errorData.put("message", "Transport unknown"); + + channel.attr(EncoderHandler.ORIGIN).set(origin); + channel.writeAndFlush(new HttpErrorMessage(errorData)); + return false; + } + ClientHead client = new ClientHead(sessionId, ackManager, disconnectable, storeFactory, data, clientsBox, transport, disconnectScheduler, configuration); channel.attr(ClientHead.CLIENT).set(client); clientsBox.addClient(client); - String[] transports = {}; if (configuration.getTransports().contains(Transport.WEBSOCKET)) { transports = new String[] {"websocket"}; diff --git a/src/main/java/com/corundumstudio/socketio/handler/EncoderHandler.java b/src/main/java/com/corundumstudio/socketio/handler/EncoderHandler.java index 0e1cbce..bd063d8 100644 --- a/src/main/java/com/corundumstudio/socketio/handler/EncoderHandler.java +++ b/src/main/java/com/corundumstudio/socketio/handler/EncoderHandler.java @@ -29,6 +29,7 @@ import org.slf4j.LoggerFactory; import com.corundumstudio.socketio.Configuration; import com.corundumstudio.socketio.Transport; +import com.corundumstudio.socketio.messages.HttpErrorMessage; import com.corundumstudio.socketio.messages.HttpMessage; import com.corundumstudio.socketio.messages.OutPacketMessage; import com.corundumstudio.socketio.messages.XHROptionsMessage; @@ -37,6 +38,7 @@ import com.corundumstudio.socketio.protocol.Packet; import com.corundumstudio.socketio.protocol.PacketEncoder; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.ByteBufUtil; import io.netty.channel.Channel; import io.netty.channel.ChannelFutureListener; @@ -113,7 +115,8 @@ public class EncoderHandler extends ChannelOutboundHandlerAdapter { .add(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE) .add(HttpHeaderNames.ACCESS_CONTROL_ALLOW_HEADERS, HttpHeaderNames.CONTENT_TYPE); - addOriginHeaders(ctx.channel(), res); + String origin = ctx.channel().attr(ORIGIN).get(); + addOriginHeaders(origin, res); ByteBuf out = encoder.allocateBuffer(ctx.alloc()); sendMessage(msg, ctx.channel(), out, res, promise); @@ -122,17 +125,20 @@ public class EncoderHandler extends ChannelOutboundHandlerAdapter { private void write(XHRPostMessage msg, ChannelHandlerContext ctx, ChannelPromise promise) { ByteBuf out = encoder.allocateBuffer(ctx.alloc()); out.writeBytes(OK); - sendMessage(msg, ctx.channel(), out, "text/html", promise); + sendMessage(msg, ctx.channel(), out, "text/html", promise, HttpResponseStatus.OK); } - private void sendMessage(HttpMessage msg, Channel channel, ByteBuf out, String type, ChannelPromise promise) { - HttpResponse res = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.OK); + private void sendMessage(HttpMessage msg, Channel channel, ByteBuf out, String type, ChannelPromise promise, HttpResponseStatus status) { + HttpResponse res = new DefaultHttpResponse(HTTP_1_1, status); res.headers().add(HttpHeaderNames.CONTENT_TYPE, type) - .add(HttpHeaderNames.SET_COOKIE, "io=" + msg.getSessionId()) .add(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); + if (msg.getSessionId() != null) { + res.headers().add(HttpHeaderNames.SET_COOKIE, "io=" + msg.getSessionId()); + } - addOriginHeaders(channel, res); + String origin = channel.attr(ORIGIN).get(); + addOriginHeaders(origin, res); HttpUtil.setContentLength(res, out.readableBytes()); @@ -150,7 +156,11 @@ public class EncoderHandler extends ChannelOutboundHandlerAdapter { channel.write(res); if (log.isTraceEnabled()) { - log.trace("Out message: {} - sessionId: {}", out.toString(CharsetUtil.UTF_8), msg.getSessionId()); + if (msg.getSessionId() != null) { + log.trace("Out message: {} - sessionId: {}", out.toString(CharsetUtil.UTF_8), msg.getSessionId()); + } else { + log.trace("Out message: {}", out.toString(CharsetUtil.UTF_8)); + } } if (out.isReadable()) { @@ -161,8 +171,16 @@ public class EncoderHandler extends ChannelOutboundHandlerAdapter { channel.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT, promise).addListener(ChannelFutureListener.CLOSE); } + + private void sendError(HttpErrorMessage errorMsg, ChannelHandlerContext ctx, ChannelPromise promise) throws IOException { + final ByteBuf encBuf = encoder.allocateBuffer(ctx.alloc()); + ByteBufOutputStream out = new ByteBufOutputStream(encBuf); + encoder.getJsonSupport().writeValue(out, errorMsg.getData()); + + sendMessage(errorMsg, ctx.channel(), encBuf, "application/json", promise, HttpResponseStatus.BAD_REQUEST); + } - private void addOriginHeaders(Channel channel, HttpResponse res) { + private void addOriginHeaders(String origin, HttpResponse res) { if (version != null) { res.headers().add(HttpHeaderNames.SERVER, version); } @@ -171,7 +189,6 @@ public class EncoderHandler extends ChannelOutboundHandlerAdapter { res.headers().add(HttpHeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN, configuration.getOrigin()); res.headers().add(HttpHeaderNames.ACCESS_CONTROL_ALLOW_CREDENTIALS, Boolean.TRUE); } else { - String origin = channel.attr(ORIGIN).get(); if (origin != null) { res.headers().add(HttpHeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN, origin); res.headers().add(HttpHeaderNames.ACCESS_CONTROL_ALLOW_CREDENTIALS, Boolean.TRUE); @@ -200,6 +217,8 @@ public class EncoderHandler extends ChannelOutboundHandlerAdapter { write((XHROptionsMessage) msg, ctx, promise); } else if (msg instanceof XHRPostMessage) { write((XHRPostMessage) msg, ctx, promise); + } else if (msg instanceof HttpErrorMessage) { + sendError((HttpErrorMessage) msg, ctx, promise); } } @@ -263,10 +282,10 @@ public class EncoderHandler extends ChannelOutboundHandlerAdapter { if (jsonpIndex == null) { type = "text/plain"; } - sendMessage(msg, channel, out, type, promise); + sendMessage(msg, channel, out, type, promise, HttpResponseStatus.OK); } else { encoder.encodePackets(queue, out, ctx.alloc(), 50); - sendMessage(msg, channel, out, "application/octet-stream", promise); + sendMessage(msg, channel, out, "application/octet-stream", promise, HttpResponseStatus.OK); } } diff --git a/src/main/java/com/corundumstudio/socketio/messages/HttpErrorMessage.java b/src/main/java/com/corundumstudio/socketio/messages/HttpErrorMessage.java new file mode 100644 index 0000000..fb1f3dd --- /dev/null +++ b/src/main/java/com/corundumstudio/socketio/messages/HttpErrorMessage.java @@ -0,0 +1,18 @@ +package com.corundumstudio.socketio.messages; + +import java.util.Map; + +public class HttpErrorMessage extends HttpMessage { + + private final Map data; + + public HttpErrorMessage(Map data) { + super(null, null); + this.data = data; + } + + public Map getData() { + return data; + } + +} diff --git a/src/main/java/com/corundumstudio/socketio/protocol/PacketEncoder.java b/src/main/java/com/corundumstudio/socketio/protocol/PacketEncoder.java index e2ea26f..fe6b602 100644 --- a/src/main/java/com/corundumstudio/socketio/protocol/PacketEncoder.java +++ b/src/main/java/com/corundumstudio/socketio/protocol/PacketEncoder.java @@ -46,6 +46,10 @@ public class PacketEncoder { this.configuration = configuration; } + public JsonSupport getJsonSupport() { + return jsonSupport; + } + public ByteBuf allocateBuffer(ByteBufAllocator allocator) { if (configuration.isPreferDirectBuffer()) { return allocator.ioBuffer();