Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id AA114200CE6 for ; Wed, 2 Aug 2017 07:49:21 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id A87F4168B71; Wed, 2 Aug 2017 05:49:21 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 4DE94168B70 for ; Wed, 2 Aug 2017 07:49:20 +0200 (CEST) Received: (qmail 24737 invoked by uid 500); 2 Aug 2017 05:49:19 -0000 Mailing-List: contact notifications-help@asterixdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@asterixdb.apache.org Delivered-To: mailing list notifications@asterixdb.apache.org Received: (qmail 24728 invoked by uid 99); 2 Aug 2017 05:49:19 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd2-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 02 Aug 2017 05:49:19 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd2-us-west.apache.org (ASF Mail Server at spamd2-us-west.apache.org) with ESMTP id 038081A02A9 for ; Wed, 2 Aug 2017 05:49:19 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd2-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 0.919 X-Spam-Level: X-Spam-Status: No, score=0.919 tagged_above=-999 required=6.31 tests=[SPF_FAIL=0.919] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd2-us-west.apache.org [10.40.0.9]) (amavisd-new, port 10024) with ESMTP id smA2mq5lNOrp for ; Wed, 2 Aug 2017 05:49:15 +0000 (UTC) Received: from unhygienix.ics.uci.edu (unhygienix.ics.uci.edu [128.195.14.130]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with ESMTP id 5EA3C5F21F for ; Wed, 2 Aug 2017 05:49:14 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by unhygienix.ics.uci.edu (Postfix) with ESMTP id B57382408A2; Tue, 1 Aug 2017 22:49:13 -0700 (PDT) Date: Tue, 1 Aug 2017 22:49:13 -0700 From: "Michael Blow (Code Review)" Message-ID: Reply-To: mblow@apache.org X-Gerrit-MessageType: newchange Subject: Change in asterixdb[master]: WIP: config null handling, http request processing X-Gerrit-Change-Id: I670b815a5276d870f7d538d1ce9d8bef2d0fcf4f X-Gerrit-ChangeURL: X-Gerrit-Commit: 5f990b7259a30c264cf6a0c7f6827916856dc416 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Content-Disposition: inline User-Agent: Gerrit/2.12.7 To: undisclosed-recipients:; archived-at: Wed, 02 Aug 2017 05:49:21 -0000 Michael Blow has uploaded a new change for review. https://asterix-gerrit.ics.uci.edu/1911 Change subject: WIP: config null handling, http request processing ...................................................................... WIP: config null handling, http request processing - handle null config values when marshall/unmarshalling - support non-post x-www-form-urlencoded directly - don't assume POSTs are x-www-form-urlencoded Change-Id: I670b815a5276d870f7d538d1ce9d8bef2d0fcf4f --- M asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java M asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java M asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryStatusApiServlet.java M asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java M hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/config/IOption.java M hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/config/IOptionType.java M hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/pom.xml M hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/ConfigManager.java M hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/OptionTypes.java M hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServletRequest.java M hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/BaseRequest.java A hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/FormUrlEncodedRequest.java D hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/PostRequest.java M hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java 14 files changed, 235 insertions(+), 110 deletions(-) git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb refs/changes/11/1911/1 diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java index 42e23ba..901aff8 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java @@ -41,7 +41,7 @@ public class QueryResultApiServlet extends AbstractQueryApiServlet { private static final Logger LOGGER = Logger.getLogger(QueryResultApiServlet.class.getName()); - public QueryResultApiServlet(ConcurrentMap ctx, String[] paths, IApplicationContext appCtx) { + public QueryResultApiServlet(ConcurrentMap ctx, IApplicationContext appCtx, String... paths) { super(appCtx, ctx, paths); } 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 9ee064e..1cec616 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 @@ -62,8 +62,6 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; - -import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; public class QueryServiceServlet extends AbstractQueryApiServlet { @@ -317,9 +315,7 @@ } private RequestParameters getRequestParameters(IServletRequest request) throws IOException { - final String contentTypeParam = request.getHttpRequest().headers().get(HttpHeaderNames.CONTENT_TYPE); - int sep = contentTypeParam.indexOf(';'); - final String contentType = sep < 0 ? contentTypeParam.trim() : contentTypeParam.substring(0, sep).trim(); + final String contentType = HttpUtil.getContentTypeOnly(request); RequestParameters param = new RequestParameters(); param.host = host(request); param.path = servletPath(request); diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryStatusApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryStatusApiServlet.java index 71dddc0..cec65f7 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryStatusApiServlet.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryStatusApiServlet.java @@ -41,7 +41,7 @@ public class QueryStatusApiServlet extends AbstractQueryApiServlet { private static final Logger LOGGER = Logger.getLogger(QueryStatusApiServlet.class.getName()); - public QueryStatusApiServlet(ConcurrentMap ctx, String[] paths, IApplicationContext appCtx) { + public QueryStatusApiServlet(ConcurrentMap ctx, IApplicationContext appCtx, String... paths) { super(appCtx, ctx, paths); } diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java index 3627974..e8636c8 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java @@ -287,9 +287,9 @@ case Servlets.RUNNING_REQUESTS: return new QueryCancellationServlet(ctx, paths); case Servlets.QUERY_STATUS: - return new QueryStatusApiServlet(ctx, paths, appCtx); + return new QueryStatusApiServlet(ctx, appCtx, paths); case Servlets.QUERY_RESULT: - return new QueryResultApiServlet(ctx, paths, appCtx); + return new QueryResultApiServlet(ctx, appCtx, paths); case Servlets.QUERY_SERVICE: return new QueryServiceServlet(ctx, paths, appCtx, SQLPP, ccExtensionManager.getCompilationProvider(SQLPP), getStatementExecutorFactory(), diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/config/IOption.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/config/IOption.java index 834d73c..b8e7635 100644 --- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/config/IOption.java +++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/config/IOption.java @@ -20,6 +20,9 @@ import java.util.function.Function; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.text.WordUtils; + public interface IOption { String name(); @@ -64,6 +67,10 @@ return name().toLowerCase().replace("_", "."); } + default String json() { + return StringUtils.remove(WordUtils.capitalize("z" + name().toLowerCase(), '_').substring(1), '_'); + } + default String toIniString() { return "[" + section().sectionName() + "] " + ini(); } diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/config/IOptionType.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/config/IOptionType.java index 1bd6097..d2a254f 100644 --- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/config/IOptionType.java +++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/config/IOptionType.java @@ -18,6 +18,8 @@ */ package org.apache.hyracks.api.config; +import com.fasterxml.jackson.databind.node.ObjectNode; + public interface IOptionType { /** * @throws IllegalArgumentException when the supplied string cannot be interpreted @@ -34,6 +36,11 @@ } /** + * @return the value in a format suitable for serialized JSON + */ + void serializeJSONField(String fieldName, Object value, ObjectNode node); + + /** * @return the value in a format suitable for serialized ini file */ default String serializeToIni(Object value) { diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/pom.xml b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/pom.xml index 5120047..80ef088 100644 --- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/pom.xml +++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/pom.xml @@ -75,5 +75,9 @@ org.apache.commons commons-collections4 + + org.apache.commons + commons-lang3 + diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/ConfigManager.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/ConfigManager.java index fcaee6d..a595301 100644 --- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/ConfigManager.java +++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/ConfigManager.java @@ -425,7 +425,7 @@ } public List getNodeNames() { - return Collections.unmodifiableList(new ArrayList(nodeSpecificMap.keySet())); + return Collections.unmodifiableList(new ArrayList<>(nodeSpecificMap.keySet())); } public IApplicationConfig getNodeEffectiveConfig(String nodeId) { diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/OptionTypes.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/OptionTypes.java index 02b9325..1e92a7a 100644 --- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/OptionTypes.java +++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/OptionTypes.java @@ -21,14 +21,20 @@ import java.net.MalformedURLException; import java.util.logging.Level; +import org.apache.commons.lang3.StringUtils; import org.apache.hyracks.api.config.IOptionType; import org.apache.hyracks.util.StorageUtil; + +import com.fasterxml.jackson.databind.node.ObjectNode; public class OptionTypes { public static final IOptionType INTEGER_BYTE_UNIT = new IOptionType() { @Override public Integer parse(String s) { + if (s == null) { + return null; + } long result1 = StorageUtil.getByteValue(s); if (result1 > Integer.MAX_VALUE || result1 < Integer.MIN_VALUE) { throw new IllegalArgumentException( @@ -46,12 +52,17 @@ public String serializeToHumanReadable(Object value) { return value + " (" + StorageUtil.toHumanReadableSize((int)value) + ")"; } + + @Override + public void serializeJSONField(String fieldName, Object value, ObjectNode node) { + node.put(fieldName, (int)value); + } }; public static final IOptionType LONG_BYTE_UNIT = new IOptionType() { @Override public Long parse(String s) { - return StorageUtil.getByteValue(s); + return s == null ? null : StorageUtil.getByteValue(s); } @Override @@ -62,6 +73,11 @@ @Override public String serializeToHumanReadable(Object value) { return value + " (" + StorageUtil.toHumanReadableSize((long)value) + ")"; + } + + @Override + public void serializeJSONField(String fieldName, Object value, ObjectNode node) { + node.put(fieldName, (long)value); } }; @@ -75,6 +91,11 @@ public Class targetType() { return Integer.class; } + + @Override + public void serializeJSONField(String fieldName, Object value, ObjectNode node) { + node.put(fieldName, (int)value); + } }; public static final IOptionType DOUBLE = new IOptionType() { @@ -86,6 +107,11 @@ @Override public Class targetType() { return Double.class; + } + + @Override + public void serializeJSONField(String fieldName, Object value, ObjectNode node) { + node.put(fieldName, (double)value); } }; @@ -99,6 +125,11 @@ public Class targetType() { return String.class; } + + @Override + public void serializeJSONField(String fieldName, Object value, ObjectNode node) { + node.put(fieldName, (String)value); + } }; public static final IOptionType LONG = new IOptionType() { @@ -110,6 +141,11 @@ @Override public Class targetType() { return Long.class; + } + + @Override + public void serializeJSONField(String fieldName, Object value, ObjectNode node) { + node.put(fieldName, (long)value); } }; @@ -123,12 +159,17 @@ public Class targetType() { return Boolean.class; } + + @Override + public void serializeJSONField(String fieldName, Object value, ObjectNode node) { + node.put(fieldName, (boolean)value); + } }; public static final IOptionType LEVEL = new IOptionType() { @Override public Level parse(String s) { - return Level.parse(s); + return s == null ? null : Level.parse(s); } @Override @@ -137,20 +178,25 @@ } @Override - public Object serializeToJSON(Object value) { - return ((Level)value).getName(); + public String serializeToJSON(Object value) { + return value == null ? null : ((Level)value).getName(); } @Override public String serializeToIni(Object value) { return ((Level)value).getName(); } + + @Override + public void serializeJSONField(String fieldName, Object value, ObjectNode node) { + node.put(fieldName, serializeToJSON(value)); + } }; public static final IOptionType STRING_ARRAY = new IOptionType() { @Override public String [] parse(String s) { - return s.split("\\s*,\\s*"); + return s == null ? null : s.split("\\s*,\\s*"); } @Override @@ -162,13 +208,18 @@ public String serializeToIni(Object value) { return String.join(",", (String [])value); } + + @Override + public void serializeJSONField(String fieldName, Object value, ObjectNode node) { + node.put(fieldName, value == null ? null : StringUtils.join((String [])value, ',')); + } }; public static final IOptionType URL = new IOptionType() { @Override public java.net.URL parse(String s) { try { - return new java.net.URL(s); + return s == null ? null : new java.net.URL(s); } catch (MalformedURLException e) { throw new IllegalArgumentException(e); } @@ -178,8 +229,12 @@ public Class targetType() { return java.net.URL.class; } - }; + @Override + public void serializeJSONField(String fieldName, Object value, ObjectNode node) { + node.put(fieldName, value == null ? null : String.valueOf(value)); + } + }; private OptionTypes() { } diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServletRequest.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServletRequest.java index 610c3d1..587cbe3 100644 --- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServletRequest.java +++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServletRequest.java @@ -18,6 +18,9 @@ */ package org.apache.hyracks.http.api; +import java.util.Map; +import java.util.Set; + import io.netty.handler.codec.http.FullHttpRequest; /** @@ -38,6 +41,20 @@ String getParameter(CharSequence name); /** + * Get the names of any request parameters + * + * @return the list of parameter names + */ + Set getParameterNames(); + + /** + * Get the all request parameters + * + * @return the parameters + */ + Map getParameters(); + + /** * Get a request header * * @param name diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/BaseRequest.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/BaseRequest.java index 5b354af..0c633cf 100644 --- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/BaseRequest.java +++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/BaseRequest.java @@ -19,8 +19,11 @@ package org.apache.hyracks.http.server; import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.hyracks.http.api.IServletRequest; import org.apache.hyracks.http.server.utils.HttpUtil; @@ -54,6 +57,21 @@ } @Override + public Set getParameterNames() { + return Collections.unmodifiableSet(parameters.keySet()); + } + + @Override + public Map getParameters() { + HashMap paramMap = new HashMap<>(); + for (String name : parameters.keySet()) { + paramMap.put(name, HttpUtil.getParameter(parameters, name)); + + } + return Collections.unmodifiableMap(paramMap); + } + + @Override public String getHeader(CharSequence name) { return request.headers().get(name); } diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/FormUrlEncodedRequest.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/FormUrlEncodedRequest.java new file mode 100644 index 0000000..743a2c4 --- /dev/null +++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/FormUrlEncodedRequest.java @@ -0,0 +1,99 @@ +/* + * 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. + */ +package org.apache.hyracks.http.server; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.hyracks.http.api.IServletRequest; +import org.apache.hyracks.http.server.utils.HttpUtil; + +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.QueryStringDecoder; +import io.netty.handler.codec.http.multipart.Attribute; +import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder; +import io.netty.handler.codec.http.multipart.InterfaceHttpData; +import io.netty.handler.codec.http.multipart.MixedAttribute; + +public class FormUrlEncodedRequest extends BaseRequest implements IServletRequest { + + private final List names; + private final List values; + + public static IServletRequest create(FullHttpRequest request) throws IOException { + List names = new ArrayList<>(); + List values = new ArrayList<>(); + HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(request); + try { + List bodyHttpDatas = decoder.getBodyHttpDatas(); + for (InterfaceHttpData data : bodyHttpDatas) { + if (data.getHttpDataType().equals(InterfaceHttpData.HttpDataType.Attribute)) { + Attribute attr = (MixedAttribute) data; + names.add(data.getName()); + values.add(attr.getValue()); + } + } + } finally { + decoder.destroy(); + } + return new FormUrlEncodedRequest(request, new QueryStringDecoder(request.uri()).parameters(), names, values); + } + + protected FormUrlEncodedRequest(FullHttpRequest request, Map> parameters, List names, + List values) { + super(request, parameters); + this.names = names; + this.values = values; + } + + @Override + public String getParameter(CharSequence name) { + for (int i = 0; i < names.size(); i++) { + if (name.equals(names.get(i))) { + return values.get(i); + } + } + return HttpUtil.getParameter(parameters, name); + } + + @Override + public Set getParameterNames() { + HashSet paramNames = new HashSet<>(); + paramNames.addAll(parameters.keySet()); + paramNames.addAll(names); + return Collections.unmodifiableSet(paramNames); + } + + @Override + public Map getParameters() { + HashMap paramMap = new HashMap<>(); + paramMap.putAll(super.getParameters()); + for (int i = 0; i < names.size(); i++) { + paramMap.put(names.get(i), values.get(i)); + } + + return Collections.unmodifiableMap(paramMap); + } +} diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/PostRequest.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/PostRequest.java deleted file mode 100644 index 1dcb088..0000000 --- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/PostRequest.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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. - */ -package org.apache.hyracks.http.server; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.apache.hyracks.http.api.IServletRequest; -import org.apache.hyracks.http.server.utils.HttpUtil; - -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.QueryStringDecoder; -import io.netty.handler.codec.http.multipart.Attribute; -import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder; -import io.netty.handler.codec.http.multipart.InterfaceHttpData; -import io.netty.handler.codec.http.multipart.MixedAttribute; - -public class PostRequest extends BaseRequest implements IServletRequest { - - private static final Logger LOGGER = Logger.getLogger(PostRequest.class.getName()); - - private final List names; - private final List values; - - public static IServletRequest create(FullHttpRequest request) throws IOException { - List names = new ArrayList<>(); - List values = new ArrayList<>(); - HttpPostRequestDecoder decoder = null; - try { - decoder = new HttpPostRequestDecoder(request); - } catch (Exception e) { - //ignore. this means that the body of the POST request does not have key value pairs - LOGGER.log(Level.WARNING, "Failed to decode a post message. Fix the API not to have queries as POST body", - e); - } - if (decoder != null) { - try { - List bodyHttpDatas = decoder.getBodyHttpDatas(); - for (InterfaceHttpData data : bodyHttpDatas) { - if (data.getHttpDataType().equals(InterfaceHttpData.HttpDataType.Attribute)) { - Attribute attr = (MixedAttribute) data; - names.add(data.getName()); - values.add(attr.getValue()); - } - } - } finally { - decoder.destroy(); - } - } - return new PostRequest(request, new QueryStringDecoder(request.uri()).parameters(), names, values); - } - - protected PostRequest(FullHttpRequest request, Map> parameters, List names, - List values) { - super(request, parameters); - this.names = names; - this.values = values; - } - - @Override - public String getParameter(CharSequence name) { - for (int i = 0; i < names.size(); i++) { - if (name.equals(names.get(i))) { - return values.get(i); - } - } - return HttpUtil.getParameter(parameters, name); - } -} 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 c11deef..2babc73 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 @@ -26,11 +26,11 @@ import org.apache.hyracks.http.api.IServletRequest; import org.apache.hyracks.http.api.IServletResponse; import org.apache.hyracks.http.server.BaseRequest; -import org.apache.hyracks.http.server.PostRequest; +import org.apache.hyracks.http.server.FormUrlEncodedRequest; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; public class HttpUtil { @@ -47,6 +47,7 @@ public static class ContentType { public static final String APPLICATION_ADM = "application/x-adm"; public static final String APPLICATION_JSON = "application/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 IMG_PNG = "image/png"; public static final String TEXT_HTML = "text/html"; @@ -57,7 +58,7 @@ } public static String getParameter(Map> parameters, CharSequence name) { - List parameter = parameters.get(name); + List parameter = parameters.get(String.valueOf(name)); if (parameter == null) { return null; } else if (parameter.size() == 1) { @@ -72,7 +73,17 @@ } public static IServletRequest toServletRequest(FullHttpRequest request) throws IOException { - return request.method() == HttpMethod.POST ? PostRequest.create(request) : BaseRequest.create(request); + return ContentType.APPLICATION_X_WWW_FORM_URLENCODED.equals(getContentTypeOnly(request)) + ? FormUrlEncodedRequest.create(request) : BaseRequest.create(request); + } + + public static String getContentTypeOnly(IServletRequest request) { + return getContentTypeOnly(request.getHttpRequest()); + } + + public static String getContentTypeOnly(HttpRequest request) { + String contentType = request.headers().get(HttpHeaderNames.CONTENT_TYPE); + return contentType == null ? null : contentType.split(";")[0]; } public static String getRequestBody(IServletRequest request) { -- To view, visit https://asterix-gerrit.ics.uci.edu/1911 To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I670b815a5276d870f7d538d1ce9d8bef2d0fcf4f Gerrit-PatchSet: 1 Gerrit-Project: asterixdb Gerrit-Branch: master Gerrit-Owner: Michael Blow