Repository: olingo-odata4 Updated Branches: refs/heads/master f7e5a5c71 -> 38f77daa5
[OLINGO-752] Support for + sign as a separator Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/38f77daa Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/38f77daa Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/38f77daa Branch: refs/heads/master Commit: 38f77daa5c555af2012449e1f090a0395bd7a883 Parents: f7e5a5c Author: Archana Rai <archana....@sap.com> Authored: Wed Aug 9 13:37:27 2017 +0530 Committer: Archana Rai <archana....@sap.com> Committed: Wed Aug 9 13:37:27 2017 +0530 ---------------------------------------------------------------------- .../olingo/fit/tecsvc/http/BasicHttpITCase.java | 104 +++++++++++++++++++ .../olingo/server/core/uri/parser/Parser.java | 15 ++- .../server/core/uri/parser/UriDecoder.java | 11 ++ 3 files changed, 128 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/38f77daa/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicHttpITCase.java ---------------------------------------------------------------------- diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicHttpITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicHttpITCase.java index 6d1bf78..bb3bd57 100644 --- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicHttpITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicHttpITCase.java @@ -19,6 +19,7 @@ package org.apache.olingo.fit.tecsvc.http; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -288,4 +289,107 @@ public class BasicHttpITCase extends AbstractBaseTestITCase { assertTrue(content.contains("\"AdditionalPropString\":null")); assertTrue(content.contains("\"@odata.type\":\"#olingo.odata.test1.CTBase\"")); } + + @Test + public void testFilterWithSpaceFormEncoding() throws Exception { + URL url = new URL(SERVICE_URI + + "ESAllPrim?$filter=PropertyInt16%20eq%201&odata-accept-forms-encoding=true"); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod(HttpMethod.GET.name()); + connection.setRequestProperty(HttpHeader.ACCEPT, "application/json;odata.metadata=full"); + connection.connect(); + + assertEquals(HttpStatusCode.OK.getStatusCode(), connection.getResponseCode()); + final String content = IOUtils.toString(connection.getInputStream()); + + assertNotNull(content); + } + + @Test + public void testFilterWithSpaceNoFormEncoding() throws Exception { + URL url = new URL(SERVICE_URI + + "ESAllPrim?$filter=PropertyInt16%20eq%201"); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod(HttpMethod.GET.name()); + connection.setRequestProperty(HttpHeader.ACCEPT, "application/json;odata.metadata=full"); + connection.connect(); + + assertEquals(HttpStatusCode.OK.getStatusCode(), connection.getResponseCode()); + final String content = IOUtils.toString(connection.getInputStream()); + + assertNotNull(content); + } + + @Test + public void testFilterWithFormEncoding() throws Exception { + URL url = new URL(SERVICE_URI + + "ESAllPrim?$filter=PropertyInt16+eq+1&odata-accept-forms-encoding=true"); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod(HttpMethod.GET.name()); + connection.setRequestProperty(HttpHeader.ACCEPT, "application/json;odata.metadata=full"); + connection.connect(); + + assertEquals(HttpStatusCode.OK.getStatusCode(), connection.getResponseCode()); + final String content = IOUtils.toString(connection.getInputStream()); + + assertNotNull(content); + } + + @Test + public void testFilterWithFormEncodingOrderChange() throws Exception { + URL url = new URL(SERVICE_URI + + "ESAllPrim?odata-accept-forms-encoding=true&$filter=PropertyInt16+eq+1"); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod(HttpMethod.GET.name()); + connection.setRequestProperty(HttpHeader.ACCEPT, "application/json;odata.metadata=full"); + connection.connect(); + + assertEquals(HttpStatusCode.OK.getStatusCode(), connection.getResponseCode()); + final String content = IOUtils.toString(connection.getInputStream()); + + assertNotNull(content); + } + + @Test + public void testFilterWithFalseFormEncoding() throws Exception { + URL url = new URL(SERVICE_URI + + "ESAllPrim?$filter=PropertyInt16+eq+1&odata-accept-forms-encoding=false"); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod(HttpMethod.GET.name()); + connection.setRequestProperty(HttpHeader.ACCEPT, "application/json;odata.metadata=full"); + connection.connect(); + + assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), connection.getResponseCode()); + } + + @Test + public void testFilterWithNoFormEncoding() throws Exception { + URL url = new URL(SERVICE_URI + + "ESAllPrim?$filter=PropertyInt16+eq+1"); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod(HttpMethod.GET.name()); + connection.setRequestProperty(HttpHeader.ACCEPT, "application/json;odata.metadata=full"); + connection.connect(); + + assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), connection.getResponseCode()); + } + + @Test + public void testFilterWithInvalidFormEncoding() throws Exception { + URL url = new URL(SERVICE_URI + + "ESAllPrim?$filter=PropertyInt16+eq+1&odata-accept-forms-encoding=qwer"); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod(HttpMethod.GET.name()); + connection.setRequestProperty(HttpHeader.ACCEPT, "application/json;odata.metadata=full"); + connection.connect(); + + assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), connection.getResponseCode()); + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/38f77daa/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java index 4e09dd1..db70142 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java @@ -95,7 +95,7 @@ public class Parser { throws UriParserException, UriValidationException { UriInfoImpl contextUriInfo = new UriInfoImpl(); - + // Read the query options (system and custom options). // This is done before parsing the resource path because the aliases have to be available there. // System query options that can only be parsed with context from the resource path will be post-processed later. @@ -103,8 +103,12 @@ public class Parser { query == null ? Collections.<QueryOption> emptyList() : UriDecoder.splitAndDecodeOptions(query); for (final QueryOption option : options) { final String optionName = option.getName(); + String value = option.getText(); + if(UriDecoder.isFormEncoding()){ + value = getFormEncodedValue(value); + } // Parse the untyped option and retrieve a system-option or alias-option instance (or null for a custom option). - final QueryOption parsedOption = parseOption(optionName, option.getText()); + final QueryOption parsedOption = parseOption(optionName, value); try { contextUriInfo.setQueryOption(parsedOption == null ? option : parsedOption); } catch (final ODataRuntimeException e) { @@ -290,6 +294,13 @@ public class Parser { return contextUriInfo; } + private String getFormEncodedValue(String value) { + if(value.contains("+")){ + value = value.replaceAll("\\+", " "); + } + return value; + } + private QueryOption parseOption(final String optionName, final String optionValue) throws UriParserException, UriValidationException { if (optionName.startsWith(DOLLAR)) { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/38f77daa/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriDecoder.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriDecoder.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriDecoder.java index 9983cca..7d1f975 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriDecoder.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriDecoder.java @@ -28,6 +28,13 @@ import org.apache.olingo.server.core.uri.queryoption.CustomQueryOptionImpl; public class UriDecoder { + private static final String ACCEPT_FORM_ENCODING = "odata-accept-forms-encoding"; + private static boolean formEncoding = false; + + public static boolean isFormEncoding() { + return formEncoding; + } + /** Splits the path string at '/' characters and percent-decodes the resulting path segments. */ protected static List<String> splitAndDecodePath(final String path) throws UriParserSyntaxException { List<String> pathSegmentsDecoded = new ArrayList<String>(); @@ -45,11 +52,15 @@ public class UriDecoder { protected static List<QueryOption> splitAndDecodeOptions(final String queryOptionString) throws UriParserSyntaxException { List<QueryOption> queryOptions = new ArrayList<QueryOption>(); + formEncoding = false; for (final String option : split(queryOptionString, '&')) { final int pos = option.indexOf('='); final String name = pos >= 0 ? option.substring(0, pos) : option; final String text = pos >= 0 ? option.substring(pos + 1) : ""; //OLINGO-846 We trim the query option text to be more lenient to wrong uri constructors + if(ACCEPT_FORM_ENCODING.equals(name)){ + formEncoding = Boolean.parseBoolean(text); + } queryOptions.add(new CustomQueryOptionImpl() .setName(decode(name).trim()) .setText(decode(text).trim()));