Don't return a Content-Location header when returning the new bundle

format
This commit is contained in:
James Agnew 2015-04-20 17:32:20 -04:00
parent 4f1d2a3c75
commit 91167733c6
11 changed files with 90 additions and 44 deletions

View File

@ -64,18 +64,21 @@
<artifactId>slf4j-android</artifactId> <artifactId>slf4j-android</artifactId>
<version>${slf4j_version}</version> <version>${slf4j_version}</version>
</dependency> </dependency>
<!-- <dependency> <groupId>org.codehaus.woodstox</groupId> <artifactId>stax2-api</artifactId> <dependency>
<version>3.1.4</version> </dependency> --> <groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j_version}</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
<version>${commons_io_version}</version> <version>${commons_io_version}</version>
<scope>test</scope>
</dependency> </dependency>
<!-- <!-- Android does not come with the Servlet API bundled, and MethodUtil
Android does not come with the Servlet API bundled, and MethodUtil requires it requires it -->
-->
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
@ -134,11 +137,10 @@
</goals> </goals>
<configuration> <configuration>
<createDependencyReducedPom>true</createDependencyReducedPom> <createDependencyReducedPom>true</createDependencyReducedPom>
<!-- <minimizeJar>true</minimizeJar>--> <!-- <minimizeJar>true</minimizeJar> -->
<artifactSet> <artifactSet>
<includes> <includes>
<include>commons-codec:commons-codec</include> <include>commons-codec:commons-codec</include>
<include>commons-io:commons-io</include>
<include>ca.uhn.hapi.fhir:hapi-fhir-base</include> <include>ca.uhn.hapi.fhir:hapi-fhir-base</include>
<include>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu</include> <include>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu</include>
<include>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2</include> <include>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2</include>
@ -147,7 +149,7 @@
<include>javax.xml.stream:stax-api</include> <include>javax.xml.stream:stax-api</include>
<include>javax.servlet:javax.servlet-api</include> <include>javax.servlet:javax.servlet-api</include>
<include>org.codehaus.woodstox:stax2-api</include> <include>org.codehaus.woodstox:stax2-api</include>
<!-- <include>org.slf4j:slf4j*</include> --> <!-- <include>org.slf4j:slf4j*</include> -->
<include>org.apache.commons:*</include> <include>org.apache.commons:*</include>
<include>org.apache.httpcomponents:*</include> <include>org.apache.httpcomponents:*</include>
<include>org.glassfish:javax.json</include> <include>org.glassfish:javax.json</include>
@ -178,7 +180,7 @@
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<profiles> <profiles>
<profile> <profile>
<id>DIST</id> <id>DIST</id>
@ -207,5 +209,5 @@
</build> </build>
</profile> </profile>
</profiles> </profiles>
</project> </project>

View File

@ -0,0 +1,14 @@
package ca.uhn.fhir.android;
import ca.uhn.fhir.context.FhirContext;
public class AndroidLoader {
public static void main(String[] theArgs) {
FhirContext ctx = FhirContext.forDstu2();
ctx.newJsonParser();
ctx.newXmlParser();
ctx.newRestfulGenericClient("");
}
}

View File

@ -279,7 +279,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
return; return;
} }
} }
RestfulServerUtils.streamResponseAsResource(theServer, response, resource, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, respondGzip, theRequest.getFhirServerBase()); RestfulServerUtils.streamResponseAsResource(theServer, response, resource, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, Constants.STATUS_HTTP_200_OK, respondGzip, theRequest.getFhirServerBase(), isAddContentLocationHeader());
break; break;
} else { } else {
Set<Include> includes = getRequestIncludesFromParams(params); Set<Include> includes = getRequestIncludesFromParams(params);
@ -312,7 +312,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
return; return;
} }
} }
RestfulServerUtils.streamResponseAsResource(theServer, response, (IResource) resBundle, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, Constants.STATUS_HTTP_200_OK, theRequest.isRespondGzip(), theRequest.getFhirServerBase()); RestfulServerUtils.streamResponseAsResource(theServer, response, (IResource) resBundle, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, Constants.STATUS_HTTP_200_OK, theRequest.isRespondGzip(), theRequest.getFhirServerBase(), isAddContentLocationHeader());
} }
break; break;
@ -336,12 +336,19 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
} }
} }
RestfulServerUtils.streamResponseAsResource(theServer, response, resource, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, respondGzip, theRequest.getFhirServerBase()); RestfulServerUtils.streamResponseAsResource(theServer, response, resource, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, Constants.STATUS_HTTP_200_OK, respondGzip, theRequest.getFhirServerBase(), isAddContentLocationHeader());
break; break;
} }
} }
} }
/**
* Should the response include a Content-Location header. Search method bunding (and any others?) may override this to disable the content-location, since it doesn't make sense
*/
protected boolean isAddContentLocationHeader() {
return true;
}
/** /**
* Subclasses may override * Subclasses may override
* *

View File

@ -132,6 +132,11 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
return RestfulOperationTypeEnum.SEARCH_TYPE; return RestfulOperationTypeEnum.SEARCH_TYPE;
} }
@Override
protected BundleTypeEnum getResponseBundleType() {
return BundleTypeEnum.SEARCHSET;
}
@Override @Override
public ReturnTypeEnum getReturnType() { public ReturnTypeEnum getReturnType() {
return ReturnTypeEnum.BUNDLE; return ReturnTypeEnum.BUNDLE;
@ -289,13 +294,9 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
} }
public void setResourceType(Class<? extends IResource> resourceType) {
this.myDeclaredResourceType = resourceType;
}
@Override @Override
public String toString() { protected boolean isAddContentLocationHeader() {
return getMethod().toString(); return false;
} }
private List<String> processWhitelistAndBlacklist(List<String> theQualifiedNames, Set<String> theQualifierWhitelist, Set<String> theQualifierBlacklist) { private List<String> processWhitelistAndBlacklist(List<String> theQualifiedNames, Set<String> theQualifierWhitelist, Set<String> theQualifierBlacklist) {
@ -313,6 +314,15 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
return retVal; return retVal;
} }
public void setResourceType(Class<? extends IResource> resourceType) {
this.myDeclaredResourceType = resourceType;
}
@Override
public String toString() {
return getMethod().toString();
}
public static BaseHttpClientInvocation createSearchInvocation(FhirContext theContext, String theResourceName, Map<String, List<String>> theParameters, IdDt theId, String theCompartmentName, public static BaseHttpClientInvocation createSearchInvocation(FhirContext theContext, String theResourceName, Map<String, List<String>> theParameters, IdDt theId, String theCompartmentName,
SearchStyleEnum theSearchStyle) { SearchStyleEnum theSearchStyle) {
SearchStyleEnum searchStyle = theSearchStyle; SearchStyleEnum searchStyle = theSearchStyle;
@ -473,9 +483,4 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
} }
@Override
protected BundleTypeEnum getResponseBundleType() {
return BundleTypeEnum.SEARCHSET;
}
} }

View File

@ -490,7 +490,7 @@ public class RestfulServer extends HttpServlet {
return; return;
} }
} }
RestfulServerUtils.streamResponseAsResource(this, theResponse, (IResource) resBundle, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, Constants.STATUS_HTTP_200_OK, theRequest.isRespondGzip(), theRequest.getFhirServerBase()); RestfulServerUtils.streamResponseAsResource(this, theResponse, (IResource) resBundle, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, Constants.STATUS_HTTP_200_OK, theRequest.isRespondGzip(), theRequest.getFhirServerBase(), false);
} }
} }

View File

@ -73,10 +73,10 @@ public class RestfulServerUtils {
} }
public static void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IResource theResource, EncodingEnum theResponseEncoding, boolean thePrettyPrint, public static void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IResource theResource, EncodingEnum theResponseEncoding, boolean thePrettyPrint,
boolean theRequestIsBrowser, RestfulServer.NarrativeModeEnum theNarrativeMode, int stausCode, boolean theRespondGzip, String theServerBase) throws IOException { boolean theRequestIsBrowser, RestfulServer.NarrativeModeEnum theNarrativeMode, int stausCode, boolean theRespondGzip, String theServerBase, boolean theAddContentLocationHeader) throws IOException {
theHttpResponse.setStatus(stausCode); theHttpResponse.setStatus(stausCode);
if (theResource.getId() != null && theResource.getId().hasIdPart() && isNotBlank(theServerBase)) { if (theAddContentLocationHeader && theResource.getId() != null && theResource.getId().hasIdPart() && isNotBlank(theServerBase)) {
String resName = theServer.getFhirContext().getResourceDefinition(theResource).getName(); String resName = theServer.getFhirContext().getResourceDefinition(theResource).getName();
IdDt fullId = theResource.getId().withServerBase(theServerBase, resName); IdDt fullId = theResource.getId().withServerBase(theServerBase, resName);
theHttpResponse.addHeader(Constants.HEADER_CONTENT_LOCATION, fullId.getValue()); theHttpResponse.addHeader(Constants.HEADER_CONTENT_LOCATION, fullId.getValue());
@ -402,12 +402,12 @@ public class RestfulServerUtils {
} }
} }
public static void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IResource theResource, EncodingEnum theResponseEncoding, boolean thePrettyPrint, // public static void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IResource theResource, EncodingEnum theResponseEncoding, boolean thePrettyPrint,
boolean theRequestIsBrowser, RestfulServer.NarrativeModeEnum theNarrativeMode, boolean theRespondGzip, String theServerBase) throws IOException { // boolean theRequestIsBrowser, RestfulServer.NarrativeModeEnum theNarrativeMode, boolean theRespondGzip, String theServerBase) throws IOException {
int stausCode = 200; // int stausCode = 200;
RestfulServerUtils.streamResponseAsResource(theServer, theHttpResponse, theResource, theResponseEncoding, thePrettyPrint, theRequestIsBrowser, theNarrativeMode, stausCode, theRespondGzip, // RestfulServerUtils.streamResponseAsResource(theServer, theHttpResponse, theResource, theResponseEncoding, thePrettyPrint, theRequestIsBrowser, theNarrativeMode, stausCode, theRespondGzip,
theServerBase); // theServerBase);
} // }
public static void validateResourceListNotNull(List<IResource> theResourceList) { public static void validateResourceListNotNull(List<IResource> theResourceList) {
if (theResourceList == null) { if (theResourceList == null) {

View File

@ -129,7 +129,7 @@ public class ExceptionHandlingInterceptor extends InterceptorAdapter {
boolean requestIsBrowser = RestfulServer.requestIsBrowser(theRequest); boolean requestIsBrowser = RestfulServer.requestIsBrowser(theRequest);
String fhirServerBase = ((Request) theRequestDetails).getFhirServerBase(); String fhirServerBase = ((Request) theRequestDetails).getFhirServerBase();
RestfulServerUtils.streamResponseAsResource(theRequestDetails.getServer(), theResponse, oo, RestfulServerUtils.determineResponseEncodingNoDefault(theRequest), true, requestIsBrowser, RestfulServerUtils.streamResponseAsResource(theRequestDetails.getServer(), theResponse, oo, RestfulServerUtils.determineResponseEncodingNoDefault(theRequest), true, requestIsBrowser,
NarrativeModeEnum.NORMAL, statusCode, false, fhirServerBase); NarrativeModeEnum.NORMAL, statusCode, false, fhirServerBase, false);
// theResponse.setStatus(statusCode); // theResponse.setStatus(statusCode);
// theRequestDetails.getServer().addHeadersToResponse(theResponse); // theRequestDetails.getServer().addHeadersToResponse(theResponse);

View File

@ -4,12 +4,11 @@ import java.util.List;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import ca.uhn.fhir.context.FhirVersionEnum;
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 ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao; import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu1; import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu1;
import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2; import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2;
@ -23,7 +22,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.LoggingInterceptor; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
public class JpaServerDemo extends RestfulServer { public class JpaServerDemo extends RestfulServer {
@ -123,12 +122,12 @@ public class JpaServerDemo extends RestfulServer {
setPagingProvider(new FifoMemoryPagingProvider(10)); setPagingProvider(new FifoMemoryPagingProvider(10));
/* /*
* Do some fancy logging to create a nice access log that has details about each incoming request. * Load interceptors for the server from Spring (these are defined in hapi-fhir-server-config.xml
*/ */
LoggingInterceptor loggingInterceptor = new LoggingInterceptor(); List<IServerInterceptor> interceptorBeans = myAppCtx.getBean("myServerInterceptors", List.class);
loggingInterceptor.setLoggerName("fhir.access"); for (IServerInterceptor interceptor : interceptorBeans) {
loggingInterceptor.setMessageFormat("Path[${servletPath}] Operation[${operationType} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}]"); this.registerInterceptor(interceptor);
this.registerInterceptor(loggingInterceptor); }
} }

View File

@ -21,4 +21,18 @@
</bean> </bean>
<tx:annotation-driven transaction-manager="myTxManager" /> <tx:annotation-driven transaction-manager="myTxManager" />
<util:list id="myServerInterceptors">
<ref bean="myLoggingInterceptor"/>
</util:list>
<!--
Do some fancy logging to create a nice access log that has details
about each incoming request.
-->
<bean id="myLoggingInterceptor" class="ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor">
<property name="loggerName" value="fhirtest.access"/>
<property name="messageFormat"
value="Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}]"/>
</bean>
</beans> </beans>

View File

@ -1,6 +1,6 @@
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.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -49,6 +49,7 @@ public class SearchDstu2Test {
Patient patient = (Patient) ourCtx.newXmlParser().parseResource(Bundle.class, responseContent).getEntry().get(0).getResource(); Patient patient = (Patient) ourCtx.newXmlParser().parseResource(Bundle.class, responseContent).getEntry().get(0).getResource();
String ref = patient.getManagingOrganization().getReference().getValue(); String ref = patient.getManagingOrganization().getReference().getValue();
assertEquals("Organization/555", ref); assertEquals("Organization/555", ref);
assertNull(status.getFirstHeader(Constants.HEADER_CONTENT_LOCATION));
} }

View File

@ -136,6 +136,10 @@
Please let us know if this is a big hardship and we can find an alternate way Please let us know if this is a big hardship and we can find an alternate way
of making this change. of making this change.
</action> </action>
<action type="fix">
Prevent server from returning a Content-Location header for search
response when using the DSTU2 bundle format
</action>
</release> </release>
<release version="0.9" date="2015-Mar-14"> <release version="0.9" date="2015-Mar-14">
<action type="add"> <action type="add">