diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/batch/exception/BatchDeserializerException.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/batch/exception/BatchDeserializerException.java index 060d47595..4bd35d28d 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/batch/exception/BatchDeserializerException.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/batch/exception/BatchDeserializerException.java @@ -39,8 +39,8 @@ public class BatchDeserializerException extends BatchException { MISSING_CONTENT_TRANSFER_ENCODING, MISSING_CONTENT_TYPE, MISSING_MANDATORY_HEADER, - FORBIDDEN_HEADER, - FORBIDDEN_ABSOLUTE_URI; + FORBIDDEN_HEADER, + INVALID_BASE_URI; @Override public String getKey() { diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/HttpRequestStatusLine.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/HttpRequestStatusLine.java index 36b18a879..74b67cba6 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/HttpRequestStatusLine.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/batch/HttpRequestStatusLine.java @@ -49,11 +49,12 @@ public class HttpRequestStatusLine { private String rawBaseUri; private String rawRequestUri; - public HttpRequestStatusLine(final Line httpStatusLine, final String baseUri, final String serviceResolutionUrir) + public HttpRequestStatusLine(final Line httpStatusLine, final String baseUri, final String serviceResolutionUri) throws BatchDeserializerException { statusLine = httpStatusLine; requestBaseUri = baseUri; - + rawServiceResolutionUri = serviceResolutionUri; + parse(); } @@ -71,27 +72,44 @@ public class HttpRequestStatusLine { } } - private void parseUri(String rawUri, String baseUrl) throws BatchDeserializerException { + private void parseUri(String rawUri, String baseUri) throws BatchDeserializerException { try { final URI uri = new URI(rawUri); if (uri.isAbsolute()) { - throw new BatchDeserializerException("Forbidden absolute uri", MessageKeys.FORBIDDEN_ABSOLUTE_URI, statusLine - .getLineNumber()); + parseAbsoluteUri(rawUri, baseUri); } else { - final Matcher relativeUriMatcher = PATTERN_RELATIVE_URI.matcher(rawUri); - - if (relativeUriMatcher.matches()) { - buildUri(relativeUriMatcher.group(1), relativeUriMatcher.group(2)); - } else { - throw new BatchDeserializerException("Malformed uri", MessageKeys.INVALID_URI, statusLine.getLineNumber()); - } + parseRelativeUri(rawUri); } } catch (URISyntaxException e) { throw new BatchDeserializerException("Malformed uri", MessageKeys.INVALID_URI, statusLine.getLineNumber()); } } + private void parseAbsoluteUri(String rawUri, String baseUri) throws BatchDeserializerException { + if (rawUri.startsWith(baseUri)) { + final String relativeUri = removeLeadingSlash(rawUri.substring(baseUri.length())); + parseRelativeUri(relativeUri); + } else { + throw new BatchDeserializerException("Base uri do not match", MessageKeys.INVALID_BASE_URI, statusLine + .getLineNumber()); + } + } + + private String removeLeadingSlash(String value) { + return (value.length() > 0 && value.charAt(0) == '/') ? value.substring(1) : value; + } + + private void parseRelativeUri(String rawUri) throws BatchDeserializerException { + final Matcher relativeUriMatcher = PATTERN_RELATIVE_URI.matcher(rawUri); + + if (relativeUriMatcher.matches()) { + buildUri(relativeUriMatcher.group(1), relativeUriMatcher.group(2)); + } else { + throw new BatchDeserializerException("Malformed uri", MessageKeys.INVALID_URI, statusLine.getLineNumber()); + } + } + private void buildUri(final String oDataPath, final String queryOptions) throws BatchDeserializerException { rawBaseUri = requestBaseUri; rawODataPath = "/" + oDataPath; diff --git a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties index e28c3e5ba..c61619d98 100644 --- a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties +++ b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties @@ -119,6 +119,6 @@ BatchDeserializerException.MISSING_CONTENT_ID=Missing content-id at line '%1$s'. BatchDeserializerException.MISSING_CONTENT_TRANSFER_ENCODING=Missing content transfer encoding at line '%1$s'. BatchDeserializerException.MISSING_CONTENT_TYPE=Missing content-type at line '%1$s'. BatchDeserializerException.MISSING_MANDATORY_HEADER=Missing mandatory header at line '%1$s'. -BatchDeserializerException.FORBIDDEN_ABSOLUTE_URI=Forbidden absolute request URI at line '%1$s'. - +BatchDeserializerException.INVALID_BASE_URI=The base URI do not match the service base URI at line '%1$s'. + BatchSerializerExecption.MISSING_CONTENT_ID=Each request within a change set required exactly one content id. \ No newline at end of file diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/batchhandler/MockedBatchHandlerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/batchhandler/MockedBatchHandlerTest.java index 3ba07148c..8d4b357a4 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/batchhandler/MockedBatchHandlerTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/batchhandler/MockedBatchHandlerTest.java @@ -116,7 +116,7 @@ public class MockedBatchHandlerTest { + "Content-Transfer-Encoding: binary" + CRLF + "Content-Id: 5" + CRLF + CRLF - + "POST $1/NavPropertyETTwoPrimMany HTTP/1.1" + CRLF + + "POST http://localhost:8080/odata/$1/NavPropertyETTwoPrimMany HTTP/1.1" + CRLF + "Content-Type: application/json;odata=verbose" + CRLF + CRLF + CRLF @@ -276,7 +276,7 @@ public class MockedBatchHandlerTest { + "Content-Transfer-Encoding: binary" + CRLF + "Content-Id: 1" + CRLF + CRLF - + "PUT ESAllPrim(2) HTTP/1.1" + CRLF + + "PUT http://localhost:8080/odata/ESAllPrim(2) HTTP/1.1" + CRLF + "Content-Type: application/json;odata=verbose" + CRLF + CRLF + CRLF diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/BatchParserCommonTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchParserCommonTest.java similarity index 99% rename from lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/BatchParserCommonTest.java rename to lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchParserCommonTest.java index 35998cbd3..294283fa0 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/BatchParserCommonTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchParserCommonTest.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.olingo.server.core.deserializer; +package org.apache.olingo.server.core.deserializer.batch; import static org.junit.Assert.*; diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/BatchRequestParserTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchRequestParserTest.java similarity index 98% rename from lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/BatchRequestParserTest.java rename to lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchRequestParserTest.java index 219167da6..628274228 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/BatchRequestParserTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BatchRequestParserTest.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.olingo.server.core.deserializer; +package org.apache.olingo.server.core.deserializer.batch; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -188,7 +188,32 @@ public class BatchRequestParserTest { } } } - + + @Test + public void testAbsoluteUri() throws Exception { + final String batch = "" + + "--batch_8194-cf13-1f56" + CRLF + + MIME_HEADERS + + CRLF + + "GET http://localhost/odata/Employees('1')/EmployeeName?$top=1 HTTP/1.1" + CRLF + + CRLF + + CRLF + + "--batch_8194-cf13-1f56--"; + + final List batchRequestParts = parse(batch); + + assertEquals(1, batchRequestParts.size()); + final BatchRequestPart part = batchRequestParts.get(0); + + assertEquals(1, part.getRequests().size()); + final ODataRequest request = part.getRequests().get(0); + + assertEquals("/Employees('1')/EmployeeName", request.getRawODataPath()); + assertEquals("$top=1", request.getRawQueryPath()); + assertEquals("http://localhost/odata/Employees('1')/EmployeeName?$top=1", request.getRawRequestUri()); + assertEquals("http://localhost/odata", request.getRawBaseUri()); + } + @Test public void testBoundaryParameterWithQuotas() throws Exception { final String contentType = "multipart/mixed; boundary=\"batch_1.2+34:2j)0?\""; @@ -527,8 +552,7 @@ public class BatchRequestParserTest { + "Content-Id: 1" + CRLF + CRLF + "POST Employees('2') HTTP/1.1" + CRLF - + "Content-Type: application/json;odata=verbose" + CRLF - + "MaxDataServiceVersion: 2.0" + CRLF + + "Content-Type: application/json;odata=verbose" + CRLF + "MaxDataServiceVersion: 2.0" + CRLF + "Content-Id: 2" + CRLF + "--changeset_f980-1cb6-94dd--" + CRLF @@ -602,20 +626,6 @@ public class BatchRequestParserTest { parseInvalidBatchBody(batch, BatchDeserializerException.MessageKeys.MISSING_CLOSE_DELIMITER); } - @Test - public void testAbsoluteUri() throws Exception { - final String batch = "" - + "--batch_8194-cf13-1f56" + CRLF - + MIME_HEADERS - + CRLF - + "GET http://localhost/aa/odata/Employees('1')/EmployeeName HTTP/1.1" + CRLF - + CRLF - + CRLF - + "--batch_8194-cf13-1f56--"; - - parseInvalidBatchBody(batch, BatchDeserializerException.MessageKeys.FORBIDDEN_ABSOLUTE_URI); - } - @Test public void testUriWithAbsolutePath() throws Exception { final String batch = "" diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/BufferedReaderIncludingLineEndingsTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BufferedReaderIncludingLineEndingsTest.java similarity index 99% rename from lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/BufferedReaderIncludingLineEndingsTest.java rename to lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BufferedReaderIncludingLineEndingsTest.java index 83b76ef92..efc3714cd 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/BufferedReaderIncludingLineEndingsTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/BufferedReaderIncludingLineEndingsTest.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.olingo.server.core.deserializer; +package org.apache.olingo.server.core.deserializer.batch; import static org.junit.Assert.*; diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/HeaderTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/HeaderTest.java similarity index 99% rename from lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/HeaderTest.java rename to lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/HeaderTest.java index 7947f5564..282251e16 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/HeaderTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/HeaderTest.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.olingo.server.core.deserializer; +package org.apache.olingo.server.core.deserializer.batch; import static org.junit.Assert.*; diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/HttpRequestStatusLineTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/HttpRequestStatusLineTest.java new file mode 100644 index 000000000..38da3a916 --- /dev/null +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/batch/HttpRequestStatusLineTest.java @@ -0,0 +1,108 @@ +/* + * 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.olingo.server.core.deserializer.batch; + +import static org.junit.Assert.*; + +import org.apache.olingo.commons.api.http.HttpMethod; +import org.apache.olingo.server.api.batch.exception.BatchDeserializerException; +import org.apache.olingo.server.api.batch.exception.BatchDeserializerException.MessageKeys; +import org.junit.Test; + +public class HttpRequestStatusLineTest { + + private static final String HTTP_VERSION = "HTTP/1.1"; + private static final String SPACE = " "; + private String baseUri = "http://localhost/odata"; + private String serviceResolutionUri = ""; + + @Test + public void testAbsolute() throws BatchDeserializerException { + final HttpRequestStatusLine line = parse("http://localhost/odata/Employee?$top=2"); + assertEquals("$top=2", line.getRawQueryPath()); + assertEquals("/Employee", line.getRawODataPath()); + assertEquals("http://localhost/odata/Employee?$top=2", line.getRawRequestUri()); + assertEquals(baseUri, line.getRawBaseUri()); + assertEquals(serviceResolutionUri, line.getRawServiceResolutionUri()); + } + + @Test + public void testAbsoluteWithRelativePath() throws BatchDeserializerException { + final HttpRequestStatusLine line = parse("http://localhost/odata../../Employee?$top=2"); + assertEquals("/../../Employee", line.getRawODataPath()); + assertEquals("$top=2", line.getRawQueryPath()); + assertEquals("http://localhost/odata/../../Employee?$top=2", line.getRawRequestUri()); + assertEquals(baseUri, line.getRawBaseUri()); + assertEquals(serviceResolutionUri, line.getRawServiceResolutionUri()); + } + + @Test + public void testRelativeWithDots() throws BatchDeserializerException { + final HttpRequestStatusLine line = parse("../../Employee?$top=2"); + assertEquals("/../../Employee", line.getRawODataPath()); + assertEquals("$top=2", line.getRawQueryPath()); + assertEquals("http://localhost/odata/../../Employee?$top=2", line.getRawRequestUri()); + assertEquals(baseUri, line.getRawBaseUri()); + assertEquals(serviceResolutionUri, line.getRawServiceResolutionUri()); + } + + @Test + public void testRelative() throws BatchDeserializerException { + final HttpRequestStatusLine line = parse("Employee?$top=2"); + assertEquals("$top=2", line.getRawQueryPath()); + assertEquals("/Employee", line.getRawODataPath()); + assertEquals("http://localhost/odata/Employee?$top=2", line.getRawRequestUri()); + assertEquals(baseUri, line.getRawBaseUri()); + assertEquals(serviceResolutionUri, line.getRawServiceResolutionUri()); + } + + @Test + public void testRelativeMultipleSegements() throws BatchDeserializerException { + final HttpRequestStatusLine line = parse("Employee/Manager/EmployeeName?$top=2"); + assertEquals("$top=2", line.getRawQueryPath()); + assertEquals("/Employee/Manager/EmployeeName", line.getRawODataPath()); + assertEquals("http://localhost/odata/Employee/Manager/EmployeeName?$top=2", line.getRawRequestUri()); + assertEquals(baseUri, line.getRawBaseUri()); + assertEquals(serviceResolutionUri, line.getRawServiceResolutionUri()); + } + + @Test + public void testOtherBaseUri() throws BatchDeserializerException { + parseFail("http://otherhost/odata/Employee?$top=2", MessageKeys.INVALID_BASE_URI); + } + + @Test + public void testInvalidRelative() throws BatchDeserializerException { + parseFail("/Employee?$top=2", MessageKeys.INVALID_URI); + } + + HttpRequestStatusLine parse(final String uri) throws BatchDeserializerException { + Line statusline = new Line(HttpMethod.GET.toString().toUpperCase() + SPACE + uri + SPACE + HTTP_VERSION, 0); + return new HttpRequestStatusLine(statusline, baseUri, serviceResolutionUri); + } + + void parseFail(final String uri, MessageKeys messageKey) { + try { + parse(uri); + fail("Expceted exception"); + } catch (BatchDeserializerException e) { + assertEquals(messageKey, e.getMessageKey()); + } + } +}