Clean up CORS

This commit is contained in:
James Agnew 2016-11-21 13:37:59 +01:00
parent 4ed17457dd
commit ba896e2553
5 changed files with 68 additions and 1201 deletions

View File

@ -94,12 +94,16 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<scope>test</scope>
</dependency>
<!-- UNIT TEST DEPENDENCIES --> <!-- 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>
<version>2.4</version>
<classifier>jdk15</classifier> <classifier>jdk15</classifier>
<scope>test</scope> <scope>test</scope>
<exclusions> <exclusions>
@ -112,14 +116,12 @@
<dependency> <dependency>
<groupId>net.sf.json-lib</groupId> <groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId> <artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15-sources</classifier> <classifier>jdk15-sources</classifier>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>directory-naming</groupId> <groupId>directory-naming</groupId>
<artifactId>naming-java</artifactId> <artifactId>naming-java</artifactId>
<version>0.8</version>
<scope>test</scope> <scope>test</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>

View File

@ -1,13 +1,15 @@
package ca.uhn.fhir.rest.server; package ca.uhn.fhir.rest.server;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets;
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;
@ -19,7 +21,6 @@ import org.apache.http.entity.StringEntity;
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.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.FilterHolder;
@ -51,7 +52,7 @@ public class CorsTest {
httpOpt.addHeader("Origin", "null"); httpOpt.addHeader("Origin", "null");
httpOpt.addHeader("Access-Control-Request-Headers", "accept, x-fhir-starter, content-type"); httpOpt.addHeader("Access-Control-Request-Headers", "accept, x-fhir-starter, content-type");
HttpResponse status = ourClient.execute(httpOpt); HttpResponse status = ourClient.execute(httpOpt);
String responseContent = IOUtils.toString(status.getEntity().getContent()); 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", status.getFirstHeader(Constants.HEADER_CORS_ALLOW_METHODS).getValue());
@ -67,7 +68,7 @@ public class CorsTest {
httpOpt.addHeader("Origin", "http://www.fhir-starter.com"); httpOpt.addHeader("Origin", "http://www.fhir-starter.com");
httpOpt.addHeader("Access-Control-Request-Headers", "accept, x-fhir-starter, content-type"); httpOpt.addHeader("Access-Control-Request-Headers", "accept, x-fhir-starter, content-type");
HttpResponse status = ourClient.execute(httpOpt); HttpResponse status = ourClient.execute(httpOpt);
String responseContent = IOUtils.toString(status.getEntity().getContent()); 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("POST", status.getFirstHeader(Constants.HEADER_CORS_ALLOW_METHODS).getValue());
@ -83,7 +84,7 @@ public class CorsTest {
Header origin = status.getFirstHeader(Constants.HEADER_CORS_ALLOW_ORIGIN); Header origin = status.getFirstHeader(Constants.HEADER_CORS_ALLOW_ORIGIN);
assertEquals("http://www.fhir-starter.com", origin.getValue()); assertEquals("http://www.fhir-starter.com", origin.getValue());
String responseContent = IOUtils.toString(status.getEntity().getContent()); 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);
@ -99,7 +100,7 @@ public class CorsTest {
httpOpt.addHeader("Access-Control-Request-Headers", "accept, x-fhir-starter, content-type"); httpOpt.addHeader("Access-Control-Request-Headers", "accept, x-fhir-starter, content-type");
httpOpt.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(new Patient()))); httpOpt.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(new Patient())));
HttpResponse status = ourClient.execute(httpOpt); HttpResponse status = ourClient.execute(httpOpt);
String responseContent = IOUtils.toString(status.getEntity().getContent()); String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response: {}", status); ourLog.info("Response: {}", status);
ourLog.info("Response was:\n{}", responseContent); ourLog.info("Response was:\n{}", responseContent);
@ -129,7 +130,7 @@ public class CorsTest {
ServletHolder servletHolder = new ServletHolder(restServer); ServletHolder servletHolder = new ServletHolder(restServer);
FilterHolder fh = new FilterHolder(); FilterHolder fh = new FilterHolder();
fh.setHeldClass(CORSFilter_.class); fh.setHeldClass(CorsFilter.class);
fh.setInitParameter("cors.logging.enabled", "true"); fh.setInitParameter("cors.logging.enabled", "true");
fh.setInitParameter("cors.allowed.origins", "*"); fh.setInitParameter("cors.allowed.origins", "*");
fh.setInitParameter("cors.allowed.headers", "x-fhir-starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers"); fh.setInitParameter("cors.allowed.headers", "x-fhir-starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers");

View File

@ -25,9 +25,13 @@ import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletHolder;
import org.hl7.fhir.dstu3.model.DateType; import org.hl7.fhir.dstu3.model.DateType;
import org.hl7.fhir.dstu3.model.IdType; import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.OperationOutcome;
import org.hl7.fhir.dstu3.model.OperationOutcome.OperationOutcomeIssueComponent;
import org.hl7.fhir.dstu3.model.Patient; import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
@ -45,7 +49,13 @@ public class CreateDstu3Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CreateDstu3Test.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CreateDstu3Test.class);
private static int ourPort; private static int ourPort;
private static Server ourServer; private static Server ourServer;
public static IBaseOperationOutcome ourReturnOo;
@Before
public void before() {
ourReturnOo = null;
}
/** /**
* #472 * #472
*/ */
@ -69,6 +79,24 @@ public class CreateDstu3Test {
} }
@Test
public void testCreateReturnsOperationOutcome() throws Exception {
ourReturnOo = new OperationOutcome().addIssue(new OperationOutcomeIssueComponent().setDiagnostics("DIAG"));
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
httpPost.setEntity(new StringEntity("{\"resourceType\":\"Patient\", \"status\":\"active\"}", ContentType.parse("application/fhir+json; charset=utf-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertThat(responseContent, containsString("DIAG"));
}
/** /**
* #342 * #342
*/ */
@ -209,7 +237,7 @@ public class CreateDstu3Test {
@Create() @Create()
public MethodOutcome create(@ResourceParam Patient theIdParam) { public MethodOutcome create(@ResourceParam Patient theIdParam) {
return new MethodOutcome(new IdType("Patient", "1"), true); return new MethodOutcome(new IdType("Patient", "1"), true).setOperationOutcome(ourReturnOo);
} }
@Override @Override

View File

@ -3,7 +3,7 @@
<properties> <properties>
<title>CORS</title> <title>CORS</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author> <author email="jamesagnew@gmail.com">James Agnew</author>
</properties> </properties>
<body> <body>
@ -15,37 +15,41 @@
you will need to enable Cross Origin Resource Sharing (CORS). There are 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. a number of ways of supporting this, but the easiest is to use a servlet filter.
</p> </p>
<p> <p>
The recommended filter for this purpose is the Note that in previous revisions of this document we recommended using the
eBay Open Sourced <a href="https://github.com/ebay/cors-filter">eBay CORS Filter</a>, but
<a href="https://github.com/ebay/cors-filter">CORS Filter</a> (Licensed under as of 2016 the eBay filter is no longer being maintained and contains known bugs.
the Apache Software License 2.0). We now recommend against using this filter.
</p> </p>
<p> <p>
To add CORS support using this library, there are two simple steps: The following examples show how to use the Apache Tomcat CorsFilter to enable
CORS support. The instructions below should work even on platforms other than
Tomcat (in other words, you can deploy the Tomcat CorsFilter to Jetty or JBoss if you like)
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>
<subsection name="Include cors-filter JAR"> <subsection name="Add the Dependency">
<p> <p>
In your server WAR file, you must include the <b>cors-filter-X.X.X.JAR</b> If you are deploying to a platform other than Tomcat, add the
dependency. This dependency is included in the HAPI distribution. following dependency to your Maven POM. If you are deploying
to Tomcat, the required classes are present on the classpath
so youdo not need to do this step.
</p> </p>
<p> <p>
If you are using Maven, you will need to Add the following dependency to your POM:
explicitly include it in your project pom.xml using the following dependency:
</p> </p>
<source><![CDATA[<dependency> <source><![CDATA[<dependency>
<groupId>org.ebaysf.web</groupId> <groupId>org.apache.tomcat</groupId>
<artifactId>cors-filter</artifactId> <artifactId>tomcat-catalina</artifactId>
<version>1.0.1</version> <version>${tomcat_version}</version>
<optional>true</optional>
</dependency>]]></source> </dependency>]]></source>
</subsection> </subsection>
<subsection name="Add the filter to your web.xml"> <subsection name="Add the filter to your web.xml">
@ -57,7 +61,7 @@
<source><![CDATA[<filter> <source><![CDATA[<filter>
<filter-name>CORS Filter</filter-name> <filter-name>CORS Filter</filter-name>
<filter-class>org.ebaysf.web.cors.CORSFilter</filter-class> <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param> <init-param>
<description>A comma separated list of allowed origins. Note: An '*' cannot be used for an allowed origin when using credentials.</description> <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-name>cors.allowed.origins</param-name>
@ -99,7 +103,7 @@
<url-pattern>/*</url-pattern> <url-pattern>/*</url-pattern>
</filter-mapping>]]></source> </filter-mapping>]]></source>
</subsection> </subsection>
</section> </section>