All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graylog2.inputs.gelf.http.GELFHttpHandler Maven / Gradle / Ivy

There is a newer version: 1.3.4
Show newest version
/**
 * This file is part of Graylog2.
 *
 * Graylog2 is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Graylog2 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Graylog2.  If not, see .
 */
package org.graylog2.inputs.gelf.http;

import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import org.graylog2.inputs.gelf.gelf.GELFMessage;
import org.graylog2.inputs.gelf.gelf.GELFProcessor;
import org.graylog2.plugin.buffers.Buffer;
import org.graylog2.plugin.inputs.MessageInput;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.*;
import org.jboss.netty.handler.codec.http.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.codahale.metrics.MetricRegistry.name;
import static org.jboss.netty.handler.codec.http.HttpHeaders.isKeepAlive;

public class GELFHttpHandler extends SimpleChannelHandler {

    private static final Logger LOG = LoggerFactory.getLogger(GELFHttpHandler.class);

    private final Meter receivedMessages;
    private final Meter gelfMessages;

    private final MessageInput sourceInput;
    private final Boolean enableCors;

    private final GELFProcessor gelfProcessor;

    public GELFHttpHandler(MetricRegistry metricRegistry,
                           MessageInput sourceInput,
                           GELFProcessor gelfProcessor,
                           Boolean enableCors) {
        this.gelfProcessor = gelfProcessor;
        this.sourceInput = sourceInput;
        this.enableCors = enableCors;

        this.receivedMessages = metricRegistry.meter(name(GELFHttpHandler.class, "receivedMessages"));
        this.gelfMessages = metricRegistry.meter(name(GELFHttpHandler.class, "gelfMessages"));
    }

    @Override
    public void messageReceived(final ChannelHandlerContext ctx, final MessageEvent e) throws Exception {
        receivedMessages.mark();

        final HttpRequest request = (HttpRequest) e.getMessage();
        final boolean keepAlive = isKeepAlive(request);
        final HttpVersion httpRequestVersion = request.getProtocolVersion();
        String origin = request.headers().get(HttpHeaders.Names.ORIGIN);

        // to allow for future changes, let's be at least a little strict in what we accept here.
        if (request.getMethod() != HttpMethod.POST) {
            writeResponse(e.getChannel(), keepAlive, httpRequestVersion, HttpResponseStatus.METHOD_NOT_ALLOWED, origin);
            return;
        }

        final ChannelBuffer buffer = request.getContent();
        final byte[] message = new byte[buffer.readableBytes()];
        buffer.toByteBuffer().get(message, buffer.readerIndex(), buffer.readableBytes());

        final GELFMessage msg;
        if ("/gelf".equals(request.getUri())) {
            gelfMessages.mark();
            msg = new GELFMessage(message);
        } else {
            writeResponse(e.getChannel(), keepAlive, httpRequestVersion, HttpResponseStatus.NOT_FOUND, origin);
            return;
        }

        gelfProcessor.messageReceived(msg, sourceInput);
        writeResponse(e.getChannel(), keepAlive, httpRequestVersion, HttpResponseStatus.ACCEPTED, origin);
    }

    private void writeResponse(Channel channel, boolean keepAlive, HttpVersion httpRequestVersion, HttpResponseStatus status, String origin) {
        final HttpResponse response =
            new DefaultHttpResponse(httpRequestVersion, status);

        response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, 0);
        response.headers().set(HttpHeaders.Names.CONNECTION,
                               keepAlive ? HttpHeaders.Values.KEEP_ALIVE : HttpHeaders.Values.CLOSE);

        if (enableCors) {
            if (origin != null && !origin.isEmpty()) {
                response.headers().set(HttpHeaders.Names.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
                response.headers().set(HttpHeaders.Names.ACCESS_CONTROL_ALLOW_CREDENTIALS, true);
                response.headers().set(HttpHeaders.Names.ACCESS_CONTROL_ALLOW_HEADERS, "Authorization");
            }
        }

        final ChannelFuture channelFuture = channel.write(response);
        if (!keepAlive) {
            channelFuture.addListener(ChannelFutureListener.CLOSE);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        LOG.debug("Could not handle GELF HTTP message.", e.getCause());

        if (ctx.getChannel() != null) {
            ctx.getChannel().close();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy