[OLINGO-472] Absolute Uris are allowed, if the base path is literally equals

Signed-off-by: Christian Amend <chrisam@apache.org>
This commit is contained in:
Christian Holzer 2014-12-08 15:48:33 +01:00 committed by Christian Amend
parent 19a7738a71
commit ace57fd586
9 changed files with 175 additions and 39 deletions

View File

@ -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() {

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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.*;

View File

@ -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<BatchRequestPart> 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 = ""

View File

@ -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.*;

View File

@ -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.*;

View File

@ -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());
}
}
}