Added API versioning backwards compability and tests.
Change-Id: I8a7b512bea67e07e449074a4d04c257b65ae1454
diff --git a/core/Changes b/core/Changes
index 0a2d333..1541f93 100644
--- a/core/Changes
+++ b/core/Changes
@@ -1,6 +1,9 @@
version 0.61.1
28/08/2018
- Added API URL versioning (margaretha)
+30/08/2018
+ - Added backwards compability for URL versioning (margaretha)
+ - Updated API version filter (margaretha)
version 0.61.0
13/08/2018
diff --git a/core/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java b/core/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
index 0a80e90..761911d 100644
--- a/core/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
+++ b/core/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
@@ -5,7 +5,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -14,7 +13,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-//import org.apache.logging.log4j.PropertyConfigurator;
+// import org.apache.logging.log4j.PropertyConfigurator;
import de.ids_mannheim.korap.util.KrillProperties;
import de.ids_mannheim.korap.utils.TimeUtils;
@@ -81,13 +80,13 @@
private String baseURL;
private Properties properties;
- private Set<String> version;
-
+ private Set<String> supportedVersions;
+ private String currentVersion;
+
// deprec?!
private final BACKENDS DEFAULT_ENGINE = BACKENDS.LUCENE;
- public KustvaktConfiguration (Properties properties)
- throws Exception {
+ public KustvaktConfiguration (Properties properties) throws Exception {
load(properties);
KrillProperties.setProp(properties);
}
@@ -100,13 +99,15 @@
* @throws Exception
*/
protected void load (Properties properties) throws Exception {
- String version = properties.getProperty("supported.api.version", "");
- if (version.isEmpty()){
- throw new IllegalArgumentException("supported.api.version must be set in the .conf file");
+ currentVersion = properties.getProperty("current.api.version", "v1.0");
+ String supportedVersions =
+ properties.getProperty("supported.api.version", "");
+ if (supportedVersions.isEmpty()){
+ supportedVersions = currentVersion;
}
- this.version = Arrays.stream(version.split(" ")).collect(Collectors.toSet());
-
-
+ this.supportedVersions = Arrays.stream(supportedVersions.split(" "))
+ .collect(Collectors.toSet());
+
baseURL = properties.getProperty("kustvakt.base.url", "/api/*");
maxhits = new Integer(properties.getProperty("maxhits", "50000"));
returnhits = new Integer(properties.getProperty("returnhits", "50000"));
@@ -176,15 +177,13 @@
// this.load(props);
// }
-
/**
* properties can be overloaded after spring init
*
* @param stream
- * @throws Exception
+ * @throws Exception
*/
- public void setPropertiesAsStream (InputStream stream)
- throws Exception {
+ public void setPropertiesAsStream (InputStream stream) throws Exception {
try {
Properties p = new Properties();
@@ -197,7 +196,6 @@
}
-
public BACKENDS chooseBackend (String value) {
if (value == null || value.equals("null"))
return DEFAULT_ENGINE;
@@ -205,57 +203,56 @@
return Enum.valueOf(BACKENDS.class, value.toUpperCase());
}
-
-
public static void loadLogger () {
-// InputStream stream = ConfigLoader.loadConfigStream("log4j.properties");
-// PropertyConfigurator.configure(stream);
+ // InputStream stream =
+ // ConfigLoader.loadConfigStream("log4j.properties");
+ // PropertyConfigurator.configure(stream);
jlog.info("Done loading logging framework Log4j!");
}
+ // @Deprecated
+ // public static void loadLog4jLogger () {
+ // /** loadSubTypes log4j configuration file programmatically */
+ // Properties log4j = new Properties();
+ // try {
+ // File f = new File(System.getProperty("user.dir"),
+ // "log4j.properties");
+ // if (f.exists()) {
+ // log4j.load(new FileInputStream(f));
+ // PropertyConfigurator.configure(log4j);
+ // jlog.info(
+ // "using local logging properties file ({}) to configure logging
+ // system",
+ // "./log4j.properties");
+ // return;
+ // }
+ // }
+ // catch (Exception e) {
+ // // do nothing
+ // }
+ // loadClassLogger();
+ // }
-
-// @Deprecated
-// public static void loadLog4jLogger () {
-// /** loadSubTypes log4j configuration file programmatically */
-// Properties log4j = new Properties();
-// try {
-// File f = new File(System.getProperty("user.dir"),
-// "log4j.properties");
-// if (f.exists()) {
-// log4j.load(new FileInputStream(f));
-// PropertyConfigurator.configure(log4j);
-// jlog.info(
-// "using local logging properties file ({}) to configure logging system",
-// "./log4j.properties");
-// return;
-// }
-// }
-// catch (Exception e) {
-// // do nothing
-// }
-// loadClassLogger();
-// }
-
-
-// @Deprecated
-// private static void loadClassLogger () {
-// Properties log4j = new Properties();
-// jlog.info(
-// "using class path logging properties file to configure logging system");
-//
-// try {
-// log4j.load(KustvaktConfiguration.class.getClassLoader()
-// .getResourceAsStream("log4j.properties"));
-// }
-// catch (IOException e) {
-// // do nothing
-// }
-//
-// PropertyConfigurator.configure(log4j);
-// jlog.warn(
-// "No logger properties detected. Using default logger properties");
-// }
+ // @Deprecated
+ // private static void loadClassLogger () {
+ // Properties log4j = new Properties();
+ // jlog.info(
+ // "using class path logging properties file to configure logging
+ // system");
+ //
+ // try {
+ // log4j.load(KustvaktConfiguration.class.getClassLoader()
+ // .getResourceAsStream("log4j.properties"));
+ // }
+ // catch (IOException e) {
+ // // do nothing
+ // }
+ //
+ // PropertyConfigurator.configure(log4j);
+ // jlog.warn(
+ // "No logger properties detected. Using default logger
+ // properties");
+ // }
public enum BACKENDS {
NEO4J, LUCENE
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/APIVersionFilter.java b/core/src/main/java/de/ids_mannheim/korap/web/APIVersionFilter.java
index 886e475..0a36153 100644
--- a/core/src/main/java/de/ids_mannheim/korap/web/APIVersionFilter.java
+++ b/core/src/main/java/de/ids_mannheim/korap/web/APIVersionFilter.java
@@ -8,28 +8,27 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
+import com.sun.jersey.api.NotFoundException;
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerRequestFilter;
import com.sun.jersey.spi.container.ContainerResponseFilter;
import com.sun.jersey.spi.container.ResourceFilter;
import de.ids_mannheim.korap.config.KustvaktConfiguration;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.exceptions.StatusCodes;
-/** Checks API version in URL path.
+/**
+ * Checks API version in URL path.
*
* @author margaretha
*
*/
@Component
@Provider
-public class APIVersionFilter implements ContainerRequestFilter, ResourceFilter {
+public class APIVersionFilter
+ implements ContainerRequestFilter, ResourceFilter {
@Autowired
private KustvaktConfiguration config;
- @Autowired
- private CoreResponseHandler kustvaktResponseHandler;
@Override
public ContainerRequestFilter getRequestFilter () {
@@ -46,10 +45,12 @@
List<PathSegment> pathSegments = request.getPathSegments();
String version = pathSegments.get(0).getPath();
- if (!config.getVersion().contains(version)) {
- throw kustvaktResponseHandler.throwit(
- new KustvaktException(StatusCodes.UNSUPPORTED_API_VERSION,
- "API " + version + " is unsupported.", version));
+ if (!config.getSupportedVersions().contains(version)) {
+ throw new NotFoundException(request.getRequestUri());
+ // throw kustvaktResponseHandler.throwit(
+ // new
+ // KustvaktException(StatusCodes.UNSUPPORTED_API_VERSION,
+ // "API " + version + " is unsupported.", version));
}
return request;
}
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/utils/NotFoundMapper.java b/core/src/main/java/de/ids_mannheim/korap/web/utils/NotFoundMapper.java
new file mode 100644
index 0000000..7f5db5c
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/web/utils/NotFoundMapper.java
@@ -0,0 +1,65 @@
+package de.ids_mannheim.korap.web.utils;
+
+import java.net.URI;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.eclipse.jetty.http.HttpStatus;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.sun.jersey.api.NotFoundException;
+
+import de.ids_mannheim.korap.config.KustvaktConfiguration;
+
+@Component
+@Provider
+public class NotFoundMapper implements ExceptionMapper<NotFoundException> {
+
+ private static Logger jlog =
+ LogManager.getLogger(NotFoundMapper.class);
+ public static final Pattern VERSION_PATTERN =
+ Pattern.compile("/(v[0-9][^/]*)(/.*)");
+
+ @Autowired
+ private KustvaktConfiguration config;
+
+ @Override
+ public Response toResponse (NotFoundException exception) {
+ URI notFoundUri = exception.getNotFoundUri();
+
+ String path = notFoundUri.getPath();
+ String baseUrl = config.getBaseURL();
+ baseUrl = baseUrl.substring(0, baseUrl.length() - 2);
+
+ if (path.startsWith(baseUrl)) {
+ path = path.substring(baseUrl.length(), path.length());
+ Matcher matcher = VERSION_PATTERN.matcher(path);
+ if (!matcher.matches()) {
+ path = baseUrl + "/" + config.getCurrentVersion() + path;
+ URI redirectUri = UriBuilder.fromUri(notFoundUri)
+ .replacePath(path).build();
+ jlog.debug("REDIRECT: "+redirectUri.toString());
+ return Response.status(HttpStatus.PERMANENT_REDIRECT_308)
+ .location(redirectUri).build();
+ }
+ else if (!matcher.group(1).equals(config.getCurrentVersion())){
+ path = baseUrl + "/" + config.getCurrentVersion()
+ + matcher.group(2);
+ URI redirectUri = UriBuilder.fromUri(notFoundUri)
+ .replacePath(path).build();
+ jlog.debug("REDIRECT replace: "+ redirectUri.toString());
+ return Response.status(HttpStatus.PERMANENT_REDIRECT_308)
+ .location(redirectUri).build();
+ }
+ }
+ return Response.status(HttpStatus.NOT_FOUND_404).build();
+ }
+}