[ASTERIXDB-2659][API] validate request parameters

- user model changes: yes
- storage format changes: no
- interface changes: no

Details:
- Return 400 BAD request for invalid request parameters.
- Changes in specifying the output format:
  HEADER "Accept": application/json;lossless=<BOOLEAN>, text/csv;header=absent/present, application/x-adm
  Request parameter "format": csv, json (and above mime types)
- when format is supplied in "Accept", only validate value of attribute if the mime is one of the above
  and the attribute name is one of the above (header & lossless).

Change-Id: Ia89fa3179cc36a73fe950f41eab1f0a9d17a541c
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/3767
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
Reviewed-by: Till Westmann <tillw@apache.org>
Contrib: Till Westmann <tillw@apache.org>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java
index 89ffcbe..3fdcc33 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/IStatementExecutor.java
@@ -24,9 +24,13 @@
 import java.io.Serializable;
 import java.rmi.RemoteException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 import org.apache.asterix.common.api.IResponsePrinter;
 import org.apache.asterix.common.exceptions.ACIDException;
@@ -62,15 +66,32 @@
         /**
          * Results are returned with the first response
          */
-        IMMEDIATE,
+        IMMEDIATE("immediate"),
         /**
          * Results are produced completely, but only a result handle is returned
          */
-        DEFERRED,
+        DEFERRED("deferred"),
         /**
          * A result handle is returned before the resutlts are complete
          */
-        ASYNC
+        ASYNC("async");
+
+        private static final Map<String, ResultDelivery> deliveryNames =
+                Collections.unmodifiableMap(Arrays.stream(ResultDelivery.values())
+                        .collect(Collectors.toMap(ResultDelivery::getName, Function.identity())));
+        private final String name;
+
+        ResultDelivery(String name) {
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public static ResultDelivery fromName(String name) {
+            return deliveryNames.get(name);
+        }
     }
 
     class ResultMetadata implements Serializable {
@@ -88,15 +109,32 @@
         private static final long serialVersionUID = 5885273238208454611L;
 
         public enum ProfileType {
-            COUNTS,
-            FULL
+            COUNTS("counts"),
+            FULL("timings"),
+            NONE("off");
+
+            private static final Map<String, ProfileType> profileNames = Collections.unmodifiableMap(Arrays
+                    .stream(ProfileType.values()).collect(Collectors.toMap(ProfileType::getName, Function.identity())));
+            private final String name;
+
+            ProfileType(String name) {
+                this.name = name;
+            }
+
+            public String getName() {
+                return name;
+            }
+
+            public static ProfileType fromName(String name) {
+                return profileNames.get(name);
+            }
         }
 
         private long count;
         private long size;
         private long processedObjects;
         private Profile profile;
-        private ProfileType type;
+        private ProfileType profileType;
         private long totalWarningsCount;
 
         public long getCount() {
@@ -141,12 +179,12 @@
             return profile != null ? profile.getProfile() : null;
         }
 
-        public ProfileType getType() {
-            return type;
+        public ProfileType getProfileType() {
+            return profileType;
         }
 
-        public void setType(ProfileType type) {
-            this.type = type;
+        public void setProfileType(ProfileType profileType) {
+            this.profileType = profileType;
         }
     }
 
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/CcQueryCancellationServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/CcQueryCancellationServlet.java
index 00aef9e..7ba2867 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/CcQueryCancellationServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/CcQueryCancellationServlet.java
@@ -21,7 +21,7 @@
 import java.io.IOException;
 import java.util.concurrent.ConcurrentMap;
 
-import org.apache.asterix.api.http.server.QueryServiceServlet.Parameter;
+import org.apache.asterix.api.http.server.QueryServiceRequestParameters.Parameter;
 import org.apache.asterix.common.api.IClientRequest;
 import org.apache.asterix.common.api.IRequestTracker;
 import org.apache.asterix.common.dataflow.ICcApplicationContext;
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryCancellationServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryCancellationServlet.java
index 053e042..617c937 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryCancellationServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryCancellationServlet.java
@@ -24,7 +24,7 @@
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.asterix.api.http.server.QueryServiceServlet.Parameter;
+import org.apache.asterix.api.http.server.QueryServiceRequestParameters.Parameter;
 import org.apache.asterix.app.message.CancelQueryRequest;
 import org.apache.asterix.app.message.CancelQueryResponse;
 import org.apache.asterix.common.messaging.api.INCMessageBroker;
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryServiceServlet.java
index acd6784..6953d1f 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryServiceServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryServiceServlet.java
@@ -32,7 +32,6 @@
 import org.apache.asterix.app.message.ExecuteStatementResponseMessage;
 import org.apache.asterix.app.result.ResponsePrinter;
 import org.apache.asterix.app.result.fields.NcResultPrinter;
-import org.apache.asterix.common.api.Duration;
 import org.apache.asterix.common.api.IApplicationContext;
 import org.apache.asterix.common.api.IRequestReference;
 import org.apache.asterix.common.config.GlobalConfig;
@@ -82,17 +81,14 @@
         MessageFuture responseFuture = ncMb.registerMessageFuture();
         final String handleUrl = getHandleUrl(param.getHost(), param.getPath(), delivery);
         try {
-            long timeout = ExecuteStatementRequestMessage.DEFAULT_NC_TIMEOUT_MILLIS;
-            if (param.getTimeout() != null && !param.getTimeout().trim().isEmpty()) {
-                timeout = TimeUnit.NANOSECONDS.toMillis(Duration.parseDurationStringToNanos(param.getTimeout()));
-            }
+            long timeout = param.getTimeout();
             int stmtCategoryRestrictionMask = org.apache.asterix.app.translator.RequestParameters
                     .getStatementCategoryRestrictionMask(param.isReadOnly());
-            ExecuteStatementRequestMessage requestMsg =
-                    new ExecuteStatementRequestMessage(ncCtx.getNodeId(), responseFuture.getFutureId(), queryLanguage,
-                            statementsText, sessionOutput.config(), resultProperties.getNcToCcResultProperties(),
-                            param.getClientContextID(), handleUrl, optionalParameters, statementParameters,
-                            param.isMultiStatement(), param.isProfile(), stmtCategoryRestrictionMask, requestReference);
+            ExecuteStatementRequestMessage requestMsg = new ExecuteStatementRequestMessage(ncCtx.getNodeId(),
+                    responseFuture.getFutureId(), queryLanguage, statementsText, sessionOutput.config(),
+                    resultProperties.getNcToCcResultProperties(), param.getClientContextID(), handleUrl,
+                    optionalParameters, statementParameters, param.isMultiStatement(), param.getProfileType(),
+                    stmtCategoryRestrictionMask, requestReference);
             execution.start();
             ncMb.sendMessageToPrimaryCC(requestMsg);
             try {
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
index 9664e80..6e70d27 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
@@ -19,42 +19,119 @@
 
 package org.apache.asterix.api.http.server;
 
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiFunction;
+import java.util.function.Function;
 
+import org.apache.asterix.common.api.Duration;
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.RuntimeDataException;
+import org.apache.asterix.translator.IStatementExecutor.ResultDelivery;
+import org.apache.asterix.translator.IStatementExecutor.Stats.ProfileType;
+import org.apache.asterix.translator.SessionConfig.OutputFormat;
+import org.apache.asterix.translator.SessionConfig.PlanFormat;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.http.HttpHeaders;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.server.utils.HttpUtil;
 import org.apache.hyracks.util.JSONUtil;
 
+import com.fasterxml.jackson.core.JsonParseException;
 import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableMap;
 
 public class QueryServiceRequestParameters {
 
-    public static final long DEFAULT_MAX_WARNINGS = 0L;
+    public enum Parameter {
+        ARGS("args"),
+        STATEMENT("statement"),
+        FORMAT("format"),
+        CLIENT_ID("client_context_id"),
+        PRETTY("pretty"),
+        MODE("mode"),
+        TIMEOUT("timeout"),
+        PLAN_FORMAT("plan-format"),
+        MAX_RESULT_READS("max-result-reads"),
+        EXPRESSION_TREE("expression-tree"),
+        REWRITTEN_EXPRESSION_TREE("rewritten-expression-tree"),
+        LOGICAL_PLAN("logical-plan"),
+        OPTIMIZED_LOGICAL_PLAN("optimized-logical-plan"),
+        PARSE_ONLY("parse-only"),
+        READ_ONLY("readonly"),
+        JOB("job"),
+        PROFILE("profile"),
+        SIGNATURE("signature"),
+        MULTI_STATEMENT("multi-statement"),
+        MAX_WARNINGS("max-warnings");
+
+        private final String str;
+
+        Parameter(String str) {
+            this.str = str;
+        }
+
+        public String str() {
+            return str;
+        }
+    }
+
+    private enum Attribute {
+        HEADER("header"),
+        LOSSLESS("lossless");
+
+        private final String str;
+
+        Attribute(String str) {
+            this.str = str;
+        }
+
+        public String str() {
+            return str;
+        }
+    }
+
+    private static final Map<String, PlanFormat> planFormats = ImmutableMap.of(HttpUtil.ContentType.JSON,
+            PlanFormat.JSON, "clean_json", PlanFormat.JSON, "string", PlanFormat.STRING);
+    private static final Map<String, Boolean> booleanValues =
+            ImmutableMap.of(Boolean.TRUE.toString(), Boolean.TRUE, Boolean.FALSE.toString(), Boolean.FALSE);
+    private static final Map<String, Boolean> csvHeaderValues =
+            ImmutableMap.of("present", Boolean.TRUE, "absent", Boolean.FALSE);
     private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
 
     private String host;
     private String path;
     private String statement;
-    private String format;
-    private String timeout;
-    private boolean pretty;
     private String clientContextID;
-    private String mode;
-    private String maxResultReads;
-    private String planFormat;
-    private Map<String, JsonNode> statementParams;
-    private boolean expressionTree;
-    private boolean parseOnly; //don't execute; simply check for syntax correctness and named parameters.
-    private boolean readOnly; // only allow statements that belong to QUERY category, fail for all other categories.
-    private boolean rewrittenExpressionTree;
-    private boolean logicalPlan;
-    private boolean optimizedLogicalPlan;
-    private boolean job;
-    private boolean profile;
-    private boolean signature;
-    private boolean multiStatement;
-    private long maxWarnings = DEFAULT_MAX_WARNINGS;
+    private OutputFormat format = OutputFormat.CLEAN_JSON;
+    private ResultDelivery mode = ResultDelivery.IMMEDIATE;
+    private PlanFormat planFormat = PlanFormat.JSON;
+    private ProfileType profileType = ProfileType.COUNTS;
+    private Map<String, JsonNode> statementParams = null;
+    private boolean pretty = false;
+    private boolean expressionTree = false;
+    private boolean parseOnly = false; // don't execute; simply check for syntax correctness and named parameters.
+    private boolean readOnly = false; // only allow statements belonging to QUERY category, fail for other categories.
+    private boolean rewrittenExpressionTree = false;
+    private boolean logicalPlan = false;
+    private boolean optimizedLogicalPlan = false;
+    private boolean job = false;
+    private boolean isCSVWithHeader = false;
+    private boolean signature = true;
+    private boolean multiStatement = true;
+    private long timeout = TimeUnit.MILLISECONDS.toMillis(Long.MAX_VALUE);
+    private long maxResultReads = 1L;
+    private long maxWarnings = 0L;
 
     public String getHost() {
         return host;
@@ -80,19 +157,24 @@
         this.statement = statement;
     }
 
-    public String getFormat() {
+    public OutputFormat getFormat() {
         return format;
     }
 
-    public void setFormat(String format) {
-        this.format = format;
+    public void setFormat(Pair<OutputFormat, Boolean> formatAndHeader) {
+        Objects.requireNonNull(formatAndHeader);
+        Objects.requireNonNull(formatAndHeader.getLeft());
+        this.format = formatAndHeader.getLeft();
+        if (format == OutputFormat.CSV) {
+            isCSVWithHeader = formatAndHeader.getRight();
+        }
     }
 
-    public String getTimeout() {
+    public long getTimeout() {
         return timeout;
     }
 
-    public void setTimeout(String timeout) {
+    public void setTimeout(long timeout) {
         this.timeout = timeout;
     }
 
@@ -112,27 +194,29 @@
         this.clientContextID = clientContextID;
     }
 
-    public String getMode() {
+    public ResultDelivery getMode() {
         return mode;
     }
 
-    public void setMode(String mode) {
+    public void setMode(ResultDelivery mode) {
+        Objects.requireNonNull(mode);
         this.mode = mode;
     }
 
-    public String getMaxResultReads() {
+    public long getMaxResultReads() {
         return maxResultReads;
     }
 
-    public void setMaxResultReads(String maxResultReads) {
+    public void setMaxResultReads(long maxResultReads) {
         this.maxResultReads = maxResultReads;
     }
 
-    public String getPlanFormat() {
+    public PlanFormat getPlanFormat() {
         return planFormat;
     }
 
-    public void setPlanFormat(String planFormat) {
+    public void setPlanFormat(PlanFormat planFormat) {
+        Objects.requireNonNull(planFormat);
         this.planFormat = planFormat;
     }
 
@@ -200,12 +284,17 @@
         this.job = job;
     }
 
-    public void setProfile(boolean profile) {
-        this.profile = profile;
+    public void setProfileType(ProfileType profileType) {
+        Objects.requireNonNull(profileType);
+        this.profileType = profileType;
     }
 
-    public boolean isProfile() {
-        return profile;
+    public ProfileType getProfileType() {
+        return profileType;
+    }
+
+    public boolean isCSVWithHeader() {
+        return format == OutputFormat.CSV && isCSVWithHeader;
     }
 
     public boolean isSignature() {
@@ -238,18 +327,18 @@
         object.put("path", path);
         object.put("statement", statement != null ? JSONUtil.escape(new StringBuilder(), statement).toString() : null);
         object.put("pretty", pretty);
-        object.put("mode", mode);
+        object.put("mode", mode.getName());
         object.put("clientContextID", clientContextID);
-        object.put("format", format);
+        object.put("format", format.toString());
         object.put("timeout", timeout);
         object.put("maxResultReads", maxResultReads);
-        object.put("planFormat", planFormat);
+        object.put("planFormat", planFormat.toString());
         object.put("expressionTree", expressionTree);
         object.put("rewrittenExpressionTree", rewrittenExpressionTree);
         object.put("logicalPlan", logicalPlan);
         object.put("optimizedLogicalPlan", optimizedLogicalPlan);
         object.put("job", job);
-        object.put("profile", profile);
+        object.put("profile", profileType.getName());
         object.put("signature", signature);
         object.put("multiStatement", multiStatement);
         object.put("parseOnly", parseOnly);
@@ -272,4 +361,266 @@
             return e.toString();
         }
     }
+
+    public void setParameters(QueryServiceServlet servlet, IServletRequest request, Map<String, String> optionalParams)
+            throws IOException {
+        setHost(servlet.host(request));
+        setPath(servlet.servletPath(request));
+        String contentType = HttpUtil.getContentTypeOnly(request);
+        try {
+            if (HttpUtil.ContentType.APPLICATION_JSON.equals(contentType)) {
+                setParamFromJSON(request, optionalParams);
+            } else {
+                setParamFromRequest(request, optionalParams);
+            }
+        } catch (JsonParseException | JsonMappingException e) {
+            throw new RuntimeDataException(ErrorCode.INVALID_REQ_JSON_VAL);
+        }
+    }
+
+    private void setParamFromJSON(IServletRequest request, Map<String, String> optionalParameters) throws IOException {
+        JsonNode jsonRequest = OBJECT_MAPPER.readTree(HttpUtil.getRequestBody(request));
+        setParams(jsonRequest, request.getHeader(HttpHeaders.ACCEPT), QueryServiceRequestParameters::getParameter);
+        setStatementParams(getOptStatementParameters(jsonRequest, jsonRequest.fieldNames(), JsonNode::get, v -> v));
+        setJsonOptionalParameters(jsonRequest, optionalParameters);
+    }
+
+    private void setParamFromRequest(IServletRequest request, Map<String, String> optionalParameters)
+            throws IOException {
+        setParams(request, request.getHeader(HttpHeaders.ACCEPT), IServletRequest::getParameter);
+        setStatementParams(getOptStatementParameters(request, request.getParameterNames().iterator(),
+                IServletRequest::getParameter, OBJECT_MAPPER::readTree));
+        setOptionalParameters(request, optionalParameters);
+    }
+
+    private <Req> void setParams(Req req, String acceptHeader, BiFunction<Req, String, String> valGetter)
+            throws HyracksDataException {
+        setStatement(valGetter.apply(req, Parameter.STATEMENT.str()));
+        setClientContextID(valGetter.apply(req, Parameter.CLIENT_ID.str()));
+
+        setFormatIfExists(req, acceptHeader, Parameter.FORMAT.str(), valGetter);
+        setMode(parseIfExists(req, Parameter.MODE.str(), valGetter, getMode(), ResultDelivery::fromName));
+        setPlanFormat(parseIfExists(req, Parameter.PLAN_FORMAT.str(), valGetter, getPlanFormat(), planFormats::get));
+        setProfileType(parseIfExists(req, Parameter.PROFILE.str(), valGetter, getProfileType(), ProfileType::fromName));
+
+        setTimeout(parseTime(req, Parameter.TIMEOUT.str(), valGetter, getTimeout()));
+        setMaxResultReads(parseLong(req, Parameter.MAX_RESULT_READS.str(), valGetter, getMaxResultReads()));
+        setMaxWarnings(parseLong(req, Parameter.MAX_WARNINGS.str(), valGetter, getMaxWarnings()));
+
+        setPretty(parseBoolean(req, Parameter.PRETTY.str(), valGetter, isPretty()));
+        setExpressionTree(parseBoolean(req, Parameter.EXPRESSION_TREE.str(), valGetter, isExpressionTree()));
+        setRewrittenExpressionTree(
+                parseBoolean(req, Parameter.REWRITTEN_EXPRESSION_TREE.str(), valGetter, isRewrittenExpressionTree()));
+        setLogicalPlan(parseBoolean(req, Parameter.LOGICAL_PLAN.str(), valGetter, isLogicalPlan()));
+        setParseOnly(parseBoolean(req, Parameter.PARSE_ONLY.str(), valGetter, isParseOnly()));
+        setReadOnly(parseBoolean(req, Parameter.READ_ONLY.str(), valGetter, isReadOnly()));
+        setOptimizedLogicalPlan(
+                parseBoolean(req, Parameter.OPTIMIZED_LOGICAL_PLAN.str(), valGetter, isOptimizedLogicalPlan()));
+        setMultiStatement(parseBoolean(req, Parameter.MULTI_STATEMENT.str(), valGetter, isMultiStatement()));
+        setJob(parseBoolean(req, Parameter.JOB.str(), valGetter, isJob()));
+        setSignature(parseBoolean(req, Parameter.SIGNATURE.str(), valGetter, isSignature()));
+    }
+
+    protected void setJsonOptionalParameters(JsonNode jsonRequest, Map<String, String> optionalParameters)
+            throws HyracksDataException {
+        // allows extensions to set extra parameters
+    }
+
+    protected void setOptionalParameters(IServletRequest request, Map<String, String> optionalParameters)
+            throws HyracksDataException {
+        // allows extensions to set extra parameters
+    }
+
+    @FunctionalInterface
+    interface CheckedFunction<I, O> {
+        O apply(I requestParamValue) throws IOException;
+    }
+
+    private <R, P> Map<String, JsonNode> getOptStatementParameters(R request, Iterator<String> paramNameIter,
+            BiFunction<R, String, P> paramValueAccessor, CheckedFunction<P, JsonNode> paramValueParser)
+            throws IOException {
+        Map<String, JsonNode> result = null;
+        while (paramNameIter.hasNext()) {
+            String paramName = paramNameIter.next();
+            String stmtParamName = extractStatementParameterName(paramName);
+            if (stmtParamName != null) {
+                if (result == null) {
+                    result = new HashMap<>();
+                }
+                P paramValue = paramValueAccessor.apply(request, paramName);
+                JsonNode stmtParamValue = paramValueParser.apply(paramValue);
+                result.put(stmtParamName, stmtParamValue);
+            } else if (Parameter.ARGS.str().equals(toLower(paramName))) {
+                if (result == null) {
+                    result = new HashMap<>();
+                }
+                P paramValue = paramValueAccessor.apply(request, paramName);
+                JsonNode stmtParamValue = paramValueParser.apply(paramValue);
+                if (!stmtParamValue.isArray()) {
+                    throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, paramName, stmtParamValue.asText());
+                }
+                for (int i = 0, ln = stmtParamValue.size(); i < ln; i++) {
+                    result.put(String.valueOf(i + 1), stmtParamValue.get(i));
+                }
+            }
+        }
+        return result;
+    }
+
+    public static String extractStatementParameterName(String name) {
+        int ln = name.length();
+        if ((ln == 2 || isStatementParameterNameRest(name, 2)) && name.charAt(0) == '$'
+                && Character.isLetter(name.charAt(1))) {
+            return name.substring(1);
+        }
+        return null;
+    }
+
+    private static boolean isStatementParameterNameRest(CharSequence input, int startIndex) {
+        int i = startIndex;
+        for (int ln = input.length(); i < ln; i++) {
+            char c = input.charAt(i);
+            boolean ok = c == '_' || Character.isLetterOrDigit(c);
+            if (!ok) {
+                return false;
+            }
+        }
+        return i > startIndex;
+    }
+
+    private static <R> boolean parseBoolean(R request, String parameterName,
+            BiFunction<R, String, String> valueAccessor, boolean defaultVal) throws HyracksDataException {
+        String value = toLower(valueAccessor.apply(request, parameterName));
+        if (value == null) {
+            return defaultVal;
+        }
+        Boolean booleanVal = booleanValues.get(value);
+        if (booleanVal == null) {
+            throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, parameterName, value);
+
+        }
+        return booleanVal.booleanValue();
+    }
+
+    private static <R> long parseLong(R request, String parameterName, BiFunction<R, String, String> valueAccessor,
+            long defaultVal) throws HyracksDataException {
+        String value = toLower(valueAccessor.apply(request, parameterName));
+        if (value == null) {
+            return defaultVal;
+        }
+        try {
+            return Long.parseLong(value);
+        } catch (NumberFormatException e) {
+            throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, parameterName, value);
+        }
+    }
+
+    private static <R> long parseTime(R request, String parameterName, BiFunction<R, String, String> valueAccessor,
+            long def) throws HyracksDataException {
+        String value = toLower(valueAccessor.apply(request, parameterName));
+        if (value == null) {
+            return def;
+        }
+        try {
+            return TimeUnit.NANOSECONDS.toMillis(Duration.parseDurationStringToNanos(value));
+        } catch (HyracksDataException e) {
+            throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, parameterName, value);
+        }
+    }
+
+    private <R> void setFormatIfExists(R request, String acceptHeader, String parameterName,
+            BiFunction<R, String, String> valueAccessor) throws HyracksDataException {
+        Pair<OutputFormat, Boolean> formatAndHeader =
+                parseFormatIfExists(request, acceptHeader, parameterName, valueAccessor);
+        if (formatAndHeader != null) {
+            setFormat(formatAndHeader);
+        }
+    }
+
+    protected <R> Pair<OutputFormat, Boolean> parseFormatIfExists(R request, String acceptHeader, String parameterName,
+            BiFunction<R, String, String> valueAccessor) throws HyracksDataException {
+        String value = toLower(valueAccessor.apply(request, parameterName));
+        if (value == null) {
+            // if no value is provided in request parameter "format", then check "Accept" parameter in HEADER
+            // and only validate attribute val if mime and attribute name are known, e.g. application/json;lossless=?
+            if (acceptHeader != null) {
+                String[] mimeTypes = StringUtils.split(acceptHeader, ',');
+                for (int i = 0, size = mimeTypes.length; i < size; i++) {
+                    Pair<OutputFormat, Boolean> formatAndHeader = fromMime(mimeTypes[i]);
+                    if (formatAndHeader != null) {
+                        return formatAndHeader;
+                    }
+                }
+            }
+            return null;
+        }
+        // checking value in request parameter "format"
+        if (value.equals(HttpUtil.ContentType.CSV)) {
+            return Pair.of(OutputFormat.CSV, Boolean.FALSE);
+        } else if (value.equals(HttpUtil.ContentType.JSON)) {
+            return Pair.of(OutputFormat.CLEAN_JSON, Boolean.FALSE);
+        } else {
+            Pair<OutputFormat, Boolean> format = fromMime(value);
+            if (format == null) {
+                throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, parameterName, value);
+            }
+            return format;
+        }
+    }
+
+    private static Pair<OutputFormat, Boolean> fromMime(String mimeType) throws HyracksDataException {
+        // find the first match, no preferences for now
+        String[] mimeSplits = StringUtils.split(mimeType, ';');
+        if (mimeSplits.length > 0) {
+            String format = mimeSplits[0].toLowerCase().trim();
+            if (format.equals(HttpUtil.ContentType.APPLICATION_JSON)) {
+                return Pair.of(hasValue(mimeSplits, Attribute.LOSSLESS.str(), booleanValues)
+                        ? OutputFormat.LOSSLESS_JSON : OutputFormat.CLEAN_JSON, Boolean.FALSE);
+            } else if (format.equals(HttpUtil.ContentType.TEXT_CSV)) {
+                return Pair.of(OutputFormat.CSV,
+                        hasValue(mimeSplits, Attribute.HEADER.str(), csvHeaderValues) ? Boolean.TRUE : Boolean.FALSE);
+            } else if (format.equals(HttpUtil.ContentType.APPLICATION_ADM)) {
+                return Pair.of(OutputFormat.ADM, Boolean.FALSE);
+            }
+        }
+        return null;
+    }
+
+    private static boolean hasValue(String[] mimeTypeParts, String attributeName, Map<String, Boolean> allowedValues)
+            throws HyracksDataException {
+        for (int i = 1, size = mimeTypeParts.length; i < size; i++) {
+            String[] attNameAndVal = StringUtils.split(mimeTypeParts[i], '=');
+            if (attNameAndVal.length == 2 && attNameAndVal[0].toLowerCase().trim().equals(attributeName)) {
+                Boolean value = allowedValues.get(attNameAndVal[1].toLowerCase().trim());
+                if (value == null) {
+                    throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, attributeName, attNameAndVal[1]);
+                }
+                return value.booleanValue();
+            }
+        }
+        return false;
+    }
+
+    private static <Req, Param> Param parseIfExists(Req request, String parameterName,
+            BiFunction<Req, String, String> valueAccessor, Param defaultVal, Function<String, Param> parseFunction)
+            throws HyracksDataException {
+        String valueInRequest = toLower(valueAccessor.apply(request, parameterName));
+        if (valueInRequest == null) {
+            return defaultVal;
+        }
+        Param resultValue = parseFunction.apply(valueInRequest);
+        if (resultValue == null) {
+            throw new RuntimeDataException(ErrorCode.INVALID_REQ_PARAM_VAL, parameterName, valueInRequest);
+        }
+        return resultValue;
+    }
+
+    protected static String getParameter(JsonNode node, String parameter) {
+        final JsonNode value = node.get(parameter);
+        return value != null ? value.asText() : null;
+    }
+
+    protected static String toLower(String s) {
+        return s != null ? s.toLowerCase() : s;
+    }
 }
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
index 72557be..63678f8 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
@@ -19,6 +19,8 @@
 package org.apache.asterix.api.http.server;
 
 import static org.apache.asterix.common.exceptions.ErrorCode.ASTERIX;
+import static org.apache.asterix.common.exceptions.ErrorCode.INVALID_REQ_JSON_VAL;
+import static org.apache.asterix.common.exceptions.ErrorCode.INVALID_REQ_PARAM_VAL;
 import static org.apache.asterix.common.exceptions.ErrorCode.NO_STATEMENT_PROVIDED;
 import static org.apache.asterix.common.exceptions.ErrorCode.REJECT_BAD_CLUSTER_STATE;
 import static org.apache.asterix.common.exceptions.ErrorCode.REJECT_NODE_UNREGISTERED;
@@ -33,13 +35,10 @@
 import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentMap;
-import java.util.function.BiFunction;
 import java.util.function.Function;
 
 import org.apache.asterix.algebra.base.ILangExtension;
@@ -65,7 +64,6 @@
 import org.apache.asterix.common.api.ICodedMessage;
 import org.apache.asterix.common.api.IReceptionist;
 import org.apache.asterix.common.api.IRequestReference;
-import org.apache.asterix.common.config.GlobalConfig;
 import org.apache.asterix.common.context.IStorageComponentProvider;
 import org.apache.asterix.common.dataflow.ICcApplicationContext;
 import org.apache.asterix.common.exceptions.CompilationException;
@@ -97,14 +95,9 @@
 import org.apache.hyracks.http.api.IServletResponse;
 import org.apache.hyracks.http.server.utils.HttpUtil;
 import org.apache.hyracks.util.LogRedactionUtil;
-import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.JsonNode;
-
 import io.netty.handler.codec.http.HttpResponseStatus;
 
 public class QueryServiceServlet extends AbstractQueryApiServlet {
@@ -154,54 +147,6 @@
         response.setStatus(HttpResponseStatus.OK);
     }
 
-    public enum Parameter {
-        ARGS("args"),
-        STATEMENT("statement"),
-        FORMAT("format"),
-        CLIENT_ID("client_context_id"),
-        PRETTY("pretty"),
-        MODE("mode"),
-        TIMEOUT("timeout"),
-        PLAN_FORMAT("plan-format"),
-        MAX_RESULT_READS("max-result-reads"),
-        EXPRESSION_TREE("expression-tree"),
-        REWRITTEN_EXPRESSION_TREE("rewritten-expression-tree"),
-        LOGICAL_PLAN("logical-plan"),
-        OPTIMIZED_LOGICAL_PLAN("optimized-logical-plan"),
-        PARSE_ONLY("parse-only"),
-        READ_ONLY("readonly"),
-        JOB("job"),
-        PROFILE("profile"),
-        SIGNATURE("signature"),
-        MULTI_STATEMENT("multi-statement"),
-        MAX_WARNINGS("max-warnings");
-
-        private final String str;
-
-        Parameter(String str) {
-            this.str = str;
-        }
-
-        public String str() {
-            return str;
-        }
-    }
-
-    private enum Attribute {
-        HEADER("header"),
-        LOSSLESS("lossless");
-
-        private final String str;
-
-        Attribute(String str) {
-            this.str = str;
-        }
-
-        public String str() {
-            return str;
-        }
-    }
-
     protected static final class RequestExecutionState {
         private long execStart = -1;
         private long execEnd = -1;
@@ -242,44 +187,6 @@
         }
     }
 
-    private static String getParameterValue(String content, String attribute) {
-        if (content == null || attribute == null) {
-            return null;
-        }
-        int sc = content.indexOf(';');
-        if (sc < 0) {
-            return null;
-        }
-        int eq = content.indexOf('=', sc + 1);
-        if (eq < 0) {
-            return null;
-        }
-        if (content.substring(sc + 1, eq).trim().equalsIgnoreCase(attribute)) {
-            return content.substring(eq + 1).trim().toLowerCase();
-        }
-        return null;
-    }
-
-    private static String toLower(String s) {
-        return s != null ? s.toLowerCase() : s;
-    }
-
-    private static SessionConfig.OutputFormat getFormat(String format) {
-        if (format != null) {
-            if (format.startsWith(HttpUtil.ContentType.CSV)) {
-                return SessionConfig.OutputFormat.CSV;
-            }
-            if (format.equals(HttpUtil.ContentType.APPLICATION_ADM)) {
-                return SessionConfig.OutputFormat.ADM;
-            }
-            if (isJsonFormat(format)) {
-                return Boolean.parseBoolean(getParameterValue(format, Attribute.LOSSLESS.str()))
-                        ? SessionConfig.OutputFormat.LOSSLESS_JSON : SessionConfig.OutputFormat.CLEAN_JSON;
-            }
-        }
-        return SessionConfig.OutputFormat.CLEAN_JSON;
-    }
-
     private static SessionOutput createSessionOutput(PrintWriter resultWriter) {
         SessionOutput.ResultDecorator resultPrefix = ResultUtil.createPreResultDecorator();
         SessionOutput.ResultDecorator resultPostfix = ResultUtil.createPostResultDecorator();
@@ -288,162 +195,9 @@
         return new SessionOutput(sessionConfig, resultWriter, resultPrefix, resultPostfix, null, appendStatus);
     }
 
-    protected String getOptText(JsonNode node, Parameter parameter) {
-        return getOptText(node, parameter.str());
-    }
-
-    protected String getOptText(JsonNode node, String fieldName) {
-        final JsonNode value = node.get(fieldName);
-        return value != null ? value.asText() : null;
-    }
-
-    protected boolean getOptBoolean(JsonNode node, Parameter parameter, boolean defaultValue) {
-        return getOptBoolean(node, parameter.str(), defaultValue);
-    }
-
-    protected boolean getOptBoolean(JsonNode node, String fieldName, boolean defaultValue) {
-        final JsonNode value = node.get(fieldName);
-        return value != null ? value.asBoolean() : defaultValue;
-    }
-
-    protected long getOptLong(JsonNode node, Parameter parameter, long defaultValue) {
-        final JsonNode value = node.get(parameter.str);
-        return value != null ? Integer.parseInt(value.asText()) : defaultValue;
-    }
-
-    protected long getOptLong(IServletRequest request, Parameter parameter, long defaultValue) {
-        String value = getParameter(request, parameter);
-        return value == null ? defaultValue : Integer.parseInt(value);
-    }
-
-    protected boolean getOptBoolean(IServletRequest request, Parameter parameter, boolean defaultValue) {
-        String value = getParameter(request, parameter);
-        return value == null ? defaultValue : Boolean.parseBoolean(value);
-    }
-
-    protected String getParameter(IServletRequest request, Parameter parameter) {
-        return request.getParameter(parameter.str());
-    }
-
-    @FunctionalInterface
-    interface CheckedFunction<I, O> {
-        O apply(I requestParamValue) throws IOException;
-    }
-
-    private <R, P> Map<String, JsonNode> getOptStatementParameters(R request, Iterator<String> paramNameIter,
-            BiFunction<R, String, P> paramValueAccessor, CheckedFunction<P, JsonNode> paramValueParser)
-            throws IOException {
-        Map<String, JsonNode> result = null;
-        while (paramNameIter.hasNext()) {
-            String paramName = paramNameIter.next();
-            String stmtParamName = extractStatementParameterName(paramName);
-            if (stmtParamName != null) {
-                if (result == null) {
-                    result = new HashMap<>();
-                }
-                P paramValue = paramValueAccessor.apply(request, paramName);
-                JsonNode stmtParamValue = paramValueParser.apply(paramValue);
-                result.put(stmtParamName, stmtParamValue);
-            } else if (Parameter.ARGS.str().equals(paramName)) {
-                if (result == null) {
-                    result = new HashMap<>();
-                }
-                P paramValue = paramValueAccessor.apply(request, paramName);
-                JsonNode stmtParamValue = paramValueParser.apply(paramValue);
-                if (stmtParamValue.isArray()) {
-                    for (int i = 0, ln = stmtParamValue.size(); i < ln; i++) {
-                        result.put(String.valueOf(i + 1), stmtParamValue.get(i));
-                    }
-                }
-            }
-        }
-        return result;
-    }
-
     protected void setRequestParam(IServletRequest request, QueryServiceRequestParameters param,
             Map<String, String> optionalParams) throws IOException, AlgebricksException {
-        param.setHost(host(request));
-        param.setPath(servletPath(request));
-        String contentType = HttpUtil.getContentTypeOnly(request);
-        if (HttpUtil.ContentType.APPLICATION_JSON.equals(contentType)) {
-            try {
-                setParamFromJSON(request, param, optionalParams);
-            } catch (JsonParseException | JsonMappingException e) {
-                // if the JSON parsing fails, the statement is empty and we get an empty statement error
-                GlobalConfig.ASTERIX_LOGGER.log(Level.ERROR, e.getMessage(), e);
-            }
-        } else {
-            setParamFromRequest(request, param, optionalParams);
-        }
-    }
-
-    private void setParamFromJSON(IServletRequest request, QueryServiceRequestParameters param,
-            Map<String, String> optionalParameters) throws IOException {
-        JsonNode jsonRequest = OBJECT_MAPPER.readTree(HttpUtil.getRequestBody(request));
-        param.setStatement(getOptText(jsonRequest, Parameter.STATEMENT));
-        param.setFormat(toLower(getOptText(jsonRequest, Parameter.FORMAT)));
-        param.setPretty(getOptBoolean(jsonRequest, Parameter.PRETTY, false));
-        param.setMode(toLower(getOptText(jsonRequest, Parameter.MODE)));
-        param.setClientContextID(getOptText(jsonRequest, Parameter.CLIENT_ID));
-        param.setTimeout(getOptText(jsonRequest, Parameter.TIMEOUT));
-        param.setMaxResultReads(getOptText(jsonRequest, Parameter.MAX_RESULT_READS));
-        param.setPlanFormat(getOptText(jsonRequest, Parameter.PLAN_FORMAT));
-        param.setExpressionTree(getOptBoolean(jsonRequest, Parameter.EXPRESSION_TREE, false));
-        param.setRewrittenExpressionTree(getOptBoolean(jsonRequest, Parameter.REWRITTEN_EXPRESSION_TREE, false));
-        param.setLogicalPlan(getOptBoolean(jsonRequest, Parameter.LOGICAL_PLAN, false));
-        param.setParseOnly(getOptBoolean(jsonRequest, Parameter.PARSE_ONLY, false));
-        param.setReadOnly(getOptBoolean(jsonRequest, Parameter.READ_ONLY, false));
-        param.setOptimizedLogicalPlan(getOptBoolean(jsonRequest, Parameter.OPTIMIZED_LOGICAL_PLAN, false));
-        param.setJob(getOptBoolean(jsonRequest, Parameter.JOB, false));
-        param.setProfile(getOptBoolean(jsonRequest, Parameter.PROFILE, false));
-        param.setSignature(getOptBoolean(jsonRequest, Parameter.SIGNATURE, true));
-        param.setStatementParams(
-                getOptStatementParameters(jsonRequest, jsonRequest.fieldNames(), JsonNode::get, v -> v));
-        param.setMultiStatement(getOptBoolean(jsonRequest, Parameter.MULTI_STATEMENT, true));
-        param.setMaxWarnings(
-                getOptLong(jsonRequest, Parameter.MAX_WARNINGS, QueryServiceRequestParameters.DEFAULT_MAX_WARNINGS));
-        setJsonOptionalParameters(jsonRequest, param, optionalParameters);
-    }
-
-    protected void setJsonOptionalParameters(JsonNode jsonRequest, QueryServiceRequestParameters param,
-            Map<String, String> optionalParameters) {
-        // allows extensions to set extra parameters
-    }
-
-    private void setParamFromRequest(IServletRequest request, QueryServiceRequestParameters param,
-            Map<String, String> optionalParameters) throws IOException {
-        param.setStatement(getParameter(request, Parameter.STATEMENT));
-        param.setFormat(toLower(getParameter(request, Parameter.FORMAT)));
-        param.setPretty(Boolean.parseBoolean(getParameter(request, Parameter.PRETTY)));
-        param.setMode(toLower(getParameter(request, Parameter.MODE)));
-        param.setClientContextID(getParameter(request, Parameter.CLIENT_ID));
-        param.setTimeout(getParameter(request, Parameter.TIMEOUT));
-        param.setMaxResultReads(getParameter(request, Parameter.MAX_RESULT_READS));
-        param.setPlanFormat(getParameter(request, Parameter.PLAN_FORMAT));
-        param.setExpressionTree(getOptBoolean(request, Parameter.EXPRESSION_TREE, false));
-        param.setRewrittenExpressionTree(getOptBoolean(request, Parameter.REWRITTEN_EXPRESSION_TREE, false));
-        param.setLogicalPlan(getOptBoolean(request, Parameter.LOGICAL_PLAN, false));
-        param.setParseOnly(getOptBoolean(request, Parameter.PARSE_ONLY, false));
-        param.setReadOnly(getOptBoolean(request, Parameter.READ_ONLY, false));
-        param.setOptimizedLogicalPlan(getOptBoolean(request, Parameter.OPTIMIZED_LOGICAL_PLAN, false));
-        param.setJob(getOptBoolean(request, Parameter.JOB, false));
-        param.setProfile(getOptBoolean(request, Parameter.PROFILE, false));
-        param.setSignature(getOptBoolean(request, Parameter.SIGNATURE, true));
-        param.setMultiStatement(getOptBoolean(request, Parameter.MULTI_STATEMENT, true));
-        param.setMaxWarnings(
-                getOptLong(request, Parameter.MAX_WARNINGS, QueryServiceRequestParameters.DEFAULT_MAX_WARNINGS));
-        try {
-            param.setStatementParams(getOptStatementParameters(request, request.getParameterNames().iterator(),
-                    IServletRequest::getParameter, OBJECT_MAPPER::readTree));
-        } catch (JsonParseException | JsonMappingException e) {
-            GlobalConfig.ASTERIX_LOGGER.log(Level.ERROR, e.getMessage(), e);
-        }
-        setOptionalParameters(request, param, optionalParameters);
-    }
-
-    protected void setOptionalParameters(IServletRequest request, QueryServiceRequestParameters param,
-            Map<String, String> optionalParameters) {
-        // allows extensions to set extra parameters
+        param.setParameters(this, request, optionalParams);
     }
 
     private void setAccessControlHeaders(IServletRequest request, IServletResponse response) throws IOException {
@@ -454,16 +208,6 @@
         response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
     }
 
-    private static ResultDelivery parseResultDelivery(String mode) {
-        if ("async".equals(mode)) {
-            return ResultDelivery.ASYNC;
-        } else if ("deferred".equals(mode)) {
-            return ResultDelivery.DEFERRED;
-        } else {
-            return ResultDelivery.IMMEDIATE;
-        }
-    }
-
     private static String handlePath(ResultDelivery delivery) {
         switch (delivery) {
             case ASYNC:
@@ -515,10 +259,9 @@
             }
             setRequestParam(request, param, optionalParams);
             LOGGER.info(() -> "handleRequest: " + LogRedactionUtil.userData(param.toString()));
-            delivery = parseResultDelivery(param.getMode());
+            delivery = param.getMode();
             setSessionConfig(sessionOutput, param, delivery);
-            final ResultProperties resultProperties = param.getMaxResultReads() == null ? new ResultProperties(delivery)
-                    : new ResultProperties(delivery, Long.parseLong(param.getMaxResultReads()));
+            final ResultProperties resultProperties = new ResultProperties(delivery, param.getMaxResultReads());
             buildResponseHeaders(requestRef, sessionOutput, param, responsePrinter, delivery);
             responsePrinter.printHeaders();
             validateStatement(param.getStatement());
@@ -533,7 +276,7 @@
                         .serializeParameterValues(param.getStatementParams());
                 setAccessControlHeaders(request, response);
                 response.setStatus(execution.getHttpStatus());
-                stats.setType(param.isProfile() ? Stats.ProfileType.FULL : Stats.ProfileType.COUNTS);
+                stats.setProfileType(param.getProfileType());
                 executeStatement(requestRef, statementsText, sessionOutput, resultProperties, stats, param, execution,
                         optionalParams, statementParams, responsePrinter, warnings);
             }
@@ -671,6 +414,8 @@
                             + LogRedactionUtil.userData(param.toString()));
                     state.setStatus(ResultStatus.FATAL, HttpResponseStatus.SERVICE_UNAVAILABLE);
                     break;
+                case ASTERIX + INVALID_REQ_PARAM_VAL:
+                case ASTERIX + INVALID_REQ_JSON_VAL:
                 case ASTERIX + NO_STATEMENT_PROVIDED:
                 case HYRACKS + JOB_REQUIREMENTS_EXCEED_CAPACITY:
                     state.setStatus(ResultStatus.FATAL, HttpResponseStatus.BAD_REQUEST);
@@ -693,9 +438,8 @@
         String handleUrl = getHandleUrl(param.getHost(), param.getPath(), delivery);
         sessionOutput.setHandleAppender(ResultUtil.createResultHandleAppender(handleUrl));
         SessionConfig sessionConfig = sessionOutput.config();
-        SessionConfig.OutputFormat format = getFormat(param.getFormat());
-        SessionConfig.PlanFormat planFormat = SessionConfig.PlanFormat.get(param.getPlanFormat(), param.getPlanFormat(),
-                SessionConfig.PlanFormat.JSON, LOGGER);
+        SessionConfig.OutputFormat format = param.getFormat();
+        SessionConfig.PlanFormat planFormat = param.getPlanFormat();
         sessionConfig.setFmt(format);
         sessionConfig.setPlanFormat(planFormat);
         sessionConfig.setMaxWarnings(param.getMaxWarnings());
@@ -708,8 +452,7 @@
         sessionConfig.set(SessionConfig.FORMAT_INDENT_JSON, param.isPretty());
         sessionConfig.set(SessionConfig.FORMAT_QUOTE_RECORD,
                 format != SessionConfig.OutputFormat.CLEAN_JSON && format != SessionConfig.OutputFormat.LOSSLESS_JSON);
-        sessionConfig.set(SessionConfig.FORMAT_CSV_HEADER, format == SessionConfig.OutputFormat.CSV
-                && "present".equals(getParameterValue(param.getFormat(), Attribute.HEADER.str())));
+        sessionConfig.set(SessionConfig.FORMAT_CSV_HEADER, param.isCSVWithHeader());
     }
 
     protected void requestFailed(Throwable throwable, ResponsePrinter responsePrinter) {
@@ -721,33 +464,7 @@
         return new QueryServiceRequestParameters();
     }
 
-    private static boolean isJsonFormat(String format) {
-        return format.startsWith(HttpUtil.ContentType.APPLICATION_JSON)
-                || format.equalsIgnoreCase(HttpUtil.ContentType.JSON);
-    }
-
-    public static String extractStatementParameterName(String name) {
-        int ln = name.length();
-        if ((ln == 2 || isStatementParameterNameRest(name, 2)) && name.charAt(0) == '$'
-                && Character.isLetter(name.charAt(1))) {
-            return name.substring(1);
-        }
-        return null;
-    }
-
-    private static boolean isStatementParameterNameRest(CharSequence input, int startIndex) {
-        int i = startIndex;
-        for (int ln = input.length(); i < ln; i++) {
-            char c = input.charAt(i);
-            boolean ok = c == '_' || Character.isLetterOrDigit(c);
-            if (!ok) {
-                return false;
-            }
-        }
-        return i > startIndex;
-    }
-
     private static boolean isPrintingProfile(IStatementExecutor.Stats stats) {
-        return stats.getType() == Stats.ProfileType.FULL && stats.getJobProfile() != null;
+        return stats.getProfileType() == Stats.ProfileType.FULL && stats.getJobProfile() != null;
     }
 }
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java
index e58ad06..94080da 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/message/ExecuteStatementRequestMessage.java
@@ -19,9 +19,6 @@
 
 package org.apache.asterix.app.message;
 
-import static org.apache.asterix.translator.IStatementExecutor.Stats.ProfileType.COUNTS;
-import static org.apache.asterix.translator.IStatementExecutor.Stats.ProfileType.FULL;
-
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
@@ -53,6 +50,7 @@
 import org.apache.asterix.om.base.IAObject;
 import org.apache.asterix.translator.IRequestParameters;
 import org.apache.asterix.translator.IStatementExecutor;
+import org.apache.asterix.translator.IStatementExecutor.Stats.ProfileType;
 import org.apache.asterix.translator.IStatementExecutorFactory;
 import org.apache.asterix.translator.ResultProperties;
 import org.apache.asterix.translator.SessionConfig;
@@ -87,13 +85,13 @@
     private final Map<String, byte[]> statementParameters;
     private final boolean multiStatement;
     private final int statementCategoryRestrictionMask;
-    private final boolean profile;
+    private final ProfileType profileType;
     private final IRequestReference requestReference;
 
     public ExecuteStatementRequestMessage(String requestNodeId, long requestMessageId, ILangExtension.Language lang,
             String statementsText, SessionConfig sessionConfig, ResultProperties resultProperties,
             String clientContextID, String handleUrl, Map<String, String> optionalParameters,
-            Map<String, byte[]> statementParameters, boolean multiStatement, boolean profile,
+            Map<String, byte[]> statementParameters, boolean multiStatement, ProfileType profileType,
             int statementCategoryRestrictionMask, IRequestReference requestReference) {
         this.requestNodeId = requestNodeId;
         this.requestMessageId = requestMessageId;
@@ -107,7 +105,7 @@
         this.statementParameters = statementParameters;
         this.multiStatement = multiStatement;
         this.statementCategoryRestrictionMask = statementCategoryRestrictionMask;
-        this.profile = profile;
+        this.profileType = profileType;
         this.requestReference = requestReference;
     }
 
@@ -147,7 +145,7 @@
             IStatementExecutor translator = statementExecutorFactory.create(ccAppCtx, statements, sessionOutput,
                     compilationProvider, storageComponentProvider, new ResponsePrinter(sessionOutput));
             final IStatementExecutor.Stats stats = new IStatementExecutor.Stats();
-            stats.setType(profile ? FULL : COUNTS);
+            stats.setProfileType(profileType);
             Map<String, IAObject> stmtParams = RequestParameters.deserializeParameterValues(statementParameters);
             final IRequestParameters requestParameters = new RequestParameters(requestReference, statementsText, null,
                     resultProperties, stats, outMetadata, clientContextID, optionalParameters, stmtParams,
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/TypePrinter.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/TypePrinter.java
index 788fbcf..ad3b8d8 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/TypePrinter.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/TypePrinter.java
@@ -18,7 +18,7 @@
  */
 package org.apache.asterix.app.result.fields;
 
-import static org.apache.hyracks.http.server.utils.HttpUtil.ContentType.CSV;
+import static org.apache.hyracks.http.server.utils.HttpUtil.ContentType.TEXT_CSV;
 
 import java.io.PrintWriter;
 
@@ -43,8 +43,8 @@
                 ResultUtil.printField(pw, FIELD_NAME, HttpUtil.ContentType.APPLICATION_ADM, false);
                 break;
             case CSV:
-                String contentType =
-                        CSV + "; header=" + (sessionConfig.is(SessionConfig.FORMAT_CSV_HEADER) ? "present" : "absent");
+                String contentType = TEXT_CSV + "; header="
+                        + (sessionConfig.is(SessionConfig.FORMAT_CSV_HEADER) ? "present" : "absent");
                 ResultUtil.printField(pw, FIELD_NAME, contentType, false);
                 break;
             default:
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
index 6bd876d..ce1a354 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
@@ -393,7 +393,7 @@
                         metadataProvider.setResultAsyncMode(
                                 resultDelivery == ResultDelivery.ASYNC || resultDelivery == ResultDelivery.DEFERRED);
                         metadataProvider.setMaxResultReads(maxResultReads);
-                        if (stats.getType() == Stats.ProfileType.FULL) {
+                        if (stats.getProfileType() == Stats.ProfileType.FULL) {
                             this.jobFlags.add(JobFlag.PROFILE_RUNTIME);
                         }
                         handleQuery(metadataProvider, (Query) stmt, hcc, resultSet, resultDelivery, outMetadata, stats,
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 8dc04eb..71ef783 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
@@ -66,7 +66,7 @@
 import java.util.regex.Pattern;
 import java.util.stream.Stream;
 
-import org.apache.asterix.api.http.server.QueryServiceServlet;
+import org.apache.asterix.api.http.server.QueryServiceRequestParameters;
 import org.apache.asterix.app.external.IExternalUDFLibrarian;
 import org.apache.asterix.common.api.Duration;
 import org.apache.asterix.common.config.GlobalConfig;
@@ -626,13 +626,14 @@
     }
 
     public List<Parameter> constructQueryParameters(String str, OutputFormat fmt, List<Parameter> params) {
-        List<Parameter> newParams = upsertParam(params, "format", ParameterTypeEnum.STRING, fmt.mimeType());
+        List<Parameter> newParams = upsertParam(params, QueryServiceRequestParameters.Parameter.FORMAT.str(),
+                ParameterTypeEnum.STRING, fmt.mimeType());
 
-        newParams = upsertParam(newParams, QueryServiceServlet.Parameter.PLAN_FORMAT.str(), ParameterTypeEnum.STRING,
-                DEFAULT_PLAN_FORMAT);
+        newParams = upsertParam(newParams, QueryServiceRequestParameters.Parameter.PLAN_FORMAT.str(),
+                ParameterTypeEnum.STRING, DEFAULT_PLAN_FORMAT);
         final Optional<String> maxReadsOptional = extractMaxResultReads(str);
         if (maxReadsOptional.isPresent()) {
-            newParams = upsertParam(newParams, QueryServiceServlet.Parameter.MAX_RESULT_READS.str(),
+            newParams = upsertParam(newParams, QueryServiceRequestParameters.Parameter.MAX_RESULT_READS.str(),
                     ParameterTypeEnum.STRING, maxReadsOptional.get());
         }
         return newParams;
@@ -2186,7 +2187,7 @@
     protected static boolean containsClientContextID(String statement) {
         List<Parameter> httpParams = extractParameters(statement);
         return httpParams.stream().map(Parameter::getName)
-                .anyMatch(QueryServiceServlet.Parameter.CLIENT_ID.str()::equals);
+                .anyMatch(QueryServiceRequestParameters.Parameter.CLIENT_ID.str()::equals);
     }
 
     private static boolean isCancellable(String type) {
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestHelper.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestHelper.java
index 7695698..619ce8c 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestHelper.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestHelper.java
@@ -33,7 +33,7 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
-import org.apache.asterix.api.http.server.QueryServiceServlet;
+import org.apache.asterix.api.http.server.QueryServiceRequestParameters;
 import org.apache.asterix.app.translator.RequestParameters;
 import org.apache.asterix.om.base.IAObject;
 import org.apache.asterix.testframework.xml.ParameterTypeEnum;
@@ -126,10 +126,10 @@
                     throw new IllegalArgumentException(String.valueOf(paramType));
 
             }
-            String name = QueryServiceServlet.extractStatementParameterName(paramName);
+            String name = QueryServiceRequestParameters.extractStatementParameterName(paramName);
             if (name != null) {
                 stmtParams.put(name, paramJsonValue);
-            } else if (QueryServiceServlet.Parameter.ARGS.str().equals(paramName)) {
+            } else if (QueryServiceRequestParameters.Parameter.ARGS.str().equals(paramName)) {
                 if (paramJsonValue.isArray()) {
                     for (int i = 0, ln = paramJsonValue.size(); i < ln; i++) {
                         stmtParams.put(String.valueOf(i + 1), paramJsonValue.get(i));
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/profiled.xml b/asterixdb/asterix-app/src/test/resources/runtimets/profiled.xml
index 496927e..f3209a1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/profiled.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/profiled.xml
@@ -22,9 +22,21 @@
   <test-group name="profile">
     <test-case FilePath="profile">
       <compilation-unit name="full-scan">
-        <parameter name="profile" value="true" />
+        <parameter name="profile" value="timings" type="string"/>
         <output-dir compare="Text">full-scan</output-dir>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="profile">
+      <compilation-unit name="full-scan-2">
+        <parameter name="profile" value="counts" type="string"/>
+        <output-dir compare="Text">full-scan-2</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="profile">
+      <compilation-unit name="full-scan-3">
+        <parameter name="profile" value="off" type="string"/>
+        <output-dir compare="Text">full-scan-3</output-dir>
+      </compilation-unit>
+    </test-case>
   </test-group>
 </test-suite>
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-01/format-param-in-accept-01.1.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-01/format-param-in-accept-01.1.post.http
new file mode 100644
index 0000000..cf0c800
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-01/format-param-in-accept-01.1.post.http
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * Description: testing specifying application/json as output format in Accept of HEADER
+ */
+/query/service
+--body={"statement": "set `import-private-functions` `true`; `unordered-list-constructor`(\"foo\", \"bar\");"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-02/format-param-in-accept-02.1.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-02/format-param-in-accept-02.1.post.http
new file mode 100644
index 0000000..cf0c800
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-02/format-param-in-accept-02.1.post.http
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * Description: testing specifying application/json as output format in Accept of HEADER
+ */
+/query/service
+--body={"statement": "set `import-private-functions` `true`; `unordered-list-constructor`(\"foo\", \"bar\");"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-03/format-param-in-accept-03.1.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-03/format-param-in-accept-03.1.post.http
new file mode 100644
index 0000000..bb7055a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-03/format-param-in-accept-03.1.post.http
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * Description: testing specifying application/json;lossless=true as output format in Accept of HEADER
+ */
+/query/service
+--body={"statement": "set `import-private-functions` `true`; `unordered-list-constructor`(\"foo\", \"bar\");"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-04/format-param-in-accept-04.1.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-04/format-param-in-accept-04.1.post.http
new file mode 100644
index 0000000..c68fabe
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-04/format-param-in-accept-04.1.post.http
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * Description: testing specifying application/x-adm as output format in Accept of HEADER and json in "format" param
+ * Expected   : json format is picked
+ */
+/query/service
+--body={"statement": "set `import-private-functions` `true`; `unordered-list-constructor`(\"foo\", \"bar\");", "format": "json"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-05/format-param-in-accept-05.1.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-05/format-param-in-accept-05.1.post.http
new file mode 100644
index 0000000..720b5f2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/format-param-in-accept-05/format-param-in-accept-05.1.post.http
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * Description: testing specifying unknown mime type, application/x-ast
+ * Expected   : json is defaulted since no "format" parameter is specified and format in Accept is unkownn
+ */
+/query/service
+--body={"statement": "set `import-private-functions` `true`; `unordered-list-constructor`(\"foo\", \"bar\");"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation-400-BAD/request-param-validation-400-BAD.01.post.http b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation-400-BAD/request-param-validation-400-BAD.01.post.http
new file mode 100644
index 0000000..8c5a4d6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation-400-BAD/request-param-validation-400-BAD.01.post.http
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+// statuscode 400
+/query/service
+--body={"statement": "from [1, 2] as v select v;", "format": "foo"}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.001.query.sqlpp
new file mode 100644
index 0000000..69e67be
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.001.query.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Description: validating that request parameters have proper values
+ */
+
+// requesttype=application/json
+// param format:string=foo
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.002.query.sqlpp
new file mode 100644
index 0000000..0ab2195
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.002.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param pretty:string=bar
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.003.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.003.query.sqlpp
new file mode 100644
index 0000000..24267b1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.003.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param plan-format:string=blah
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.004.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.004.query.sqlpp
new file mode 100644
index 0000000..68ba956
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.004.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param max-result-reads:string=foo
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.005.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.005.query.sqlpp
new file mode 100644
index 0000000..2c8b15e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.005.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param max-result-reads:string=9999999999999999999999999999999999999999
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.006.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.006.query.sqlpp
new file mode 100644
index 0000000..f7adc7a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.006.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param max-warnings:string=baz
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.007.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.007.query.sqlpp
new file mode 100644
index 0000000..6433ae6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.007.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param max-warnings:string=1.5
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.008.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.008.query.sqlpp
new file mode 100644
index 0000000..46cd166
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.008.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param mode:string=asyn
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.009.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.009.query.sqlpp
new file mode 100644
index 0000000..29ef01b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.009.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param timeout:string=12
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.010.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.010.query.sqlpp
new file mode 100644
index 0000000..e56f9a2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.010.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param args:json=12
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.011.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.011.query.sqlpp
new file mode 100644
index 0000000..073a264
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.011.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param args:json=[12,,1]
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.012.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.012.query.sqlpp
new file mode 100644
index 0000000..1bf1146
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.012.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param $var:json={"a":}
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.013.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.013.query.sqlpp
new file mode 100644
index 0000000..837ee28
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.013.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param format:string=foo
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.014.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.014.query.sqlpp
new file mode 100644
index 0000000..25b8eb8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.014.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param pretty:string=bar
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.015.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.015.query.sqlpp
new file mode 100644
index 0000000..bdda7c4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.015.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param plan-format:string=blah
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.016.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.016.query.sqlpp
new file mode 100644
index 0000000..eedad6d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.016.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param max-result-reads:string=foo
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.017.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.017.query.sqlpp
new file mode 100644
index 0000000..fc0c48d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.017.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param max-warnings:string=baz
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.018.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.018.query.sqlpp
new file mode 100644
index 0000000..cbcf381
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.018.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param mode:string=asyn
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.019.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.019.query.sqlpp
new file mode 100644
index 0000000..d682463
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.019.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param args:json=12
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.020.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.020.query.sqlpp
new file mode 100644
index 0000000..0f58953
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.020.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param args:json=[12,,1]
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.021.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.021.query.sqlpp
new file mode 100644
index 0000000..e37d945
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.021.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param $var:json={"a":}
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.022.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.022.query.sqlpp
new file mode 100644
index 0000000..0665e09
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.022.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param profile:string=true
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.023.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.023.query.sqlpp
new file mode 100644
index 0000000..5767812
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.023.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param profile:string=true
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.024.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.024.query.sqlpp
new file mode 100644
index 0000000..e99ec6c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.024.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param profile:string=foo
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.025.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.025.query.sqlpp
new file mode 100644
index 0000000..2ca9df4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param-validation/request-param-validation.025.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/x-www-form-urlencoded
+// param profile:string=foo
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.001.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.001.query.sqlpp
new file mode 100644
index 0000000..f22230e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.001.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param format:string=json
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.002.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.002.query.sqlpp
new file mode 100644
index 0000000..b574cc9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.002.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param format:string=csv
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.003.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.003.query.sqlpp
new file mode 100644
index 0000000..ba37336
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.003.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param format:string=application/json
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.004.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.004.query.sqlpp
new file mode 100644
index 0000000..b5d0d64
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.004.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param format:string=text/csv
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.005.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.005.query.sqlpp
new file mode 100644
index 0000000..9d3b964
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.005.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param format:string=application/x-adm
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.006.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.006.query.sqlpp
new file mode 100644
index 0000000..d667f48
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.006.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param format:string=text/csv;header=absent
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.007.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.007.query.sqlpp
new file mode 100644
index 0000000..cba7638
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.007.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param format:string=application/json;lossless=true
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.008.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.008.query.sqlpp
new file mode 100644
index 0000000..7b6c450
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.008.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param format:string=application/json;lossless=false
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.009.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.009.query.sqlpp
new file mode 100644
index 0000000..d483eb3
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-param/request-param.009.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// requesttype=application/json
+// param mode:string=immediate
+
+from [1, 2] as v
+select v;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.1.ddl.sqlpp
new file mode 100644
index 0000000..c5cab5d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.1.ddl.sqlpp
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * Description  : Testing that "counts" is supplied in request parameter "profile".
+ * Expected Res : Success with expected result not having "profile" field.
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use test;
+
+create type test.AddressType as
+{
+  number : bigint,
+  street : string,
+  city : string
+};
+
+create type test.CustomerType as
+ closed {
+  cid : bigint,
+  name : string,
+  age : bigint?,
+  address : AddressType?,
+  lastorder : {
+      oid : bigint,
+      total : float
+  }
+};
+
+create dataset Customers(CustomerType) primary key cid;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.2.update.sqlpp
new file mode 100644
index 0000000..957c234
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.2.update.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+load dataset Customers using localfs
+  ((`path`=`asterix_nc1://data/custord-tiny/customer-tiny-neg.adm`),
+  (`format`=`adm`));
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.3.profile.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.3.profile.sqlpp
new file mode 100644
index 0000000..070196a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.3.profile.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+select count(*) from Customers;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.4.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.4.ddl.sqlpp
new file mode 100644
index 0000000..f12a2b7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-2/full-scan-2.4.ddl.sqlpp
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+drop dataverse test;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.1.ddl.sqlpp
new file mode 100644
index 0000000..da6580a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.1.ddl.sqlpp
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * Description  : Testing that "off" is supplied in request parameter "profile".
+ * Expected Res : Success with expected result not having "profile" field.
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use test;
+
+create type test.AddressType as
+{
+  number : bigint,
+  street : string,
+  city : string
+};
+
+create type test.CustomerType as
+ closed {
+  cid : bigint,
+  name : string,
+  age : bigint?,
+  address : AddressType?,
+  lastorder : {
+      oid : bigint,
+      total : float
+  }
+};
+
+create dataset Customers(CustomerType) primary key cid;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.2.update.sqlpp
new file mode 100644
index 0000000..957c234
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.2.update.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+load dataset Customers using localfs
+  ((`path`=`asterix_nc1://data/custord-tiny/customer-tiny-neg.adm`),
+  (`format`=`adm`));
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.3.profile.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.3.profile.sqlpp
new file mode 100644
index 0000000..070196a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.3.profile.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+select count(*) from Customers;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.4.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.4.ddl.sqlpp
new file mode 100644
index 0000000..f12a2b7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/profile/full-scan-3/full-scan-3.4.ddl.sqlpp
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+drop dataverse test;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-01/format-param-in-accept-01.1.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-01/format-param-in-accept-01.1.regexjson
new file mode 100644
index 0000000..ad8ba0a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-01/format-param-in-accept-01.1.regexjson
@@ -0,0 +1,9 @@
+{
+	"requestID": "R{[a-zA-Z0-9-]+}",
+	"signature": {"*": "*"},
+	"type": "application/x-adm",
+	"results": [ "{{ \"foo\", \"bar\" }}\n" ],
+	"plans":{},
+	"status": "success",
+    "metrics": "R{.*}"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-02/format-param-in-accept-02.1.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-02/format-param-in-accept-02.1.regexjson
new file mode 100644
index 0000000..7443917
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-02/format-param-in-accept-02.1.regexjson
@@ -0,0 +1,8 @@
+{
+	"requestID": "R{[a-zA-Z0-9-]+}",
+	"signature": {"*": "*"},
+	"results": [["foo","bar"]],
+	"plans":{},
+	"status": "success",
+    "metrics": "R{.*}"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-03/format-param-in-accept-03.1.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-03/format-param-in-accept-03.1.regexjson
new file mode 100644
index 0000000..e48a4e1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-03/format-param-in-accept-03.1.regexjson
@@ -0,0 +1,8 @@
+{
+	"requestID": "R{[a-zA-Z0-9-]+}",
+	"signature": {"*": "*"},
+	"results": [{"unorderedlist":["foo","bar"]}],
+	"plans":{},
+	"status": "success",
+    "metrics": "R{.*}"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-04/format-param-in-accept-04.1.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-04/format-param-in-accept-04.1.regexjson
new file mode 100644
index 0000000..7443917
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-04/format-param-in-accept-04.1.regexjson
@@ -0,0 +1,8 @@
+{
+	"requestID": "R{[a-zA-Z0-9-]+}",
+	"signature": {"*": "*"},
+	"results": [["foo","bar"]],
+	"plans":{},
+	"status": "success",
+    "metrics": "R{.*}"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-05/format-param-in-accept-05.1.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-05/format-param-in-accept-05.1.regexjson
new file mode 100644
index 0000000..7443917
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/format-param-in-accept-05/format-param-in-accept-05.1.regexjson
@@ -0,0 +1,8 @@
+{
+	"requestID": "R{[a-zA-Z0-9-]+}",
+	"signature": {"*": "*"},
+	"results": [["foo","bar"]],
+	"plans":{},
+	"status": "success",
+    "metrics": "R{.*}"
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param-validation-400-BAD/request-param-validation-400-BAD.01.regexjson b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param-validation-400-BAD/request-param-validation-400-BAD.01.regexjson
new file mode 100644
index 0000000..f444fa1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param-validation-400-BAD/request-param-validation-400-BAD.01.regexjson
@@ -0,0 +1,14 @@
+{
+	"errors": [{ 
+		"code": 1,		"msg": "ASX0047: Invalid value for parameter \"format\": foo"	} 
+	],
+	"status": "fatal",
+	"metrics": {
+		"elapsedTime": "R{.*}",
+		"executionTime": "R{.*}",
+		"resultCount": 0,
+		"resultSize": 0,
+		"processedObjects": 0,
+		"errorCount": 1
+	}
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.001.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.001.json
new file mode 100644
index 0000000..83ce118
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.001.json
@@ -0,0 +1 @@
+{"v":1}{"v":2}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.002.csv b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.002.csv
new file mode 100644
index 0000000..7a754f4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.002.csv
@@ -0,0 +1,2 @@
+1
+2
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.003.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.003.json
new file mode 100644
index 0000000..83ce118
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.003.json
@@ -0,0 +1 @@
+{"v":1}{"v":2}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.004.csv b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.004.csv
new file mode 100644
index 0000000..7a754f4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.004.csv
@@ -0,0 +1,2 @@
+1
+2
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.005.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.005.adm
new file mode 100644
index 0000000..cb88308
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.005.adm
@@ -0,0 +1,2 @@
+{ "v": 1 }
+{ "v": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.006.csv b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.006.csv
new file mode 100644
index 0000000..7a754f4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.006.csv
@@ -0,0 +1,2 @@
+1
+2
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.007.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.007.json
new file mode 100644
index 0000000..32c4637
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.007.json
@@ -0,0 +1 @@
+{"v":{"int64":1}}{"v":{"int64":2}}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.008.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.008.json
new file mode 100644
index 0000000..83ce118
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.008.json
@@ -0,0 +1 @@
+{"v":1}{"v":2}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.009.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.009.adm
new file mode 100644
index 0000000..cb88308
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/request-param/request-param.009.adm
@@ -0,0 +1,2 @@
+{ "v": 1 }
+{ "v": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/full-scan-2/full-scan-2.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/full-scan-2/full-scan-2.3.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/full-scan-2/full-scan-2.3.adm
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/full-scan-3/full-scan-3.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/full-scan-3/full-scan-3.3.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/profile/full-scan-3/full-scan-3.3.adm
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index 0f82c9e..7deee6f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -42,6 +42,72 @@
         <expected-error>ASX0044: DELETE statement is prohibited by this request</expected-error>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="api">
+      <compilation-unit name="request-param-validation">
+        <output-dir compare="Text">request-param-validation</output-dir>
+        <source-location>false</source-location>
+        <expected-error>Invalid value for parameter "format": foo</expected-error>
+        <expected-error>Invalid value for parameter "pretty": bar</expected-error>
+        <expected-error>Invalid value for parameter "plan-format": blah</expected-error>
+        <expected-error>Invalid value for parameter "max-result-reads": foo</expected-error>
+        <expected-error>Invalid value for parameter "max-result-reads": 9999999999999999999999999999999999999999</expected-error>
+        <expected-error>Invalid value for parameter "max-warnings": baz</expected-error>
+        <expected-error>Invalid value for parameter "max-warnings": 1.5</expected-error>
+        <expected-error>Invalid value for parameter "mode": asyn</expected-error>
+        <expected-error>Invalid value for parameter "timeout": 12</expected-error>
+        <expected-error>Invalid value for parameter "args": 12</expected-error>
+        <expected-error>Unable to process JSON content in request</expected-error>
+        <expected-error>Unable to process JSON content in request</expected-error>
+        <expected-error>Invalid value for parameter "format": foo</expected-error>
+        <expected-error>Invalid value for parameter "pretty": bar</expected-error>
+        <expected-error>Invalid value for parameter "plan-format": blah</expected-error>
+        <expected-error>Invalid value for parameter "max-result-reads": foo</expected-error>
+        <expected-error>Invalid value for parameter "max-warnings": baz</expected-error>
+        <expected-error>Invalid value for parameter "mode": asyn</expected-error>
+        <expected-error>Invalid value for parameter "args": 12</expected-error>
+        <expected-error>Unable to process JSON content in request</expected-error>
+        <expected-error>Unable to process JSON content in request</expected-error>
+        <expected-error>Invalid value for parameter "profile": true</expected-error>
+        <expected-error>Invalid value for parameter "profile": true</expected-error>
+        <expected-error>Invalid value for parameter "profile": foo</expected-error>
+        <expected-error>Invalid value for parameter "profile": foo</expected-error>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="api">
+      <compilation-unit name="request-param-validation-400-BAD">
+        <output-dir compare="Text">request-param-validation-400-BAD</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="api">
+      <compilation-unit name="request-param">
+        <output-dir compare="Text">request-param</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="api">
+      <compilation-unit name="format-param-in-accept-01">
+        <output-dir compare="Text">format-param-in-accept-01</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="api">
+      <compilation-unit name="format-param-in-accept-02">
+        <output-dir compare="Clean-JSON">format-param-in-accept-02</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="api">
+      <compilation-unit name="format-param-in-accept-03">
+        <output-dir compare="Lossless-JSON">format-param-in-accept-03</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="api">
+      <compilation-unit name="format-param-in-accept-04">
+        <output-dir compare="Text">format-param-in-accept-04</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="api">
+      <compilation-unit name="format-param-in-accept-05">
+        <output-dir compare="AST">format-param-in-accept-05</output-dir>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="flwor">
     <test-case FilePath="flwor">
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
index e718ca5..da1c4e7 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
@@ -79,6 +79,8 @@
     public static final int PROHIBITED_STATEMENT_CATEGORY = 44;
     public static final int INTEGER_VALUE_EXPECTED_FUNCTION = 45;
     public static final int INVALID_LIKE_PATTERN = 46;
+    public static final int INVALID_REQ_PARAM_VAL = 47;
+    public static final int INVALID_REQ_JSON_VAL = 48;
 
     public static final int UNSUPPORTED_JRE = 100;
 
diff --git a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
index f8d7a89..457206d 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -81,6 +81,8 @@
 44 = %1$s statement is prohibited by this request
 45 = Invalid value: function %1$s expects its %2$s input parameter to be an integer value, got %3$s
 46 = Invalid pattern \"%1$s\" for LIKE
+47 = Invalid value for parameter \"%1$s\": %2$s
+48 = Unable to process JSON content in request
 
 100 = Unsupported JRE: %1$s
 
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 0f857bd..591cf8c 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
@@ -69,7 +69,8 @@
         public static final String APPLICATION_JSON = "application/json";
         public static final String JSON = "json";
         public static final String APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";
-        public static final String CSV = "text/csv";
+        public static final String CSV = "csv";
+        public static final String TEXT_CSV = "text/csv";
         public static final String IMG_PNG = "image/png";
         public static final String TEXT_HTML = "text/html";
         public static final String TEXT_PLAIN = "text/plain";