[ASTERIXDB-2976][API] Infra to ignore query parameters on POST/DELETE/PUT requests
- user model changes: no
- storage format changes: no
- interface changes: yes
Change-Id: Ib084b583bae914ae5bde5c7a70e0b8e5699407de
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/13664
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
Reviewed-by: Murtadha Hubail <mhubail@apache.org>
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/BasicAuthServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/BasicAuthServlet.java
index 9dc971a..061ceb9 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/BasicAuthServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/BasicAuthServlet.java
@@ -168,4 +168,9 @@
private static String generateRandomString(int size) {
return RandomStringUtils.randomAlphanumeric(size);
}
+
+ @Override
+ public boolean ignoresQueryParameters(HttpMethod method) {
+ return delegate.ignoresQueryParameters(method);
+ }
}
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
index db7ca7d..766a9d4 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
@@ -19,10 +19,11 @@
package org.apache.asterix.test.common;
+import static org.apache.asterix.api.http.server.QueryServiceRequestParameters.Parameter.CLIENT_ID;
+
import java.io.InputStream;
import java.net.URI;
import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
import java.util.BitSet;
import java.util.Iterator;
import java.util.List;
@@ -40,8 +41,6 @@
import org.apache.asterix.testframework.xml.TestCase;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.http.HttpResponse;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.methods.RequestBuilder;
import org.apache.hyracks.api.util.ExceptionUtils;
import org.junit.Assert;
@@ -55,8 +54,8 @@
Predicate<Integer> responseCodeValidator, boolean cancellable) throws Exception {
cancellable = cancellable && !containsClientContextID(str);
String clientContextId = UUID.randomUUID().toString();
- final List<TestCase.CompilationUnit.Parameter> newParams = cancellable
- ? upsertParam(params, "client_context_id", ParameterTypeEnum.STRING, clientContextId) : params;
+ final List<TestCase.CompilationUnit.Parameter> newParams =
+ cancellable ? upsertParam(params, CLIENT_ID.str(), ParameterTypeEnum.STRING, clientContextId) : params;
Callable<InputStream> query = () -> {
try {
return CancellationTestExecutor.super.executeQueryService(str, fmt, uri,
@@ -89,21 +88,10 @@
// Cancels a submitted query through the cancellation REST API.
private int cancelQuery(URI uri, List<TestCase.CompilationUnit.Parameter> params) throws Exception {
- HttpUriRequest method = constructDeleteMethodUrl(uri, params);
- HttpResponse response = executeHttpRequest(method);
+ HttpResponse response = executeHttpRequest(constructDeleteMethod(uri, params));
return response.getStatusLine().getStatusCode();
}
- // Constructs a HTTP DELETE request.
- private HttpUriRequest constructDeleteMethodUrl(URI uri, List<TestCase.CompilationUnit.Parameter> otherParams) {
- RequestBuilder builder = RequestBuilder.delete(uri);
- for (TestCase.CompilationUnit.Parameter param : otherParams) {
- builder.addParameter(param.getName(), param.getValue());
- }
- builder.setCharset(StandardCharsets.UTF_8);
- return builder.build();
- }
-
@Override
protected boolean isUnExpected(Exception e, List<String> expectedErrors, int numOfErrors, MutableInt queryCount,
boolean expectedSourceLoc) {
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/RebalanceCancellationTestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/RebalanceCancellationTestExecutor.java
index d35bfb7..758ba6f 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/RebalanceCancellationTestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/RebalanceCancellationTestExecutor.java
@@ -21,7 +21,6 @@
import java.io.File;
import java.net.URI;
-import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -35,8 +34,6 @@
import org.apache.asterix.testframework.xml.TestCase;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.http.HttpResponse;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.methods.RequestBuilder;
import org.apache.hyracks.api.util.ExceptionUtils;
import org.apache.logging.log4j.Level;
import org.junit.Assert;
@@ -102,18 +99,7 @@
// Cancels a submitted query through the cancellation REST API.
private int cancelQuery(URI uri, List<TestCase.CompilationUnit.Parameter> params) throws Exception {
- HttpUriRequest method = constructDeleteMethodUrl(uri, params);
- HttpResponse response = executeHttpRequest(method);
+ HttpResponse response = executeHttpRequest(constructDeleteMethod(uri, params));
return response.getStatusLine().getStatusCode();
}
-
- // Constructs a HTTP DELETE request.
- private HttpUriRequest constructDeleteMethodUrl(URI uri, List<TestCase.CompilationUnit.Parameter> otherParams) {
- RequestBuilder builder = RequestBuilder.delete(uri);
- for (TestCase.CompilationUnit.Parameter param : otherParams) {
- builder.addParameter(param.getName(), param.getValue());
- }
- builder.setCharset(StandardCharsets.UTF_8);
- return builder.build();
- }
}
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
index 95b77cc..7dc42b2 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
@@ -128,6 +128,7 @@
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.mutable.MutableInt;
+import org.apache.http.Consts;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
@@ -136,6 +137,7 @@
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
@@ -152,6 +154,7 @@
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.StandardHttpRequestRetryHandler;
+import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.apache.hyracks.algebricks.common.utils.Pair;
@@ -172,6 +175,8 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.util.RawValue;
+import io.netty.handler.codec.http.HttpMethod;
+
public class TestExecutor {
/*
@@ -929,20 +934,6 @@
return result;
}
- private HttpUriRequest constructHttpMethod(String statement, URI uri, String stmtParam, boolean postStmtAsParam,
- List<Parameter> otherParams) {
- String stmtParamName = (postStmtAsParam ? stmtParam : null);
- return constructPostMethodUrl(statement, uri, stmtParamName, otherParams);
- }
-
- private HttpUriRequest constructGetMethod(URI endpoint, List<Parameter> params) {
- RequestBuilder builder = RequestBuilder.get(endpoint);
- for (Parameter param : params) {
- builder.addParameter(param.getName(), param.getValue());
- }
- return builder.build();
- }
-
private boolean isMultipart(Parameter p) {
return p != null && (ParameterTypeEnum.MULTIPART_TEXT == p.getType()
|| ParameterTypeEnum.MULTIPART_BINARY == p.getType());
@@ -966,16 +957,30 @@
|| p.getType() == ParameterTypeEnum.MULTIPART_TEXT)
? Optional.of(MultipartEntityBuilder.create().setMode(HttpMultipartMode.STRICT))
: Optional.empty();
+ List<NameValuePair> parameters = new ArrayList<>();
for (Parameter param : params) {
if (isMultipart(param)) {
addMultipart(mPartBuilder.get(), param);
} else {
- builder.addParameter(param.getName(), param.getValue());
+ parameters.add(new BasicNameValuePair(param.getName(), param.getValue()));
}
}
builder.setCharset(UTF_8);
mPartBuilder.ifPresent(mpb -> builder.setEntity(mpb.build()));
- body.ifPresent(s -> builder.setEntity(new StringEntity(s, contentType)));
+ if (body.isPresent()) {
+ builder.addParameters(parameters.toArray(new NameValuePair[0]));
+ builder.setEntity(new StringEntity(body.get(), contentType));
+ } else if (mPartBuilder.isPresent()) {
+ builder.addParameters(parameters.toArray(new NameValuePair[0]));
+ builder.setEntity(mPartBuilder.get().build());
+ } else {
+ boolean formParams = HttpUtil.ignoreQueryParameters(HttpMethod.valueOf(method));
+ if (formParams) {
+ builder.setEntity(new UrlEncodedFormEntity(parameters, Consts.UTF_8));
+ } else {
+ builder.addParameters(parameters.toArray(new NameValuePair[0]));
+ }
+ }
return builder.build();
}
@@ -994,6 +999,27 @@
return method;
}
+ public static HttpUriRequest constructGetMethod(URI endpoint, List<Parameter> params) {
+ RequestBuilder builder = RequestBuilder.get(endpoint);
+ for (Parameter param : params) {
+ builder.addParameter(param.getName(), param.getValue());
+ }
+ return builder.build();
+ }
+
+ public static HttpUriRequest constructDeleteMethod(URI uri, List<Parameter> params) {
+ List<NameValuePair> form = new ArrayList<>();
+ for (Parameter param : params) {
+ form.add(new BasicNameValuePair(param.getName(), param.getValue()));
+ }
+ return constructDeleteRequest(uri, form);
+ }
+
+ public static HttpUriRequest constructDeleteRequest(URI uri, List<NameValuePair> params) {
+ RequestBuilder builder = RequestBuilder.delete(uri);
+ return builder.setEntity(new UrlEncodedFormEntity(params, Consts.UTF_8)).setCharset(UTF_8).build();
+ }
+
private HttpUriRequest constructPostMethod(URI uri, List<Parameter> params) {
RequestBuilder builder = RequestBuilder.post(uri);
for (Parameter param : params) {
@@ -1065,12 +1091,6 @@
TEXT_PLAIN_UTF8);
}
- public InputStream executeJSON(OutputFormat fmt, String method, URI uri, Predicate<Integer> responseCodeValidator)
- throws Exception {
- return executeJSON(fmt, method, uri, Collections.emptyList(), responseCodeValidator, Optional.empty(),
- TEXT_PLAIN_UTF8);
- }
-
private InputStream executeJSON(OutputFormat fmt, String method, URI uri, List<Parameter> params,
Predicate<Integer> responseCodeValidator, Optional<String> body, ContentType contentType) throws Exception {
HttpUriRequest request = buildRequest(method, uri, fmt, params, body, contentType);
@@ -1491,25 +1511,24 @@
final String mimeReqType = extractHttpRequestType(statement);
final String saveResponseVar = getResultVariable(statement);
ContentType contentType = mimeReqType != null ? ContentType.create(mimeReqType, UTF_8) : TEXT_PLAIN_UTF8;
- if (!body.isPresent()) {
+ if (body.isEmpty()) {
body = getBodyFromReference(statement, variableCtx);
}
final Pair<String, String> credentials = extractCredentials(statement);
InputStream resultStream;
+ URI uri;
if ("http".equals(extension)) {
- if (credentials != null) {
- resultStream = executeHttp(reqType, variablesReplaced, fmt, params, statusCodePredicate, body,
- contentType, credentials);
- } else {
- resultStream =
- executeHttp(reqType, variablesReplaced, fmt, params, statusCodePredicate, body, contentType);
- }
+ uri = createEndpointURI(variablesReplaced);
} else if ("uri".equals(extension)) {
- resultStream = executeURI(reqType, URI.create(variablesReplaced), fmt, params, statusCodePredicate, body,
- contentType);
+ uri = URI.create(variablesReplaced);
} else {
throw new IllegalArgumentException("Unexpected format for method " + reqType + ": " + extension);
}
+ if (credentials != null) {
+ resultStream = executeURI(reqType, uri, fmt, params, statusCodePredicate, body, contentType, credentials);
+ } else {
+ resultStream = executeURI(reqType, uri, fmt, params, statusCodePredicate, body, contentType);
+ }
if (extracResult) {
resultStream = ResultExtractor.extract(resultStream, UTF_8).getResult();
} else if (extractStatus) {
@@ -1530,8 +1549,8 @@
LOGGER.info("Diagnostic output: {}", IOUtils.toString(resultStream, UTF_8));
} else {
LOGGER.info("Unexpected output: {}", IOUtils.toString(resultStream, UTF_8));
- Assert.fail("no result file for " + testFile.toString() + "; queryCount: " + queryCount
- + ", filectxs.size: " + numResultFiles);
+ Assert.fail("no result file for " + testFile + "; queryCount: " + queryCount + ", filectxs.size: "
+ + numResultFiles);
}
} else {
writeOutputToFile(actualResultFile, resultStream);
@@ -1988,9 +2007,8 @@
}
public static Pair<String, String> extractCredentials(String statement) {
- List<Parameter> params = new ArrayList<>();
final Matcher m = HTTP_AUTH_PATTERN.matcher(statement);
- while (m.find()) {
+ if (m.find()) {
String username = m.group("username");
String password = m.group("password");
return new Pair<>(username, password);
@@ -2041,23 +2059,6 @@
}
}
- protected InputStream executeHttp(String ctxType, String endpoint, OutputFormat fmt, List<Parameter> params,
- Predicate<Integer> statusCodePredicate, Optional<String> body, ContentType contentType) throws Exception {
- URI uri = createEndpointURI(endpoint);
- return executeURI(ctxType, uri, fmt, params, statusCodePredicate, body, contentType);
- }
-
- private InputStream executeHttp(String ctxType, String endpoint, OutputFormat fmt, List<Parameter> params,
- Predicate<Integer> statusCodePredicate, Optional<String> body, ContentType contentType,
- Pair<String, String> credentials) throws Exception {
- URI uri = createEndpointURI(endpoint);
- return executeURI(ctxType, uri, fmt, params, statusCodePredicate, body, contentType, credentials);
- }
-
- private InputStream executeURI(String ctxType, URI uri, OutputFormat fmt, List<Parameter> params) throws Exception {
- return executeJSON(fmt, ctxType.toUpperCase(), uri, params);
- }
-
private InputStream executeURI(String ctxType, URI uri, OutputFormat fmt, List<Parameter> params,
Predicate<Integer> responseCodeValidator, Optional<String> body, ContentType contentType) throws Exception {
return executeJSON(fmt, ctxType.toUpperCase(), uri, params, responseCodeValidator, body, contentType);
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServlet.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServlet.java
index 515b95c..f3e099d 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServlet.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServlet.java
@@ -23,6 +23,8 @@
import org.apache.hyracks.http.server.HttpServer;
+import io.netty.handler.codec.http.HttpMethod;
+
/**
* Represents a component that handles IServlet requests
*/
@@ -62,4 +64,9 @@
*/
default void init() throws IOException {
}
+
+ /**
+ * @return {@code true} if the servlet ignores query parameters.
+ */
+ boolean ignoresQueryParameters(HttpMethod method);
}
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java
index ed567f5..ff23ac2 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java
@@ -205,4 +205,8 @@
return this.getClass().getSimpleName() + Arrays.toString(paths);
}
+ @Override
+ public boolean ignoresQueryParameters(HttpMethod method) {
+ return false;
+ }
}
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/BaseRequest.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/BaseRequest.java
index d4f57ea..c3c7dbc 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/BaseRequest.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/BaseRequest.java
@@ -43,9 +43,10 @@
protected final HttpScheme scheme;
protected final InetSocketAddress localAddress;
- public static IServletRequest create(ChannelHandlerContext ctx, FullHttpRequest request, HttpScheme scheme) {
- QueryStringDecoder decoder = new QueryStringDecoder(request.uri());
- Map<? extends CharSequence, List<String>> param = decoder.parameters();
+ public static IServletRequest create(ChannelHandlerContext ctx, FullHttpRequest request, HttpScheme scheme,
+ boolean ignoreQueryParameters) {
+ Map<? extends CharSequence, List<String>> param =
+ ignoreQueryParameters ? Collections.emptyMap() : new QueryStringDecoder(request.uri()).parameters();
InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress();
InetSocketAddress localAddress = (InetSocketAddress) ctx.channel().localAddress();
return new BaseRequest(request, localAddress, remoteAddress, param, scheme);
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/FormUrlEncodedRequest.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/FormUrlEncodedRequest.java
index de6ed72..fa7ef66 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/FormUrlEncodedRequest.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/FormUrlEncodedRequest.java
@@ -36,13 +36,16 @@
public class FormUrlEncodedRequest extends BaseRequest implements IServletRequest {
- public static IServletRequest create(ChannelHandlerContext ctx, FullHttpRequest request, HttpScheme scheme) {
+ public static IServletRequest create(ChannelHandlerContext ctx, FullHttpRequest request, HttpScheme scheme,
+ boolean ignoreQueryParameters) {
Charset charset = HttpUtil.getRequestCharset(request);
Map<String, List<String>> parameters = new LinkedHashMap<>();
URLEncodedUtils.parse(request.content().toString(charset), charset).forEach(
pair -> parameters.computeIfAbsent(pair.getName(), a -> new ArrayList<>()).add(pair.getValue()));
- new QueryStringDecoder(request.uri()).parameters()
- .forEach((name, value) -> parameters.computeIfAbsent(name, a -> new ArrayList<>()).addAll(value));
+ if (!ignoreQueryParameters) {
+ new QueryStringDecoder(request.uri()).parameters()
+ .forEach((name, value) -> parameters.computeIfAbsent(name, a -> new ArrayList<>()).addAll(value));
+ }
InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress();
InetSocketAddress localAddress = (InetSocketAddress) ctx.channel().localAddress();
return new FormUrlEncodedRequest(request, localAddress, remoteAddress, parameters, scheme);
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/HttpServerHandler.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/HttpServerHandler.java
index a7ace7a..b5adf2f 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/HttpServerHandler.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/HttpServerHandler.java
@@ -142,7 +142,8 @@
IServletRequest servletRequest;
try {
HttpScheme scheme = HttpUtil.getScheme(server, request);
- servletRequest = createServletRequest(ctx, request, scheme);
+ boolean ignoreParam = servlet.ignoresQueryParameters(request.method());
+ servletRequest = createServletRequest(ctx, request, scheme, ignoreParam);
} catch (IllegalArgumentException e) {
LOGGER.log(Level.WARN, "Failure Decoding Request", e);
respond(ctx, request, HttpResponseStatus.BAD_REQUEST);
@@ -171,8 +172,8 @@
}
protected IServletRequest createServletRequest(ChannelHandlerContext ctx, FullHttpRequest request,
- HttpScheme scheme) {
- return HttpUtil.toServletRequest(ctx, request, scheme);
+ HttpScheme scheme, boolean ignoreQueryParameters) {
+ return HttpUtil.toServletRequest(ctx, request, scheme, ignoreQueryParameters);
}
@Override
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java
index 1d5df5c..3bd4033 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java
@@ -71,10 +71,15 @@
}
public static IServletRequest toServletRequest(ChannelHandlerContext ctx, FullHttpRequest request,
- HttpScheme scheme) {
+ HttpScheme scheme, boolean ignoreQueryParameters) {
return ContentType.APPLICATION_X_WWW_FORM_URLENCODED.equals(getContentTypeOnly(request))
- && !HttpMethod.GET.equals(request.method()) ? FormUrlEncodedRequest.create(ctx, request, scheme)
- : BaseRequest.create(ctx, request, scheme);
+ && !HttpMethod.GET.equals(request.method())
+ ? FormUrlEncodedRequest.create(ctx, request, scheme, ignoreQueryParameters)
+ : BaseRequest.create(ctx, request, scheme, ignoreQueryParameters);
+ }
+
+ public static boolean ignoreQueryParameters(HttpMethod method) {
+ return HttpMethod.POST.equals(method) || HttpMethod.DELETE.equals(method) || HttpMethod.PUT.equals(method);
}
public static String getContentTypeOnly(IServletRequest request) {