Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* This file is part of Graylog.
*
* Graylog 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.
*
* Graylog 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 Graylog. If not, see .
*/
package org.graylog2.inputs.transports;
import com.codahale.metrics.InstrumentedExecutorService;
import com.codahale.metrics.MetricRegistry;
import com.github.joschi.jadconfig.util.Size;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import org.graylog2.plugin.LocalMetricRegistry;
import org.graylog2.plugin.configuration.Configuration;
import org.graylog2.plugin.configuration.ConfigurationRequest;
import org.graylog2.plugin.configuration.fields.BooleanField;
import org.graylog2.plugin.configuration.fields.ConfigurationField;
import org.graylog2.plugin.configuration.fields.NumberField;
import org.graylog2.plugin.inputs.MessageInput;
import org.graylog2.plugin.inputs.annotations.ConfigClass;
import org.graylog2.plugin.inputs.annotations.FactoryClass;
import org.graylog2.plugin.inputs.transports.AbstractTcpTransport;
import org.graylog2.plugin.inputs.transports.Transport;
import org.graylog2.plugin.inputs.util.ConnectionCounter;
import org.graylog2.plugin.inputs.util.ThroughputCounter;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
import org.jboss.netty.handler.codec.http.HttpContentDecompressor;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.HttpVersion;
import org.jboss.netty.handler.timeout.ReadTimeoutHandler;
import org.jboss.netty.util.HashedWheelTimer;
import javax.inject.Named;
import java.util.LinkedHashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import static com.codahale.metrics.MetricRegistry.name;
import static org.jboss.netty.channel.Channels.fireMessageReceived;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Values;
import static org.jboss.netty.handler.codec.http.HttpHeaders.isKeepAlive;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.ACCEPTED;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.METHOD_NOT_ALLOWED;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.OK;
public class HttpTransport extends AbstractTcpTransport {
static final int DEFAULT_MAX_INITIAL_LINE_LENGTH = 4096;
static final int DEFAULT_MAX_HEADER_SIZE = 8192;
static final int DEFAULT_MAX_CHUNK_SIZE = (int) Size.kilobytes(64L).toBytes();
static final int DEFAULT_IDLE_WRITER_TIMEOUT = 60;
static final String CK_ENABLE_CORS = "enable_cors";
static final String CK_MAX_CHUNK_SIZE = "max_chunk_size";
static final String CK_IDLE_WRITER_TIMEOUT = "idle_writer_timeout";
private final boolean enableCors;
private final HashedWheelTimer timer;
private final int maxChunkSize;
private final int idleWriterTimeout;
@AssistedInject
public HttpTransport(@Assisted Configuration configuration,
@Named("bossPool") Executor bossPool,
ThroughputCounter throughputCounter,
ConnectionCounter connectionCounter,
HashedWheelTimer timer,
LocalMetricRegistry localRegistry) {
super(configuration,
throughputCounter,
localRegistry,
bossPool,
executorService("worker", "http-transport-worker-%d", localRegistry),
connectionCounter);
enableCors = configuration.getBoolean(CK_ENABLE_CORS);
this.timer = timer;
int maxChunkSize = configuration.intIsSet(CK_MAX_CHUNK_SIZE) ? configuration.getInt(CK_MAX_CHUNK_SIZE) : DEFAULT_MAX_CHUNK_SIZE;
this.maxChunkSize = maxChunkSize <= 0 ? DEFAULT_MAX_CHUNK_SIZE : maxChunkSize;
this.idleWriterTimeout = configuration.intIsSet(CK_IDLE_WRITER_TIMEOUT) ? configuration.getInt(CK_IDLE_WRITER_TIMEOUT, DEFAULT_IDLE_WRITER_TIMEOUT) : DEFAULT_IDLE_WRITER_TIMEOUT;
}
private static Executor executorService(final String executorName, final String threadNameFormat, final MetricRegistry metricRegistry) {
final ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat(threadNameFormat).build();
return new InstrumentedExecutorService(
Executors.newCachedThreadPool(threadFactory),
metricRegistry,
name(HttpTransport.class, executorName, "executor-service"));
}
@Override
protected LinkedHashMap> getBaseChannelHandlers(MessageInput input) {
final LinkedHashMap> baseChannelHandlers =
super.getBaseChannelHandlers(input);
if (idleWriterTimeout > 0) {
// Install read timeout handler to close idle connections after a timeout.
// This avoids dangling HTTP connections when the HTTP client does not close the connection properly.
// For details see: https://github.com/Graylog2/graylog2-server/issues/3223#issuecomment-270350500
baseChannelHandlers.put("read-timeout-handler", () -> new ReadTimeoutHandler(timer, idleWriterTimeout, TimeUnit.SECONDS));
}
baseChannelHandlers.put("decoder", () -> new HttpRequestDecoder(DEFAULT_MAX_INITIAL_LINE_LENGTH, DEFAULT_MAX_HEADER_SIZE, maxChunkSize));
baseChannelHandlers.put("aggregator", () -> new HttpChunkAggregator(maxChunkSize));
baseChannelHandlers.put("encoder", HttpResponseEncoder::new);
baseChannelHandlers.put("decompressor", HttpContentDecompressor::new);
return baseChannelHandlers;
}
@Override
protected LinkedHashMap> getFinalChannelHandlers(MessageInput input) {
final LinkedHashMap> handlers = Maps.newLinkedHashMap();
handlers.put("http-handler", () -> new Handler(enableCors));
handlers.putAll(super.getFinalChannelHandlers(input));
return handlers;
}
@FactoryClass
public interface Factory extends Transport.Factory {
@Override
HttpTransport create(Configuration configuration);
@Override
Config getConfig();
}
@ConfigClass
public static class Config extends AbstractTcpTransport.Config {
@Override
public ConfigurationRequest getRequestedConfiguration() {
final ConfigurationRequest r = super.getRequestedConfiguration();
r.addField(new BooleanField(CK_ENABLE_CORS,
"Enable CORS",
true,
"Input sends CORS headers to satisfy browser security policies"));
r.addField(new NumberField(CK_MAX_CHUNK_SIZE,
"Max. HTTP chunk size",
DEFAULT_MAX_CHUNK_SIZE,
"The maximum HTTP chunk size in bytes (e. g. length of HTTP request body)",
ConfigurationField.Optional.OPTIONAL));
r.addField(new NumberField(CK_IDLE_WRITER_TIMEOUT,
"Idle writer timeout",
DEFAULT_IDLE_WRITER_TIMEOUT,
"The server closes the connection after the given time in seconds after the last client write request. (use 0 to disable)",
ConfigurationField.Optional.OPTIONAL,
NumberField.Attribute.ONLY_POSITIVE));
return r;
}
}
public static class Handler extends SimpleChannelHandler {
private final boolean enableCors;
public Handler(boolean enableCors) {
this.enableCors = enableCors;
}
@Override
public void messageReceived(final ChannelHandlerContext ctx, final MessageEvent e) throws Exception {
final Channel channel = e.getChannel();
final HttpRequest request = (HttpRequest) e.getMessage();
final boolean keepAlive = isKeepAlive(request);
final HttpVersion httpRequestVersion = request.getProtocolVersion();
final String origin = request.headers().get(Names.ORIGIN);
// to allow for future changes, let's be at least a little strict in what we accept here.
if (HttpMethod.OPTIONS.equals(request.getMethod())) {
writeResponse(channel, keepAlive, httpRequestVersion, OK, origin);
return;
} else if (!HttpMethod.POST.equals(request.getMethod())) {
writeResponse(channel, keepAlive, httpRequestVersion, METHOD_NOT_ALLOWED, origin);
return;
}
final ChannelBuffer buffer = request.getContent();
final boolean correctPath = "/gelf".equals(request.getUri());
if (!correctPath) {
writeResponse(channel, keepAlive, httpRequestVersion, NOT_FOUND, origin);
} else {
// send on to raw message handler
writeResponse(channel, keepAlive, httpRequestVersion, ACCEPTED, origin);
fireMessageReceived(ctx, buffer);
}
}
private void writeResponse(Channel channel,
boolean keepAlive,
HttpVersion httpRequestVersion,
HttpResponseStatus status,
String origin) {
final HttpResponse response =
new DefaultHttpResponse(httpRequestVersion, status);
response.headers().set(Names.CONTENT_LENGTH, 0);
response.headers().set(Names.CONNECTION,
keepAlive ? Values.KEEP_ALIVE : Values.CLOSE);
if (enableCors && origin != null && !origin.isEmpty()) {
response.headers().set(Names.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
response.headers().set(Names.ACCESS_CONTROL_ALLOW_CREDENTIALS, true);
response.headers().set(Names.ACCESS_CONTROL_ALLOW_HEADERS, "Authorization, Content-Type");
}
final ChannelFuture channelFuture = channel.write(response);
if (!keepAlive) {
channelFuture.addListener(ChannelFutureListener.CLOSE);
}
}
}
}