diff --git a/graylog2-server/pom.xml b/graylog2-server/pom.xml
index 0187a5db86a9..b230e79fa5fb 100644
--- a/graylog2-server/pom.xml
+++ b/graylog2-server/pom.xml
@@ -31,12 +31,6 @@
-
- commons-codec
- commons-codec
- 1.8
- test
-
log4j
log4j
@@ -48,12 +42,6 @@
2.5.1
test
-
- com.twilio.sdk
- twilio-java-sdk
- 3.3.15
- jar-with-dependencies
-
com.lmax
disruptor
@@ -114,6 +102,16 @@
opencsv
2.3
+
+ commons-codec
+ commons-codec
+ 1.8
+
+
+ org.apache.httpcomponents
+ httpclient
+ 4.3.1
+
diff --git a/graylog2-server/src/main/java/org/graylog2/Core.java b/graylog2-server/src/main/java/org/graylog2/Core.java
index 7c99eb13b3a5..a238fbdc332d 100644
--- a/graylog2-server/src/main/java/org/graylog2/Core.java
+++ b/graylog2-server/src/main/java/org/graylog2/Core.java
@@ -21,6 +21,7 @@
package org.graylog2;
import com.codahale.metrics.MetricRegistry;
+import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
@@ -61,6 +62,7 @@
import org.graylog2.plugin.outputs.MessageOutput;
import org.graylog2.plugin.streams.Stream;
import org.graylog2.plugins.PluginLoader;
+import org.graylog2.rest.ObjectMapperProvider;
import org.graylog2.security.ShiroSecurityBinding;
import org.graylog2.security.ShiroSecurityContextFactory;
import org.graylog2.security.realm.LdapRealm;
@@ -76,6 +78,7 @@
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
+import org.jboss.netty.handler.stream.ChunkedWriteHandler;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.slf4j.Logger;
@@ -354,11 +357,14 @@ public void startRestApi() throws IOException {
bossExecutor,
workerExecutor
));
- ResourceConfig rc = new ResourceConfig();
- rc.property(NettyContainer.PROPERTY_BASE_URI, configuration.getRestListenUri());
- rc.registerClasses(MetricsDynamicBinding.class, AnyExceptionClassMapper.class, ShiroSecurityBinding.class);
- rc.register(new Graylog2Binder());
- rc.registerFinder(new PackageNamesScanner(new String[] {"org.graylog2.rest.resources"}, true));
+
+ ResourceConfig rc = new ResourceConfig()
+ .property(NettyContainer.PROPERTY_BASE_URI, configuration.getRestListenUri())
+ .registerClasses(MetricsDynamicBinding.class, AnyExceptionClassMapper.class, ShiroSecurityBinding.class)
+ .register(new Graylog2Binder())
+ .register(ObjectMapperProvider.class)
+ .register(JacksonJsonProvider.class)
+ .registerFinder(new PackageNamesScanner(new String[]{"org.graylog2.rest.resources"}, true));
final NettyContainer jerseyHandler = ContainerFactory.createContainer(NettyContainer.class, rc);
jerseyHandler.setSecurityContextFactory(new ShiroSecurityContextFactory(this));
@@ -368,6 +374,7 @@ public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("encoder", new HttpResponseEncoder());
+ pipeline.addLast("chunks", new ChunkedWriteHandler());
pipeline.addLast("jerseyHandler", jerseyHandler);
return pipeline;
}
diff --git a/graylog2-server/src/main/java/org/graylog2/rest/ObjectMapperProvider.java b/graylog2-server/src/main/java/org/graylog2/rest/ObjectMapperProvider.java
new file mode 100644
index 000000000000..9e3984d840fe
--- /dev/null
+++ b/graylog2-server/src/main/java/org/graylog2/rest/ObjectMapperProvider.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 TORCH GmbH
+ *
+ * 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.rest;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.PropertyNamingStrategy;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
+@Provider
+public class ObjectMapperProvider implements ContextResolver {
+ private final ObjectMapper objectMapper;
+
+ public ObjectMapperProvider() {
+ objectMapper = new ObjectMapper();
+ objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+ objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
+ }
+
+ @Override
+ public ObjectMapper getContext(Class> type) {
+ return objectMapper;
+ }
+}
diff --git a/graylog2-server/src/main/java/org/graylog2/rest/documentation/generator/Generator.java b/graylog2-server/src/main/java/org/graylog2/rest/documentation/generator/Generator.java
index 2feb1beadbd4..791ad0cb4e3c 100644
--- a/graylog2-server/src/main/java/org/graylog2/rest/documentation/generator/Generator.java
+++ b/graylog2-server/src/main/java/org/graylog2/rest/documentation/generator/Generator.java
@@ -164,6 +164,13 @@ public Map generateForRoute(String route, String basePath) {
}
}
+ Produces produces = null;
+ if (clazz.isAnnotationPresent(Produces.class) || method.isAnnotationPresent(Produces.class)) {
+ produces = clazz.getAnnotation(Produces.class);
+ if (method.isAnnotationPresent(Produces.class)) {
+ produces = method.getAnnotation(Produces.class);
+ }
+ }
api.put("path", methodPath);
Map operation = Maps.newHashMap();
@@ -171,6 +178,10 @@ public Map generateForRoute(String route, String basePath) {
operation.put("summary", apiOperation.value());
operation.put("notes", apiOperation.notes());
operation.put("nickname", method.getName());
+ if (produces != null) {
+ operation.put("produces", produces.value());
+ }
+ operation.put("type", method.getReturnType().getSimpleName());
List