Merge branch 'master' into ATEST-246
Conflicts: .settings/org.eclipse.jdt.core.prefs src/test/java/ch/psi/daq/test/queryrest/controller/DaqRestControllerTest.java
This commit is contained in:
@@ -9,9 +9,11 @@ import java.util.function.Function;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
@@ -23,12 +25,6 @@ import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.Version;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
|
||||
import ch.psi.daq.cassandra.util.test.CassandraDataGen;
|
||||
import ch.psi.daq.common.statistic.StorelessStatistics;
|
||||
import ch.psi.daq.domain.DataEvent;
|
||||
@@ -39,11 +35,18 @@ import ch.psi.daq.query.model.Aggregation;
|
||||
import ch.psi.daq.query.model.Query;
|
||||
import ch.psi.daq.query.model.QueryField;
|
||||
import ch.psi.daq.queryrest.controller.validator.QueryValidator;
|
||||
import ch.psi.daq.queryrest.filter.CorsFilter;
|
||||
import ch.psi.daq.queryrest.model.PropertyFilterMixin;
|
||||
import ch.psi.daq.queryrest.response.JsonByteArraySerializer;
|
||||
import ch.psi.daq.queryrest.response.JsonStreamSerializer;
|
||||
import ch.psi.daq.queryrest.response.ResponseStreamWriter;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.Version;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
|
||||
@Configuration
|
||||
@PropertySource(value = {"classpath:queryrest.properties"})
|
||||
@PropertySource(value = {"file:${user.home}/.config/daq/queryrest.properties"}, ignoreResourceNotFound = true)
|
||||
@@ -168,6 +171,12 @@ public class QueryRestConfig extends WebMvcConfigurerAdapter {
|
||||
return new QueryValidator();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty("queryrest.cors.enable")
|
||||
public Filter corsFilter() {
|
||||
return new CorsFilter();
|
||||
}
|
||||
|
||||
// ==========================================================================================
|
||||
// TODO: This is simply for initial / rudimentary testing - remove once further evolved
|
||||
@Bean
|
||||
|
||||
@@ -2,9 +2,11 @@ package ch.psi.daq.queryrest.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@@ -27,9 +29,11 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import ch.psi.daq.cassandra.request.validate.RequestProviderValidator;
|
||||
import ch.psi.daq.cassandra.util.test.CassandraDataGen;
|
||||
import ch.psi.daq.common.json.deserialize.AttributeBasedDeserializer;
|
||||
import ch.psi.daq.common.ordering.Ordering;
|
||||
import ch.psi.daq.domain.DataEvent;
|
||||
import ch.psi.daq.query.analyzer.QueryAnalyzer;
|
||||
import ch.psi.daq.query.model.Aggregation;
|
||||
import ch.psi.daq.query.model.AggregationType;
|
||||
import ch.psi.daq.query.model.DBMode;
|
||||
import ch.psi.daq.query.model.Query;
|
||||
import ch.psi.daq.query.model.QueryField;
|
||||
@@ -39,6 +43,8 @@ import ch.psi.daq.query.request.ChannelsRequest;
|
||||
import ch.psi.daq.queryrest.config.QueryRestConfig;
|
||||
import ch.psi.daq.queryrest.response.ResponseStreamWriter;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
@RestController
|
||||
public class QueryRestController {
|
||||
|
||||
@@ -114,6 +120,68 @@ public class QueryRestController {
|
||||
return getChannels(new ChannelsRequest(channelName));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current list of {@link Ordering}s available.
|
||||
*
|
||||
* @return list of {@link Ordering}s as String array
|
||||
*/
|
||||
@RequestMapping(value = "ordering", method = {RequestMethod.GET},
|
||||
produces = {MediaType.APPLICATION_JSON_VALUE})
|
||||
public @ResponseBody List<String> getOrderingValues() {
|
||||
List<Ordering> orderings = Lists.newArrayList(Ordering.values());
|
||||
return orderings.stream()
|
||||
.map((Ordering ord) -> {
|
||||
return ord.toString();
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current list of {@link QueryField}s available.
|
||||
*
|
||||
* @return list of {@link QueryField}s as String array
|
||||
*/
|
||||
@RequestMapping(value = "queryfields", method = {RequestMethod.GET},
|
||||
produces = {MediaType.APPLICATION_JSON_VALUE})
|
||||
public @ResponseBody List<String> getQueryFieldValues() {
|
||||
List<QueryField> orderings = Lists.newArrayList(QueryField.values());
|
||||
return orderings.stream()
|
||||
.map((QueryField qf) -> {
|
||||
return qf.toString();
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current list of {@link Aggregation}s available.
|
||||
*
|
||||
* @return list of {@link Aggregation}s as String array
|
||||
*/
|
||||
@RequestMapping(value = "aggregations", method = {RequestMethod.GET},
|
||||
produces = {MediaType.APPLICATION_JSON_VALUE})
|
||||
public @ResponseBody List<String> getAggregationsValues() {
|
||||
List<Aggregation> orderings = Lists.newArrayList(Aggregation.values());
|
||||
return orderings.stream()
|
||||
.map((Aggregation value) -> {
|
||||
return value.toString();
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current list of {@link AggregationType}s available.
|
||||
*
|
||||
* @return list of {@link AggregationType}s as String array
|
||||
*/
|
||||
@RequestMapping(value = "aggregationtypes", method = {RequestMethod.GET},
|
||||
produces = {MediaType.APPLICATION_JSON_VALUE})
|
||||
public @ResponseBody List<String> getAggregationTypesValues() {
|
||||
List<AggregationType> orderings = Lists.newArrayList(AggregationType.values());
|
||||
return orderings.stream()
|
||||
.map((AggregationType value) -> {
|
||||
return value.toString();
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Catch-all query method for getting data from the backend.
|
||||
* <p>
|
||||
@@ -143,8 +211,8 @@ public class QueryRestController {
|
||||
QueryAnalyzer queryAnalizer = queryAnalizerFactory.apply(query);
|
||||
|
||||
// all the magic happens here
|
||||
Stream<Entry<String, Stream<? extends DataEvent>>> channelToDataEvents = getQueryProcessor(query.getDbMode())
|
||||
.process(queryAnalizer);
|
||||
Stream<Entry<String, Stream<? extends DataEvent>>> channelToDataEvents =
|
||||
getQueryProcessor(query.getDbMode()).process(queryAnalizer);
|
||||
|
||||
// do post-process
|
||||
Stream<Entry<String, ?>> channelToData = queryAnalizer.postProcess(channelToDataEvents);
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package ch.psi.daq.queryrest.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
public class CorsFilter extends OncePerRequestFilter {
|
||||
|
||||
private static final String ALLOW_ORIGIN_HEADER = "Access-Control-Allow-Origin";
|
||||
|
||||
@Value("${queryrest.cors.allowedorigins}")
|
||||
private String configuredOrigins;
|
||||
|
||||
@Value("${queryrest.cors.forceallheaders}")
|
||||
private boolean forceAllHeaders;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @{inheritDoc
|
||||
*/
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
Set<String> allowedOrigins = new HashSet<String>(Arrays.asList(configuredOrigins.split(","))
|
||||
.stream()
|
||||
.map(s -> {
|
||||
return s.trim(); })
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
String originHeader = request.getHeader("Origin");
|
||||
if (forceAllHeaders) {
|
||||
// include headers no matter what - good for development
|
||||
if (allowedOrigins.contains(originHeader)) {
|
||||
response.addHeader(ALLOW_ORIGIN_HEADER, originHeader);
|
||||
} else {
|
||||
response.addHeader(ALLOW_ORIGIN_HEADER, "*");
|
||||
}
|
||||
setDefaultCorsHeaders(response);
|
||||
|
||||
} else if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
|
||||
// this is for 'real' Cross-site browser requests
|
||||
if (allowedOrigins.contains(originHeader)) {
|
||||
response.addHeader(ALLOW_ORIGIN_HEADER, originHeader);
|
||||
}
|
||||
setDefaultCorsHeaders(response);
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
|
||||
private void setDefaultCorsHeaders(HttpServletResponse response) {
|
||||
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
||||
response.addHeader("Access-Control-Allow-Headers", "Origin, Authorization, Accept, Content-Type");
|
||||
response.addHeader("Access-Control-Max-Age", "1800");
|
||||
}
|
||||
|
||||
|
||||
public void setConfiguredOrigins(String configuredOrigins) {
|
||||
this.configuredOrigins = configuredOrigins;
|
||||
}
|
||||
|
||||
|
||||
public void setForceAllHeaders(boolean forceAllHeaders) {
|
||||
this.forceAllHeaders = forceAllHeaders;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user