Package org.jboss.aerogear.io.netty.handler.codec.sockjs.transport

Source Code of org.jboss.aerogear.io.netty.handler.codec.sockjs.transport.AbstractSendTransport

/*
* Copyright 2013 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License, version
* 2.0 (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.jboss.aerogear.io.netty.handler.codec.sockjs.transport;

import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
import static org.jboss.aerogear.io.netty.handler.codec.sockjs.transport.Transports.CONTENT_TYPE_PLAIN;
import static org.jboss.aerogear.io.netty.handler.codec.sockjs.transport.Transports.internalServerErrorResponse;
import static org.jboss.aerogear.io.netty.handler.codec.sockjs.transport.Transports.responseWithContent;

import com.fasterxml.jackson.core.JsonParseException;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.QueryStringDecoder;
import org.jboss.aerogear.io.netty.handler.codec.sockjs.SockJsConfig;
import org.jboss.aerogear.io.netty.handler.codec.sockjs.util.ArgumentUtil;
import org.jboss.aerogear.io.netty.handler.codec.sockjs.util.JsonUtil;
import io.netty.util.CharsetUtil;

import java.util.List;

/**
* A common base class for SockJS transports that send messages to a SockJS service.
*/
public abstract class AbstractSendTransport extends SimpleChannelInboundHandler<FullHttpRequest> {

    protected final SockJsConfig config;

    protected AbstractSendTransport(final SockJsConfig config) {
        ArgumentUtil.checkNotNull(config, "config");
        this.config = config;
    }

    @Override
    public void messageReceived(final ChannelHandlerContext ctx, final FullHttpRequest request) throws Exception {
        final String content = getContent(request);
        if (content.isEmpty()) {
            ctx.writeAndFlush(internalServerErrorResponse(request.getProtocolVersion(), "Payload expected."))
            .addListener(ChannelFutureListener.CLOSE);
        } else {
            try {
                final String[] messages = JsonUtil.decode(content);
                for (String message : messages) {
                    ctx.fireChannelRead(message);
                }
                respond(ctx, request);
            } catch (final JsonParseException e) {
                ctx.writeAndFlush(internalServerErrorResponse(request.getProtocolVersion(), "Broken JSON encoding."));
            }
        }
    }

    /**
     * Allows concrete subclasses to very how they will respond after a message has been sent
     * to the target SockJS service.
     * Different transport protocols require different responses, for example jsonp_send requires an
     * OK response while xhr_send NO_CONTENT.
     *
     * @param ctx the current {@link ChannelHandlerContext}.
     * @param request the http request.
     * @throws Exception if a failure occurs while trying to respond.
     */
    public abstract void respond(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception;

    private static String getContent(final FullHttpRequest request) {
        final String contentType = getContentType(request);
        if (Transports.CONTENT_TYPE_FORM.equals(contentType)) {
            final List<String> data = getDataFormParameter(request);
            if (data != null) {
                return data.get(0);
            } else {
                return "";
            }
        }
        return request.content().toString(CharsetUtil.UTF_8);
    }

    private static String getContentType(final FullHttpRequest request) {
        final String contentType = request.headers().get(CONTENT_TYPE);
        if (contentType == null) {
            return CONTENT_TYPE_PLAIN;
        }
        return contentType;
    }

    private static List<String> getDataFormParameter(final FullHttpRequest request) {
        final QueryStringDecoder decoder = new QueryStringDecoder('?' + request.content().toString(CharsetUtil.UTF_8));
        return decoder.parameters().get("d");
    }

    protected void respond(final ChannelHandlerContext ctx,
            final HttpVersion httpVersion,
            final HttpResponseStatus status,
            final String message) {
        final FullHttpResponse response = responseWithContent(httpVersion, status, CONTENT_TYPE_PLAIN, message);
        Transports.setDefaultHeaders(response, config);
        if (ctx.channel().isActive() && ctx.channel().isRegistered()) {
            ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
        }
    }

}
TOP

Related Classes of org.jboss.aerogear.io.netty.handler.codec.sockjs.transport.AbstractSendTransport

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.