Introduce new CORS interceptor and switch examples to use it
This commit is contained in:
parent
2d52affd8d
commit
888f42a032
|
@ -73,6 +73,10 @@
|
||||||
<version>3.0</version>
|
<version>3.0</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-web</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<reporting>
|
<reporting>
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
package example;
|
package example;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.annotation.WebServlet;
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
|
||||||
import org.hl7.fhir.instance.hapi.validation.FhirInstanceValidator;
|
import org.hl7.fhir.instance.hapi.validation.FhirInstanceValidator;
|
||||||
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.*;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor;
|
|
||||||
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
|
|
||||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
|
@ -119,4 +118,38 @@ public class ServletExamples {
|
||||||
}
|
}
|
||||||
// END SNIPPET: responseHighlighterInterceptor
|
// END SNIPPET: responseHighlighterInterceptor
|
||||||
|
|
||||||
|
// START SNIPPET: corsInterceptor
|
||||||
|
@WebServlet(urlPatterns = { "/fhir/*" }, displayName = "FHIR Server")
|
||||||
|
public class RestfulServerWithCors extends RestfulServer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initialize() throws ServletException {
|
||||||
|
|
||||||
|
// ... define your resource providers here ...
|
||||||
|
|
||||||
|
// Define your CORS configuration. This is an example
|
||||||
|
// showing a typical setup. You should customize this
|
||||||
|
// to your specific needs
|
||||||
|
CorsConfiguration config = new CorsConfiguration();
|
||||||
|
config.addAllowedHeader("x-fhir-starter");
|
||||||
|
config.addAllowedHeader("Origin");
|
||||||
|
config.addAllowedHeader("Accept");
|
||||||
|
config.addAllowedHeader("X-Requested-With");
|
||||||
|
config.addAllowedHeader("Content-Type");
|
||||||
|
|
||||||
|
config.addAllowedOrigin("*");
|
||||||
|
|
||||||
|
config.addExposedHeader("Location");
|
||||||
|
config.addExposedHeader("Content-Location");
|
||||||
|
config.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE","OPTIONS"));
|
||||||
|
|
||||||
|
// Create the interceptor and register it
|
||||||
|
CorsInterceptor interceptor = new CorsInterceptor(config);
|
||||||
|
registerInterceptor(interceptor);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// END SNIPPET: corsInterceptor
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,15 +43,6 @@
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Only required for CORS support -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.ebaysf.web</groupId>
|
|
||||||
<artifactId>cors-filter</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
<!-- <exclusions> <exclusion> <artifactId>servlet-api</artifactId> <groupId>javax.servlet</groupId>
|
|
||||||
</exclusion> </exclusions> -->
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Only required for Schematron Validator Support -->
|
<!-- Only required for Schematron Validator Support -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.phloc</groupId>
|
<groupId>com.phloc</groupId>
|
||||||
|
@ -123,6 +114,17 @@
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-web</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-logging</artifactId>
|
||||||
|
<groupId>commons-logging</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Server -->
|
<!-- Server -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
package ca.uhn.fhir.rest.server.interceptor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
|
import org.springframework.web.cors.CorsProcessor;
|
||||||
|
import org.springframework.web.cors.CorsUtils;
|
||||||
|
import org.springframework.web.cors.DefaultCorsProcessor;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
|
|
||||||
|
public class CorsInterceptor extends InterceptorAdapter {
|
||||||
|
|
||||||
|
private CorsProcessor myCorsProcessor;
|
||||||
|
private CorsConfiguration myConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public CorsInterceptor() {
|
||||||
|
this(new CorsConfiguration());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param theConfiguration
|
||||||
|
* The CORS configuration
|
||||||
|
*/
|
||||||
|
public CorsInterceptor(CorsConfiguration theConfiguration) {
|
||||||
|
Validate.notNull(theConfiguration, "theConfiguration must not be null");
|
||||||
|
myCorsProcessor = new DefaultCorsProcessor();
|
||||||
|
setConfig(theConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the CORS configuration
|
||||||
|
*/
|
||||||
|
public void setConfig(CorsConfiguration theConfiguration) {
|
||||||
|
myConfig = theConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the CORS configuration
|
||||||
|
*/
|
||||||
|
public CorsConfiguration getConfig() {
|
||||||
|
return myConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean incomingRequestPreProcessed(HttpServletRequest theRequest, HttpServletResponse theResponse) {
|
||||||
|
if (CorsUtils.isCorsRequest(theRequest)) {
|
||||||
|
boolean isValid;
|
||||||
|
try {
|
||||||
|
isValid = myCorsProcessor.processRequest(myConfig, theRequest, theResponse);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new InternalErrorException(e);
|
||||||
|
}
|
||||||
|
if (!isValid || CorsUtils.isPreFlightRequest(theRequest)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.incomingRequestPreProcessed(theRequest, theResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -171,10 +171,6 @@
|
||||||
<artifactId>thymeleaf-spring4</artifactId>
|
<artifactId>thymeleaf-spring4</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.ebaysf.web</groupId>
|
|
||||||
<artifactId>cors-filter</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.phloc</groupId>
|
<groupId>com.phloc</groupId>
|
||||||
<artifactId>phloc-schematron</artifactId>
|
<artifactId>phloc-schematron</artifactId>
|
||||||
|
|
|
@ -147,11 +147,6 @@
|
||||||
<groupId>com.phloc</groupId>
|
<groupId>com.phloc</groupId>
|
||||||
<artifactId>phloc-schematron</artifactId>
|
<artifactId>phloc-schematron</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.tomcat</groupId>
|
|
||||||
<artifactId>tomcat-catalina</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package ca.uhn.fhir.jpa.demo;
|
package ca.uhn.fhir.jpa.demo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -9,6 +10,7 @@ import javax.servlet.ServletException;
|
||||||
import org.hl7.fhir.dstu3.model.Meta;
|
import org.hl7.fhir.dstu3.model.Meta;
|
||||||
import org.springframework.web.context.ContextLoaderListener;
|
import org.springframework.web.context.ContextLoaderListener;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
|
@ -30,6 +32,7 @@ import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.CorsInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
|
|
||||||
public class JpaServerDemo extends RestfulServer {
|
public class JpaServerDemo extends RestfulServer {
|
||||||
|
@ -139,6 +142,22 @@ public class JpaServerDemo extends RestfulServer {
|
||||||
*/
|
*/
|
||||||
setPagingProvider(new FifoMemoryPagingProvider(10));
|
setPagingProvider(new FifoMemoryPagingProvider(10));
|
||||||
|
|
||||||
|
// Register a CORS filter
|
||||||
|
CorsConfiguration config = new CorsConfiguration();
|
||||||
|
CorsInterceptor corsInterceptor = new CorsInterceptor(config);
|
||||||
|
config.addAllowedHeader("x-fhir-starter");
|
||||||
|
config.addAllowedHeader("Origin");
|
||||||
|
config.addAllowedHeader("Accept");
|
||||||
|
config.addAllowedHeader("X-Requested-With");
|
||||||
|
config.addAllowedHeader("Content-Type");
|
||||||
|
config.addAllowedHeader("Access-Control-Request-Method");
|
||||||
|
config.addAllowedHeader("Access-Control-Request-Headers");
|
||||||
|
config.addAllowedOrigin("*");
|
||||||
|
config.addExposedHeader("Location");
|
||||||
|
config.addExposedHeader("Content-Location");
|
||||||
|
config.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE","OPTIONS"));
|
||||||
|
registerInterceptor(corsInterceptor);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load interceptors for the server from Spring (these are defined in FhirServerConfig.java)
|
* Load interceptors for the server from Spring (these are defined in FhirServerConfig.java)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -61,52 +61,4 @@
|
||||||
<url-pattern>/</url-pattern>
|
<url-pattern>/</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- This filters provide support for Cross Origin Resource Sharing (CORS) -->
|
|
||||||
<filter>
|
|
||||||
<filter-name>CORS Filter</filter-name>
|
|
||||||
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
|
|
||||||
<init-param>
|
|
||||||
<description>A comma separated list of allowed origins. Note: An '*' cannot be used for an allowed origin when using credentials.</description>
|
|
||||||
<param-name>cors.allowed.origins</param-name>
|
|
||||||
<param-value>*</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<description>A comma separated list of HTTP verbs, using which a CORS request can be made.</description>
|
|
||||||
<param-name>cors.allowed.methods</param-name>
|
|
||||||
<param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<description>A comma separated list of allowed headers when making a non simple CORS request.</description>
|
|
||||||
<param-name>cors.allowed.headers</param-name>
|
|
||||||
<param-value>X-FHIR-Starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<description>A comma separated list non-standard response headers that will be exposed to XHR2 object.</description>
|
|
||||||
<param-name>cors.exposed.headers</param-name>
|
|
||||||
<param-value>Location,Content-Location</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<description>A flag that suggests if CORS is supported with cookies</description>
|
|
||||||
<param-name>cors.support.credentials</param-name>
|
|
||||||
<param-value>true</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<description>A flag to control logging</description>
|
|
||||||
<param-name>cors.logging.enabled</param-name>
|
|
||||||
<param-value>true</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<description>Indicates how long (in seconds) the results of a preflight request can be cached in a preflight result cache.</description>
|
|
||||||
<param-name>cors.preflight.maxage</param-name>
|
|
||||||
<param-value>300</param-value>
|
|
||||||
</init-param>
|
|
||||||
</filter>
|
|
||||||
<filter-mapping>
|
|
||||||
<filter-name>CORS Filter</filter-name>
|
|
||||||
<url-pattern>/*</url-pattern>
|
|
||||||
</filter-mapping>
|
|
||||||
|
|
||||||
|
|
||||||
</web-app>
|
</web-app>
|
||||||
|
|
|
@ -130,11 +130,13 @@
|
||||||
<artifactId>commons-dbcp2</artifactId>
|
<artifactId>commons-dbcp2</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!--
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.tomcat</groupId>
|
<groupId>org.apache.tomcat</groupId>
|
||||||
<artifactId>tomcat-catalina</artifactId>
|
<artifactId>tomcat-catalina</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
-->
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>javax.servlet</groupId>
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
package ca.uhn.fhir.jpa.config;
|
package ca.uhn.fhir.jpa.config;
|
||||||
|
|
||||||
|
import javax.el.ExpressionFactory;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class DispatcherServletConfig {
|
public class DispatcherServletConfig {
|
||||||
//nothing
|
//nothing
|
||||||
|
|
||||||
|
ExpressionFactory myFacg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,18 +3,14 @@ package ca.uhn.fhir.jpa.provider.dstu3;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.EnumSet;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.servlet.DispatcherType;
|
|
||||||
|
|
||||||
import org.apache.catalina.filters.CorsFilter;
|
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.servlet.FilterHolder;
|
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle;
|
import org.hl7.fhir.dstu3.model.Bundle;
|
||||||
|
@ -28,6 +24,7 @@ import org.springframework.web.context.WebApplicationContext;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||||
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
import org.springframework.web.servlet.DispatcherServlet;
|
import org.springframework.web.servlet.DispatcherServlet;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.config.dstu3.WebsocketDstu3Config;
|
import ca.uhn.fhir.jpa.config.dstu3.WebsocketDstu3Config;
|
||||||
|
@ -40,6 +37,7 @@ import ca.uhn.fhir.rest.client.IGenericClient;
|
||||||
import ca.uhn.fhir.rest.client.ServerValidationModeEnum;
|
import ca.uhn.fhir.rest.client.ServerValidationModeEnum;
|
||||||
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.CorsInterceptor;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
|
||||||
public abstract class BaseResourceProviderDstu3Test extends BaseJpaDstu3Test {
|
public abstract class BaseResourceProviderDstu3Test extends BaseJpaDstu3Test {
|
||||||
|
@ -116,15 +114,21 @@ public abstract class BaseResourceProviderDstu3Test extends BaseJpaDstu3Test {
|
||||||
subsServletHolder.setInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, WebsocketDstu3Config.class.getName());
|
subsServletHolder.setInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, WebsocketDstu3Config.class.getName());
|
||||||
proxyHandler.addServlet(subsServletHolder, "/*");
|
proxyHandler.addServlet(subsServletHolder, "/*");
|
||||||
|
|
||||||
FilterHolder corsFilterHolder = new FilterHolder();
|
// Register a CORS filter
|
||||||
corsFilterHolder.setHeldClass(CorsFilter.class);
|
CorsConfiguration config = new CorsConfiguration();
|
||||||
corsFilterHolder.setInitParameter("cors.allowed.origins", "*");
|
CorsInterceptor corsInterceptor = new CorsInterceptor(config);
|
||||||
corsFilterHolder.setInitParameter("cors.allowed.methods", "GET,POST,PUT,DELETE,OPTIONS");
|
config.addAllowedHeader("x-fhir-starter");
|
||||||
corsFilterHolder.setInitParameter("cors.allowed.headers", "X-FHIR-Starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers");
|
config.addAllowedHeader("Origin");
|
||||||
corsFilterHolder.setInitParameter("cors.exposed.headers", "Location,Content-Location");
|
config.addAllowedHeader("Accept");
|
||||||
corsFilterHolder.setInitParameter("cors.support.credentials", "true");
|
config.addAllowedHeader("X-Requested-With");
|
||||||
corsFilterHolder.setInitParameter("cors.logging.enabled", "true");
|
config.addAllowedHeader("Content-Type");
|
||||||
proxyHandler.addFilter(corsFilterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
|
config.addAllowedHeader("Access-Control-Request-Method");
|
||||||
|
config.addAllowedHeader("Access-Control-Request-Headers");
|
||||||
|
config.addAllowedOrigin("*");
|
||||||
|
config.addExposedHeader("Location");
|
||||||
|
config.addExposedHeader("Content-Location");
|
||||||
|
config.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE","OPTIONS"));
|
||||||
|
ourRestServer.registerInterceptor(corsInterceptor);
|
||||||
|
|
||||||
server.setHandler(proxyHandler);
|
server.setHandler(proxyHandler);
|
||||||
server.start();
|
server.start();
|
||||||
|
|
|
@ -151,17 +151,6 @@
|
||||||
<artifactId>phloc-schematron</artifactId>
|
<artifactId>phloc-schematron</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--
|
|
||||||
Used for CORS support
|
|
||||||
If you are deploying your project to Apache Tomcat, you can
|
|
||||||
comment this dependency out since the tomcat CORS filter will
|
|
||||||
already be available on the classpath
|
|
||||||
-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.tomcat</groupId>
|
|
||||||
<artifactId>tomcat-catalina</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package ca.uhn.fhir.jpa.demo;
|
package ca.uhn.fhir.jpa.demo;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -8,6 +9,7 @@ import javax.servlet.ServletException;
|
||||||
import org.hl7.fhir.dstu3.model.Meta;
|
import org.hl7.fhir.dstu3.model.Meta;
|
||||||
import org.springframework.web.context.ContextLoaderListener;
|
import org.springframework.web.context.ContextLoaderListener;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
|
@ -29,6 +31,7 @@ import ca.uhn.fhir.rest.server.ETagSupportEnum;
|
||||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.CorsInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
|
|
||||||
public class JpaServerDemo extends RestfulServer {
|
public class JpaServerDemo extends RestfulServer {
|
||||||
|
@ -140,6 +143,23 @@ public class JpaServerDemo extends RestfulServer {
|
||||||
*/
|
*/
|
||||||
setPagingProvider(myAppCtx.getBean(DatabaseBackedPagingProvider.class));
|
setPagingProvider(myAppCtx.getBean(DatabaseBackedPagingProvider.class));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable CORS
|
||||||
|
*/
|
||||||
|
CorsConfiguration config = new CorsConfiguration();
|
||||||
|
CorsInterceptor corsInterceptor = new CorsInterceptor(config);
|
||||||
|
config.addAllowedHeader("Origin");
|
||||||
|
config.addAllowedHeader("Accept");
|
||||||
|
config.addAllowedHeader("X-Requested-With");
|
||||||
|
config.addAllowedHeader("Content-Type");
|
||||||
|
config.addAllowedHeader("Access-Control-Request-Method");
|
||||||
|
config.addAllowedHeader("Access-Control-Request-Headers");
|
||||||
|
config.addAllowedOrigin("*");
|
||||||
|
config.addExposedHeader("Location");
|
||||||
|
config.addExposedHeader("Content-Location");
|
||||||
|
config.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE","OPTIONS"));
|
||||||
|
registerInterceptor(corsInterceptor);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load interceptors for the server from Spring (these are defined in FhirServerConfig.java)
|
* Load interceptors for the server from Spring (these are defined in FhirServerConfig.java)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -159,17 +159,6 @@
|
||||||
<artifactId>commons-dbcp2</artifactId>
|
<artifactId>commons-dbcp2</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--
|
|
||||||
Only required for CORS support - Change the scope from
|
|
||||||
"provided" to "compile" if you are deploying to something
|
|
||||||
other than Tomcat
|
|
||||||
-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.tomcat</groupId>
|
|
||||||
<artifactId>tomcat-catalina</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,7 @@
|
||||||
package ca.uhn.fhirtest;
|
package ca.uhn.fhirtest;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -12,6 +13,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.web.context.ContextLoaderListener;
|
import org.springframework.web.context.ContextLoaderListener;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.config.WebsocketDstu2Config;
|
import ca.uhn.fhir.jpa.config.WebsocketDstu2Config;
|
||||||
|
@ -27,19 +29,15 @@ import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
|
||||||
import ca.uhn.fhir.jpa.provider.dstu3.TerminologyUploaderProviderDstu3;
|
import ca.uhn.fhir.jpa.provider.dstu3.TerminologyUploaderProviderDstu3;
|
||||||
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
|
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
|
||||||
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
||||||
import ca.uhn.fhir.rest.server.ETagSupportEnum;
|
import ca.uhn.fhir.rest.server.*;
|
||||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
|
||||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
|
||||||
import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
|
|
||||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
|
||||||
import ca.uhn.fhir.rest.server.interceptor.BanUnsupportedHttpMethodsInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.BanUnsupportedHttpMethodsInterceptor;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.CorsInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||||
import ca.uhn.fhirtest.config.TestDstu3Config;
|
|
||||||
import ca.uhn.fhirtest.config.TdlDstu2Config;
|
import ca.uhn.fhirtest.config.TdlDstu2Config;
|
||||||
import ca.uhn.fhirtest.config.TdlDstu3Config;
|
import ca.uhn.fhirtest.config.TdlDstu3Config;
|
||||||
import ca.uhn.fhirtest.config.TestDstu2Config;
|
import ca.uhn.fhirtest.config.TestDstu2Config;
|
||||||
|
import ca.uhn.fhirtest.config.TestDstu3Config;
|
||||||
|
|
||||||
public class TestRestfulServer extends RestfulServer {
|
public class TestRestfulServer extends RestfulServer {
|
||||||
|
|
||||||
|
@ -172,6 +170,23 @@ public class TestRestfulServer extends RestfulServer {
|
||||||
|
|
||||||
setPlainProviders(plainProviders);
|
setPlainProviders(plainProviders);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable CORS
|
||||||
|
*/
|
||||||
|
CorsConfiguration config = new CorsConfiguration();
|
||||||
|
CorsInterceptor corsInterceptor = new CorsInterceptor(config);
|
||||||
|
config.addAllowedHeader("Origin");
|
||||||
|
config.addAllowedHeader("Accept");
|
||||||
|
config.addAllowedHeader("X-Requested-With");
|
||||||
|
config.addAllowedHeader("Content-Type");
|
||||||
|
config.addAllowedHeader("Access-Control-Request-Method");
|
||||||
|
config.addAllowedHeader("Access-Control-Request-Headers");
|
||||||
|
config.addAllowedOrigin("*");
|
||||||
|
config.addExposedHeader("Location");
|
||||||
|
config.addExposedHeader("Content-Location");
|
||||||
|
config.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE","OPTIONS"));
|
||||||
|
registerInterceptor(corsInterceptor);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We want to format the response using nice HTML if it's a browser, since this
|
* We want to format the response using nice HTML if it's a browser, since this
|
||||||
* makes things a little easier for testers.
|
* makes things a little easier for testers.
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
<load-on-startup>1</load-on-startup>
|
<load-on-startup>1</load-on-startup>
|
||||||
</servlet>
|
</servlet>
|
||||||
|
|
||||||
|
<!--
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>fhirServletTdl2</servlet-name>
|
<servlet-name>fhirServletTdl2</servlet-name>
|
||||||
<servlet-class>ca.uhn.fhirtest.TestRestfulServer</servlet-class>
|
<servlet-class>ca.uhn.fhirtest.TestRestfulServer</servlet-class>
|
||||||
|
@ -89,7 +90,6 @@
|
||||||
</init-param>
|
</init-param>
|
||||||
<load-on-startup>1</load-on-startup>
|
<load-on-startup>1</load-on-startup>
|
||||||
</servlet>
|
</servlet>
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>fhirServletTdl3</servlet-name>
|
<servlet-name>fhirServletTdl3</servlet-name>
|
||||||
<servlet-class>ca.uhn.fhirtest.TestRestfulServer</servlet-class>
|
<servlet-class>ca.uhn.fhirtest.TestRestfulServer</servlet-class>
|
||||||
|
@ -103,6 +103,7 @@
|
||||||
</init-param>
|
</init-param>
|
||||||
<load-on-startup>1</load-on-startup>
|
<load-on-startup>1</load-on-startup>
|
||||||
</servlet>
|
</servlet>
|
||||||
|
-->
|
||||||
|
|
||||||
<servlet-mapping>
|
<servlet-mapping>
|
||||||
<servlet-name>fhirServletDstu1</servlet-name>
|
<servlet-name>fhirServletDstu1</servlet-name>
|
||||||
|
@ -132,11 +133,11 @@
|
||||||
<url-pattern>/baseStu3/*</url-pattern>
|
<url-pattern>/baseStu3/*</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<!--
|
||||||
<servlet-mapping>
|
<servlet-mapping>
|
||||||
<servlet-name>fhirServletTdl2</servlet-name>
|
<servlet-name>fhirServletTdl2</servlet-name>
|
||||||
<url-pattern>/testDataLibraryDstu2/*</url-pattern>
|
<url-pattern>/testDataLibraryDstu2/*</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet-mapping>
|
<servlet-mapping>
|
||||||
<servlet-name>fhirServletTdl3</servlet-name>
|
<servlet-name>fhirServletTdl3</servlet-name>
|
||||||
<url-pattern>/testDataLibraryDstu3/*</url-pattern>
|
<url-pattern>/testDataLibraryDstu3/*</url-pattern>
|
||||||
|
@ -145,6 +146,7 @@
|
||||||
<servlet-name>fhirServletTdl3</servlet-name>
|
<servlet-name>fhirServletTdl3</servlet-name>
|
||||||
<url-pattern>/testDataLibraryStu3/*</url-pattern>
|
<url-pattern>/testDataLibraryStu3/*</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
-->
|
||||||
|
|
||||||
<servlet-mapping>
|
<servlet-mapping>
|
||||||
<servlet-name>fhirServletDstu2</servlet-name>
|
<servlet-name>fhirServletDstu2</servlet-name>
|
||||||
|
@ -156,52 +158,4 @@
|
||||||
<url-pattern>/</url-pattern>
|
<url-pattern>/</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- This filters provide support for Cross Origin Resource Sharing (CORS) -->
|
|
||||||
<filter>
|
|
||||||
<filter-name>CORS Filter</filter-name>
|
|
||||||
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
|
|
||||||
<init-param>
|
|
||||||
<description>A comma separated list of allowed origins. Note: An '*' cannot be used for an allowed origin when using credentials.</description>
|
|
||||||
<param-name>cors.allowed.origins</param-name>
|
|
||||||
<param-value>*</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<description>A comma separated list of HTTP verbs, using which a CORS request can be made.</description>
|
|
||||||
<param-name>cors.allowed.methods</param-name>
|
|
||||||
<param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<description>A comma separated list of allowed headers when making a non simple CORS request.</description>
|
|
||||||
<param-name>cors.allowed.headers</param-name>
|
|
||||||
<param-value>X-FHIR-Starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<description>A comma separated list non-standard response headers that will be exposed to XHR2 object.</description>
|
|
||||||
<param-name>cors.exposed.headers</param-name>
|
|
||||||
<param-value>Location,Content-Location</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<description>A flag that suggests if CORS is supported with cookies</description>
|
|
||||||
<param-name>cors.support.credentials</param-name>
|
|
||||||
<param-value>true</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<description>A flag to control logging</description>
|
|
||||||
<param-name>cors.logging.enabled</param-name>
|
|
||||||
<param-value>true</param-value>
|
|
||||||
</init-param>
|
|
||||||
<init-param>
|
|
||||||
<description>Indicates how long (in seconds) the results of a preflight request can be cached in a preflight result cache.</description>
|
|
||||||
<param-name>cors.preflight.maxage</param-name>
|
|
||||||
<param-value>300</param-value>
|
|
||||||
</init-param>
|
|
||||||
</filter>
|
|
||||||
<filter-mapping>
|
|
||||||
<filter-name>CORS Filter</filter-name>
|
|
||||||
<url-pattern>/*</url-pattern>
|
|
||||||
</filter-mapping>
|
|
||||||
|
|
||||||
|
|
||||||
</web-app>
|
</web-app>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>2.1-SNAPSHOT</version>
|
<version>2.2-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -19,18 +19,15 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-base</artifactId>
|
<artifactId>hapi-fhir-base</artifactId>
|
||||||
<version>2.1-SNAPSHOT</version>
|
<version>2.2-SNAPSHOT</version>
|
||||||
</dependency>
|
|
||||||
<!-- conformance profile -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
|
||||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
|
||||||
<version>2.1-SNAPSHOT</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Unit test dependencies -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-structures-dstu3</artifactId>
|
<artifactId>hapi-fhir-structures-dstu3</artifactId>
|
||||||
<version>2.1-SNAPSHOT</version>
|
<version>2.2-SNAPSHOT</version>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -73,11 +73,6 @@
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.ebaysf.web</groupId>
|
|
||||||
<artifactId>cors-filter</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.thymeleaf</groupId>
|
<groupId>org.thymeleaf</groupId>
|
||||||
<artifactId>thymeleaf</artifactId>
|
<artifactId>thymeleaf</artifactId>
|
||||||
|
@ -94,13 +89,13 @@
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- UNIT TEST DEPENDENCIES -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.tomcat</groupId>
|
<!-- This is used for cors -->
|
||||||
<artifactId>tomcat-catalina</artifactId>
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-web</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- UNIT TEST DEPENDENCIES -->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.sf.json-lib</groupId>
|
<groupId>net.sf.json-lib</groupId>
|
||||||
<artifactId>json-lib</artifactId>
|
<artifactId>json-lib</artifactId>
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.servlet.DispatcherType;
|
import javax.servlet.DispatcherType;
|
||||||
|
|
||||||
import org.apache.catalina.filters.CorsFilter;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.Header;
|
import org.apache.http.Header;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
|
@ -29,11 +29,14 @@ import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
|
import org.springframework.web.filter.CorsFilter;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.model.api.Bundle;
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServerSelfReferenceTest.DummyPatientResourceProvider;
|
import ca.uhn.fhir.rest.server.RestfulServerSelfReferenceTest.DummyPatientResourceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.CorsInterceptor;
|
||||||
import ca.uhn.fhir.util.PortUtil;
|
import ca.uhn.fhir.util.PortUtil;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
|
||||||
|
@ -55,11 +58,26 @@ public class CorsTest {
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
ourLog.info("Response was:\n{}", responseContent);
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
assertEquals("GET", status.getFirstHeader(Constants.HEADER_CORS_ALLOW_METHODS).getValue());
|
assertEquals("GET,POST,PUT,DELETE,OPTIONS", status.getFirstHeader(Constants.HEADER_CORS_ALLOW_METHODS).getValue());
|
||||||
assertEquals("null", status.getFirstHeader(Constants.HEADER_CORS_ALLOW_ORIGIN).getValue());
|
assertEquals("null", status.getFirstHeader(Constants.HEADER_CORS_ALLOW_ORIGIN).getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequestWithInvalidOrigin() throws ClientProtocolException, IOException {
|
||||||
|
{
|
||||||
|
HttpOptions httpOpt = new HttpOptions(ourBaseUri + "/Organization/b27ed191-f62d-4128-d99d-40b5e84f2bf2");
|
||||||
|
httpOpt.addHeader("Access-Control-Request-Method", "GET");
|
||||||
|
httpOpt.addHeader("Origin", "http://yahoo.com");
|
||||||
|
httpOpt.addHeader("Access-Control-Request-Headers", "accept, x-fhir-starter, content-type");
|
||||||
|
HttpResponse status = ourClient.execute(httpOpt);
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
assertEquals(403, status.getStatusLine().getStatusCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testContextWithSpace() throws Exception {
|
public void testContextWithSpace() throws Exception {
|
||||||
{
|
{
|
||||||
|
@ -71,7 +89,7 @@ public class CorsTest {
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
ourLog.info("Response was:\n{}", responseContent);
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
assertEquals("POST", status.getFirstHeader(Constants.HEADER_CORS_ALLOW_METHODS).getValue());
|
assertEquals("GET,POST,PUT,DELETE,OPTIONS", status.getFirstHeader(Constants.HEADER_CORS_ALLOW_METHODS).getValue());
|
||||||
assertEquals("http://www.fhir-starter.com", status.getFirstHeader(Constants.HEADER_CORS_ALLOW_ORIGIN).getValue());
|
assertEquals("http://www.fhir-starter.com", status.getFirstHeader(Constants.HEADER_CORS_ALLOW_ORIGIN).getValue());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -113,6 +131,13 @@ public class CorsTest {
|
||||||
ourClient.close();
|
ourClient.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCorsConfigMethods() {
|
||||||
|
CorsInterceptor corsInterceptor = new CorsInterceptor();
|
||||||
|
assertNotNull(corsInterceptor.getConfig());
|
||||||
|
corsInterceptor.setConfig(new CorsConfiguration());
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeClass() throws Exception {
|
public static void beforeClass() throws Exception {
|
||||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||||
|
@ -129,18 +154,26 @@ public class CorsTest {
|
||||||
// ServletHandler proxyHandler = new ServletHandler();
|
// ServletHandler proxyHandler = new ServletHandler();
|
||||||
ServletHolder servletHolder = new ServletHolder(restServer);
|
ServletHolder servletHolder = new ServletHolder(restServer);
|
||||||
|
|
||||||
FilterHolder fh = new FilterHolder();
|
CorsConfiguration config = new CorsConfiguration();
|
||||||
fh.setHeldClass(CorsFilter.class);
|
CorsInterceptor interceptor = new CorsInterceptor(config);
|
||||||
fh.setInitParameter("cors.logging.enabled", "true");
|
config.addAllowedHeader("x-fhir-starter");
|
||||||
fh.setInitParameter("cors.allowed.origins", "*");
|
config.addAllowedHeader("Origin");
|
||||||
fh.setInitParameter("cors.allowed.headers", "x-fhir-starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers");
|
config.addAllowedHeader("Accept");
|
||||||
fh.setInitParameter("cors.exposed.headers", "Location,Content-Location");
|
config.addAllowedHeader("X-Requested-With");
|
||||||
fh.setInitParameter("cors.allowed.methods", "GET,POST,PUT,DELETE,OPTIONS");
|
config.addAllowedHeader("Content-Type");
|
||||||
|
config.addAllowedHeader("Access-Control-Request-Method");
|
||||||
|
config.addAllowedHeader("Access-Control-Request-Headers");
|
||||||
|
config.addAllowedOrigin("http://www.fhir-starter.com");
|
||||||
|
config.addAllowedOrigin("null");
|
||||||
|
config.addAllowedOrigin("file://");
|
||||||
|
config.addExposedHeader("Location");
|
||||||
|
config.addExposedHeader("Content-Location");
|
||||||
|
config.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE","OPTIONS"));
|
||||||
|
restServer.registerInterceptor(interceptor);
|
||||||
|
|
||||||
ServletContextHandler ch = new ServletContextHandler();
|
ServletContextHandler ch = new ServletContextHandler();
|
||||||
ch.setContextPath("/rootctx/rcp2");
|
ch.setContextPath("/rootctx/rcp2");
|
||||||
ch.addServlet(servletHolder, "/fhirctx/fcp2/*");
|
ch.addServlet(servletHolder, "/fhirctx/fcp2/*");
|
||||||
ch.addFilter(fh, "/*", EnumSet.of(DispatcherType.INCLUDE, DispatcherType.REQUEST));
|
|
||||||
|
|
||||||
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
||||||
ourServer.setHandler(contexts);
|
ourServer.setHandler(contexts);
|
||||||
|
|
|
@ -81,11 +81,6 @@
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.ebaysf.web</groupId>
|
|
||||||
<artifactId>cors-filter</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.thymeleaf</groupId>
|
<groupId>org.thymeleaf</groupId>
|
||||||
<artifactId>thymeleaf</artifactId>
|
<artifactId>thymeleaf</artifactId>
|
||||||
|
@ -142,6 +137,11 @@
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-web</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -16,11 +16,7 @@ import static org.mockito.Mockito.when;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
@ -33,7 +29,6 @@ import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
import org.ebaysf.web.cors.CORSFilter;
|
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
@ -42,6 +37,7 @@ import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
|
|
||||||
import com.phloc.commons.collections.iterate.ArrayEnumeration;
|
import com.phloc.commons.collections.iterate.ArrayEnumeration;
|
||||||
|
|
||||||
|
@ -62,11 +58,7 @@ import ca.uhn.fhir.rest.annotation.Read;
|
||||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Search;
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
import ca.uhn.fhir.rest.server.BundleInclusionRule;
|
import ca.uhn.fhir.rest.server.*;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
|
||||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
|
||||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.util.PortUtil;
|
import ca.uhn.fhir.util.PortUtil;
|
||||||
|
@ -708,14 +700,30 @@ public class ResponseHighlightingInterceptorTest {
|
||||||
|
|
||||||
ServletHandler proxyHandler = new ServletHandler();
|
ServletHandler proxyHandler = new ServletHandler();
|
||||||
ourServlet = new RestfulServer(ourCtx);
|
ourServlet = new RestfulServer(ourCtx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable CORS
|
||||||
|
*/
|
||||||
|
CorsConfiguration config = new CorsConfiguration();
|
||||||
|
CorsInterceptor corsInterceptor = new CorsInterceptor(config);
|
||||||
|
config.addAllowedHeader("Origin");
|
||||||
|
config.addAllowedHeader("Accept");
|
||||||
|
config.addAllowedHeader("X-Requested-With");
|
||||||
|
config.addAllowedHeader("Content-Type");
|
||||||
|
config.addAllowedHeader("Access-Control-Request-Method");
|
||||||
|
config.addAllowedHeader("Access-Control-Request-Headers");
|
||||||
|
config.addAllowedOrigin("*");
|
||||||
|
config.addExposedHeader("Location");
|
||||||
|
config.addExposedHeader("Content-Location");
|
||||||
|
config.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE","OPTIONS"));
|
||||||
|
ourServlet.registerInterceptor(corsInterceptor);
|
||||||
|
|
||||||
ourServlet.registerInterceptor(new ResponseHighlighterInterceptor());
|
ourServlet.registerInterceptor(new ResponseHighlighterInterceptor());
|
||||||
ourServlet.setResourceProviders(patientProvider, new DummyBinaryResourceProvider());
|
ourServlet.setResourceProviders(patientProvider, new DummyBinaryResourceProvider());
|
||||||
ourServlet.setBundleInclusionRule(BundleInclusionRule.BASED_ON_RESOURCE_PRESENCE);
|
ourServlet.setBundleInclusionRule(BundleInclusionRule.BASED_ON_RESOURCE_PRESENCE);
|
||||||
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
||||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||||
|
|
||||||
proxyHandler.addFilterWithMapping(CORSFilter.class, "/*", 1);
|
|
||||||
|
|
||||||
ourServer.setHandler(proxyHandler);
|
ourServer.setHandler(proxyHandler);
|
||||||
ourServer.start();
|
ourServer.start();
|
||||||
|
|
||||||
|
|
|
@ -95,11 +95,6 @@
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.ebaysf.web</groupId>
|
|
||||||
<artifactId>cors-filter</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.thymeleaf</groupId>
|
<groupId>org.thymeleaf</groupId>
|
||||||
<artifactId>thymeleaf</artifactId>
|
<artifactId>thymeleaf</artifactId>
|
||||||
|
@ -153,6 +148,11 @@
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-web</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<reporting>
|
<reporting>
|
||||||
|
|
|
@ -94,11 +94,6 @@
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.ebaysf.web</groupId>
|
|
||||||
<artifactId>cors-filter</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.thymeleaf</groupId>
|
<groupId>org.thymeleaf</groupId>
|
||||||
<artifactId>thymeleaf</artifactId>
|
<artifactId>thymeleaf</artifactId>
|
||||||
|
@ -155,6 +150,11 @@
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-web</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<reporting>
|
<reporting>
|
||||||
|
|
14
pom.xml
14
pom.xml
|
@ -309,8 +309,6 @@
|
||||||
<phloc_commons_version>4.4.5</phloc_commons_version>
|
<phloc_commons_version>4.4.5</phloc_commons_version>
|
||||||
<spring_version>4.3.1.RELEASE</spring_version>
|
<spring_version>4.3.1.RELEASE</spring_version>
|
||||||
<thymeleaf-version>3.0.1.RELEASE</thymeleaf-version>
|
<thymeleaf-version>3.0.1.RELEASE</thymeleaf-version>
|
||||||
<tomcat_version>8.0.39</tomcat_version>
|
|
||||||
<ebay_cors_filter_version>1.0.1</ebay_cors_filter_version>
|
|
||||||
<xmlunit_version>1.6</xmlunit_version>
|
<xmlunit_version>1.6</xmlunit_version>
|
||||||
|
|
||||||
<!-- We are aiming to still work on a very old version of SLF4j even though we depend on the newest, just to be nice to users of the API. This version is tested in the hapi-fhir-cobertura. -->
|
<!-- We are aiming to still work on a very old version of SLF4j even though we depend on the newest, just to be nice to users of the API. This version is tested in the hapi-fhir-cobertura. -->
|
||||||
|
@ -526,12 +524,6 @@
|
||||||
<artifactId>wagon-scm</artifactId>
|
<artifactId>wagon-scm</artifactId>
|
||||||
<version>2.10</version>
|
<version>2.10</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.tomcat</groupId>
|
|
||||||
<artifactId>tomcat-catalina</artifactId>
|
|
||||||
<!-- Use property for version because we should refer to this from docs -->
|
|
||||||
<version>${tomcat_version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.velocity</groupId>
|
<groupId>org.apache.velocity</groupId>
|
||||||
<artifactId>velocity</artifactId>
|
<artifactId>velocity</artifactId>
|
||||||
|
@ -547,11 +539,6 @@
|
||||||
<artifactId>woodstox-core-asl</artifactId>
|
<artifactId>woodstox-core-asl</artifactId>
|
||||||
<version>4.4.1</version>
|
<version>4.4.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.ebaysf.web</groupId>
|
|
||||||
<artifactId>cors-filter</artifactId>
|
|
||||||
<version>${ebay_cors_filter_version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-http</artifactId>
|
<artifactId>jetty-http</artifactId>
|
||||||
|
@ -1592,6 +1579,7 @@
|
||||||
<module>hapi-fhir-base-test-mindeps-server</module>
|
<module>hapi-fhir-base-test-mindeps-server</module>
|
||||||
<module>hapi-tinder-plugin</module>
|
<module>hapi-tinder-plugin</module>
|
||||||
<module>hapi-tinder-test</module>
|
<module>hapi-tinder-test</module>
|
||||||
|
<module>hapi-fhir-narrativegenerator</module>
|
||||||
<module>hapi-fhir-structures-dstu</module>
|
<module>hapi-fhir-structures-dstu</module>
|
||||||
<module>hapi-fhir-validation-resources-dstu2</module>
|
<module>hapi-fhir-validation-resources-dstu2</module>
|
||||||
<module>hapi-fhir-structures-dstu2</module>
|
<module>hapi-fhir-structures-dstu2</module>
|
||||||
|
|
|
@ -30,11 +30,13 @@
|
||||||
to GitHub user @vijayt27 for reporting!
|
to GitHub user @vijayt27 for reporting!
|
||||||
</action>
|
</action>
|
||||||
<action type="add">
|
<action type="add">
|
||||||
All server examples as well as the CLI have been
|
As the eBay CORS interceptor has gone dormant, we have introduced a new
|
||||||
switched from using eBay's CORS filter to using
|
HAPI server interceptor which can be used to implement CORS support
|
||||||
the Apache Tomcat CORS filter instead. The former
|
instead of using the previously recommended Servlet Filter. All server
|
||||||
has become unmaintained and has unfixed bugs so
|
examples as well as the CLI have been switched to use this new interceptor.
|
||||||
it is no longer recommended for use.
|
See the
|
||||||
|
<![CDATA[<a href="./doc_cors.html">CORS Documentation</a>]]>
|
||||||
|
for more information.
|
||||||
</action>
|
</action>
|
||||||
<action type="fix" issue="480">
|
<action type="fix" issue="480">
|
||||||
Make the parser configurable so that when
|
Make the parser configurable so that when
|
||||||
|
|
|
@ -10,13 +10,7 @@
|
||||||
|
|
||||||
<section name="CORS">
|
<section name="CORS">
|
||||||
|
|
||||||
<p>
|
<p class="doc_info_bubble">
|
||||||
If you are intending to support JavaScript clients in your server application,
|
|
||||||
you will need to enable Cross Origin Resource Sharing (CORS). There are
|
|
||||||
a number of ways of supporting this, but the easiest is to use a servlet filter.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Note that in previous revisions of this document we recommended using the
|
Note that in previous revisions of this document we recommended using the
|
||||||
<a href="https://github.com/ebay/cors-filter">eBay CORS Filter</a>, but
|
<a href="https://github.com/ebay/cors-filter">eBay CORS Filter</a>, but
|
||||||
as of 2016 the eBay filter is no longer being maintained and contains known bugs.
|
as of 2016 the eBay filter is no longer being maintained and contains known bugs.
|
||||||
|
@ -24,34 +18,79 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The following examples show how to use the Apache Tomcat CorsFilter to enable
|
If you are intending to support JavaScript clients in your server application,
|
||||||
CORS support. The instructions below should work even on platforms other than
|
you will generally need to enable Cross Origin Resource Sharing (CORS). There are
|
||||||
Tomcat (in other words, you can deploy the Tomcat CorsFilter to Jetty or JBoss if you like)
|
a number of ways of supporting this, so two are shown here:
|
||||||
but if you run into conflicts it may be worth investigating if there is a dedicated
|
|
||||||
CORS filter for the platform you are using.
|
|
||||||
</p>
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>An approach using a HAPI FHIR Server Interceptor (Requires SpringFramework)</li>
|
||||||
|
<li>An approach using a servlet Filter (Container Specific)</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<subsection name="HAPI FHIR Server Interceptor">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The HAPI FHIR server framework includes an interceptor that can be
|
||||||
|
used to provide CORS functionality on your server. This mechanism is
|
||||||
|
nice because it relies purely on Java configuration (no messing around with
|
||||||
|
web.xml files). HAPI's interceptor is a thin wrapper around Spring Framework's
|
||||||
|
CorsProcessor class, so it requires Spring to be present on your classpath.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Spring is generally unlikely to conflict with other libraries so it is usually
|
||||||
|
safe to add it to your classpath, but it is a fairly large library so if size is
|
||||||
|
a concern you might opt to use a filter instead.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The following steps outline how to enable HAPI's CorsInterceptor:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Add the following dependency to your POM. Note the exclusion of
|
||||||
|
commons-logging, as we are using SLF4j without commons-logging in
|
||||||
|
most of our examples. If your application uses commons-logging you don't need
|
||||||
|
to exclude that dependency.
|
||||||
|
</p>
|
||||||
|
<source><![CDATA[<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-web</artifactId>
|
||||||
|
<version>${spring_version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-logging</artifactId>
|
||||||
|
<groupId>commons-logging</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>]]></source>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In your server's initialization method, create and register
|
||||||
|
a CorsInterceptor:
|
||||||
|
</p>
|
||||||
|
<macro name="snippet">
|
||||||
|
<param name="id" value="corsInterceptor" />
|
||||||
|
<param name="file" value="examples/src/main/java/example/ServletExamples.java" />
|
||||||
|
</macro>
|
||||||
|
|
||||||
|
</subsection>
|
||||||
|
|
||||||
<subsection name="Add the Dependency">
|
<subsection name="Add the Dependency">
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
If you are deploying to a platform other than Tomcat, add the
|
The following examples show how to use the Apache Tomcat CorsFilter to enable
|
||||||
following dependency to your Maven POM. If you are deploying
|
CORS support. The filter being used
|
||||||
to Tomcat, the required classes are present on the classpath
|
(<code>org.apache.catalina.filters.CorsFilter</code>) is bundled with Apache
|
||||||
so youdo not need to do this step.
|
Tomcat so if you are deploying to that server you can use the filter.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Add the following dependency to your POM:
|
Other containers have similar filters you can use, so consult the documentation
|
||||||
|
for the given container you are using for more information. (If you have
|
||||||
|
an example for how to configure a different CORS filter, please send it
|
||||||
|
our way! Examples are always useful!)
|
||||||
</p>
|
</p>
|
||||||
<source><![CDATA[<dependency>
|
|
||||||
<groupId>org.apache.tomcat</groupId>
|
|
||||||
<artifactId>tomcat-catalina</artifactId>
|
|
||||||
<version>${tomcat_version}</version>
|
|
||||||
</dependency>]]></source>
|
|
||||||
|
|
||||||
</subsection>
|
|
||||||
|
|
||||||
<subsection name="Add the filter to your web.xml">
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
In your web.xml file (within the WEB-INF directory in your WAR file),
|
In your web.xml file (within the WEB-INF directory in your WAR file),
|
||||||
|
|
|
@ -290,6 +290,17 @@
|
||||||
|
|
||||||
</subsection>
|
</subsection>
|
||||||
|
|
||||||
|
<subsection name="CORS (Cross-Origin Resource Sharing)">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
HAPI FHIR includes an interceptor which can be used to
|
||||||
|
implement CORS support on your server. See HAPI's
|
||||||
|
<a href="./doc_cors.html">CORS Documentation</a> for information
|
||||||
|
on how to use this interceptor.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</subsection>
|
||||||
|
|
||||||
<subsection name="Rejecting Unsupported HTTP Verbs">
|
<subsection name="Rejecting Unsupported HTTP Verbs">
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
Loading…
Reference in New Issue