Fix #411 - Searching by POST with urlencoded parameters doesn't work if
interceptors are accessing the parameters and there is are also parameters on the URL
This commit is contained in:
parent
f5eda76388
commit
11d3ae9447
|
@ -528,13 +528,9 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
for (IServerInterceptor next : myInterceptors) {
|
/* ***********************************
|
||||||
boolean continueProcessing = next.incomingRequestPreProcessed(theRequest, theResponse);
|
* Parse out the request parameters
|
||||||
if (!continueProcessing) {
|
* ***********************************/
|
||||||
ourLog.debug("Interceptor {} returned false, not continuing processing");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String requestFullPath = StringUtils.defaultString(theRequest.getRequestURI());
|
String requestFullPath = StringUtils.defaultString(theRequest.getRequestURI());
|
||||||
String servletPath = StringUtils.defaultString(theRequest.getServletPath());
|
String servletPath = StringUtils.defaultString(theRequest.getServletPath());
|
||||||
|
@ -551,14 +547,6 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
ourLog.trace("Context Path: {}", servletContextPath);
|
ourLog.trace("Context Path: {}", servletContextPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
String requestPath = getRequestPath(requestFullPath, servletContextPath, servletPath);
|
|
||||||
|
|
||||||
if (requestPath.length() > 0 && requestPath.charAt(0) == '/') {
|
|
||||||
requestPath = requestPath.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fhirServerBase = getServerBaseForRequest(theRequest);
|
|
||||||
|
|
||||||
String completeUrl;
|
String completeUrl;
|
||||||
Map<String, String[]> params = null;
|
Map<String, String[]> params = null;
|
||||||
if (StringUtils.isNotBlank(theRequest.getQueryString())) {
|
if (StringUtils.isNotBlank(theRequest.getQueryString())) {
|
||||||
|
@ -572,7 +560,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
if (isIgnoreServerParsedRequestParameters()) {
|
if (isIgnoreServerParsedRequestParameters()) {
|
||||||
String contentType = theRequest.getHeader(Constants.HEADER_CONTENT_TYPE);
|
String contentType = theRequest.getHeader(Constants.HEADER_CONTENT_TYPE);
|
||||||
if (theRequestType == RequestTypeEnum.POST && isNotBlank(contentType) && contentType.startsWith(Constants.CT_X_FORM_URLENCODED)) {
|
if (theRequestType == RequestTypeEnum.POST && isNotBlank(contentType) && contentType.startsWith(Constants.CT_X_FORM_URLENCODED)) {
|
||||||
String requestBody = new String(requestDetails.loadRequestContents(), Charsets.UTF_8);
|
String requestBody = new String(requestDetails.loadRequestContents(), Constants.CHARSET_UTF8);
|
||||||
params = UrlUtil.parseQueryStrings(theRequest.getQueryString(), requestBody);
|
params = UrlUtil.parseQueryStrings(theRequest.getQueryString(), requestBody);
|
||||||
} else if (theRequestType == RequestTypeEnum.GET) {
|
} else if (theRequestType == RequestTypeEnum.GET) {
|
||||||
params = UrlUtil.parseQueryString(theRequest.getQueryString());
|
params = UrlUtil.parseQueryString(theRequest.getQueryString());
|
||||||
|
@ -588,6 +576,28 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
|
|
||||||
requestDetails.setParameters(params);
|
requestDetails.setParameters(params);
|
||||||
|
|
||||||
|
/* *************************
|
||||||
|
* Notify interceptors about the incoming request
|
||||||
|
* *************************/
|
||||||
|
|
||||||
|
for (IServerInterceptor next : myInterceptors) {
|
||||||
|
boolean continueProcessing = next.incomingRequestPreProcessed(theRequest, theResponse);
|
||||||
|
if (!continueProcessing) {
|
||||||
|
ourLog.debug("Interceptor {} returned false, not continuing processing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String requestPath = getRequestPath(requestFullPath, servletContextPath, servletPath);
|
||||||
|
|
||||||
|
if (requestPath.length() > 0 && requestPath.charAt(0) == '/') {
|
||||||
|
requestPath = requestPath.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fhirServerBase = getServerBaseForRequest(theRequest);
|
||||||
|
|
||||||
|
|
||||||
IIdType id;
|
IIdType id;
|
||||||
populateRequestDetailsFromRequestPath(requestDetails, requestPath);
|
populateRequestDetailsFromRequestPath(requestDetails, requestPath);
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class JaxRsResponseDstu3Test {
|
||||||
boolean theAddContentLocationHeader = false;
|
boolean theAddContentLocationHeader = false;
|
||||||
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), bundle, theSummaryMode, 200, theAddContentLocationHeader, respondGzip, request);
|
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), bundle, theSummaryMode, 200, theAddContentLocationHeader, respondGzip, request);
|
||||||
assertEquals(200, result.getStatus());
|
assertEquals(200, result.getStatus());
|
||||||
assertEquals(Constants.CT_FHIR_JSON+Constants.CHARSET_UTF8_CTSUFFIX, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
assertEquals(Constants.CT_FHIR_JSON_NEW+Constants.CHARSET_UTF8_CTSUFFIX, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||||
assertTrue(result.getEntity().toString().contains("Patient"));
|
assertTrue(result.getEntity().toString().contains("Patient"));
|
||||||
assertTrue(result.getEntity().toString().contains("15"));
|
assertTrue(result.getEntity().toString().contains("15"));
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ public class JaxRsResponseDstu3Test {
|
||||||
boolean respondGzip = true;
|
boolean respondGzip = true;
|
||||||
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), createPatient(), theSummaryMode, 200, addContentLocationHeader, respondGzip, this.request);
|
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), createPatient(), theSummaryMode, 200, addContentLocationHeader, respondGzip, this.request);
|
||||||
assertEquals(200, result.getStatus());
|
assertEquals(200, result.getStatus());
|
||||||
assertEquals("application/json+fhir; charset=UTF-8", result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
assertEquals(Constants.CT_FHIR_JSON_NEW+"; charset=UTF-8", result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||||
assertTrue(result.getEntity().toString().contains("resourceType\": \"Patient"));
|
assertTrue(result.getEntity().toString().contains("resourceType\": \"Patient"));
|
||||||
assertTrue(result.getEntity().toString().contains("15"));
|
assertTrue(result.getEntity().toString().contains("15"));
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,16 @@ package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.NameValuePair;
|
import org.apache.http.NameValuePair;
|
||||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||||
|
@ -30,16 +35,37 @@ import org.junit.Test;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
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.TagList;
|
||||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Search;
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
import ca.uhn.fhir.rest.annotation.Sort;
|
import ca.uhn.fhir.rest.annotation.Sort;
|
||||||
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
import ca.uhn.fhir.rest.api.SortSpec;
|
import ca.uhn.fhir.rest.api.SortSpec;
|
||||||
|
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.param.StringAndListParam;
|
import ca.uhn.fhir.rest.param.StringAndListParam;
|
||||||
|
import ca.uhn.fhir.rest.server.SearchPostDstu3Test.ParamLoggingInterceptor;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter;
|
||||||
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.util.PortUtil;
|
import ca.uhn.fhir.util.PortUtil;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
|
||||||
public class SearchPostDstu3Test {
|
public class SearchPostDstu3Test {
|
||||||
|
|
||||||
|
public class ParamLoggingInterceptor extends InterceptorAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean incomingRequestPreProcessed(HttpServletRequest theRequest, HttpServletResponse theResponse) {
|
||||||
|
ourLog.info("Params: {}", theRequest.getParameterMap());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private static CloseableHttpClient ourClient;
|
private static CloseableHttpClient ourClient;
|
||||||
private static FhirContext ourCtx = FhirContext.forDstu3();
|
private static FhirContext ourCtx = FhirContext.forDstu3();
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchPostDstu3Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchPostDstu3Test.class);
|
||||||
|
@ -48,24 +74,32 @@ public class SearchPostDstu3Test {
|
||||||
private static String ourLastMethod;
|
private static String ourLastMethod;
|
||||||
private static SortSpec ourLastSortSpec;
|
private static SortSpec ourLastSortSpec;
|
||||||
private static StringAndListParam ourLastName;
|
private static StringAndListParam ourLastName;
|
||||||
|
private static RestfulServer ourServlet;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() {
|
public void before() {
|
||||||
ourLastMethod = null;
|
ourLastMethod = null;
|
||||||
ourLastSortSpec = null;
|
ourLastSortSpec = null;
|
||||||
ourLastName = null;
|
ourLastName = null;
|
||||||
|
|
||||||
|
for (IServerInterceptor next : new ArrayList<>(ourServlet.getInterceptors())) {
|
||||||
|
ourServlet.unregisterInterceptor(next);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See #411
|
* See #411
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithMixedParams() throws Exception {
|
public void testSearchWithMixedParamsNoInterceptorsYesParams() throws Exception {
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/_search?_format=application/xml");
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/_search?_format=application/fhir+json");
|
||||||
|
httpPost.addHeader("Cache-Control","no-cache");
|
||||||
List<NameValuePair> parameters = Lists.newArrayList();
|
List<NameValuePair> parameters = Lists.newArrayList();
|
||||||
parameters.add(new BasicNameValuePair("name", "Smith"));
|
parameters.add(new BasicNameValuePair("name", "Smith"));
|
||||||
httpPost.setEntity(new UrlEncodedFormEntity(parameters));
|
httpPost.setEntity(new UrlEncodedFormEntity(parameters));
|
||||||
|
|
||||||
|
ourLog.info("Outgoing post: {}", httpPost);
|
||||||
|
|
||||||
CloseableHttpResponse status = ourClient.execute(httpPost);
|
CloseableHttpResponse status = ourClient.execute(httpPost);
|
||||||
try {
|
try {
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
|
@ -77,7 +111,104 @@ public class SearchPostDstu3Test {
|
||||||
assertEquals(1, ourLastName.getValuesAsQueryTokens().size());
|
assertEquals(1, ourLastName.getValuesAsQueryTokens().size());
|
||||||
assertEquals(1, ourLastName.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().size());
|
assertEquals(1, ourLastName.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().size());
|
||||||
assertEquals("Smith", ourLastName.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().get(0).getValue());
|
assertEquals("Smith", ourLastName.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().get(0).getValue());
|
||||||
|
assertEquals(Constants.CT_FHIR_JSON_NEW, status.getEntity().getContentType().getValue().replaceAll(";.*", ""));
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See #411
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSearchWithMixedParamsNoInterceptorsNoParams() throws Exception {
|
||||||
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/_search");
|
||||||
|
httpPost.addHeader("Cache-Control","no-cache");
|
||||||
|
List<NameValuePair> parameters = Lists.newArrayList();
|
||||||
|
parameters.add(new BasicNameValuePair("name", "Smith"));
|
||||||
|
httpPost.setEntity(new UrlEncodedFormEntity(parameters));
|
||||||
|
|
||||||
|
ourLog.info("Outgoing post: {}", httpPost);
|
||||||
|
|
||||||
|
CloseableHttpResponse status = ourClient.execute(httpPost);
|
||||||
|
try {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
|
assertEquals("search", ourLastMethod);
|
||||||
|
assertEquals(null, ourLastSortSpec);
|
||||||
|
assertEquals(1, ourLastName.getValuesAsQueryTokens().size());
|
||||||
|
assertEquals(1, ourLastName.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().size());
|
||||||
|
assertEquals("Smith", ourLastName.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().get(0).getValue());
|
||||||
|
assertEquals(Constants.CT_FHIR_XML_NEW, status.getEntity().getContentType().getValue().replaceAll(";.*", ""));
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See #411
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSearchWithMixedParamsYesInterceptorsYesParams() throws Exception {
|
||||||
|
ourServlet.registerInterceptor(new ParamLoggingInterceptor());
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/_search?_format=application/fhir+json");
|
||||||
|
httpPost.addHeader("Cache-Control","no-cache");
|
||||||
|
List<NameValuePair> parameters = Lists.newArrayList();
|
||||||
|
parameters.add(new BasicNameValuePair("name", "Smith"));
|
||||||
|
httpPost.setEntity(new UrlEncodedFormEntity(parameters));
|
||||||
|
|
||||||
|
ourLog.info("Outgoing post: {}", httpPost);
|
||||||
|
|
||||||
|
CloseableHttpResponse status = ourClient.execute(httpPost);
|
||||||
|
try {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
|
assertEquals("search", ourLastMethod);
|
||||||
|
assertEquals(null, ourLastSortSpec);
|
||||||
|
assertEquals(1, ourLastName.getValuesAsQueryTokens().size());
|
||||||
|
assertEquals(1, ourLastName.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().size());
|
||||||
|
assertEquals("Smith", ourLastName.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().get(0).getValue());
|
||||||
|
assertEquals(Constants.CT_FHIR_JSON_NEW, status.getEntity().getContentType().getValue().replaceAll(";.*", ""));
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See #411
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSearchWithMixedParamsYesInterceptorsNoParams() throws Exception {
|
||||||
|
ourServlet.registerInterceptor(new ParamLoggingInterceptor());
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/_search");
|
||||||
|
httpPost.addHeader("Cache-Control","no-cache");
|
||||||
|
List<NameValuePair> parameters = Lists.newArrayList();
|
||||||
|
parameters.add(new BasicNameValuePair("name", "Smith"));
|
||||||
|
httpPost.setEntity(new UrlEncodedFormEntity(parameters));
|
||||||
|
|
||||||
|
ourLog.info("Outgoing post: {}", httpPost);
|
||||||
|
|
||||||
|
CloseableHttpResponse status = ourClient.execute(httpPost);
|
||||||
|
try {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
|
assertEquals("search", ourLastMethod);
|
||||||
|
assertEquals(null, ourLastSortSpec);
|
||||||
|
assertEquals(1, ourLastName.getValuesAsQueryTokens().size());
|
||||||
|
assertEquals(1, ourLastName.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().size());
|
||||||
|
assertEquals("Smith", ourLastName.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().get(0).getValue());
|
||||||
|
assertEquals(Constants.CT_FHIR_XML_NEW, status.getEntity().getContentType().getValue().replaceAll(";.*", ""));
|
||||||
} finally {
|
} finally {
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
}
|
}
|
||||||
|
@ -98,11 +229,12 @@ public class SearchPostDstu3Test {
|
||||||
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
|
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
|
||||||
|
|
||||||
ServletHandler proxyHandler = new ServletHandler();
|
ServletHandler proxyHandler = new ServletHandler();
|
||||||
RestfulServer servlet = new RestfulServer(ourCtx);
|
ourServlet = new RestfulServer(ourCtx);
|
||||||
servlet.setPagingProvider(new FifoMemoryPagingProvider(10));
|
ourServlet.setDefaultResponseEncoding(EncodingEnum.XML);
|
||||||
|
ourServlet.setPagingProvider(new FifoMemoryPagingProvider(10));
|
||||||
|
|
||||||
servlet.setResourceProviders(patientProvider);
|
ourServlet.setResourceProviders(patientProvider);
|
||||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
||||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||||
ourServer.setHandler(proxyHandler);
|
ourServer.setHandler(proxyHandler);
|
||||||
ourServer.start();
|
ourServer.start();
|
||||||
|
|
Loading…
Reference in New Issue