Repository: olingo-odata4 Updated Branches: refs/heads/master 081a38001 -> 7715006ea
Content-Type is mandatory in POST/PUT/PATCH requests Change-Id: Icbd3455241b0618339d2418214441e4ab59602c8 Signed-off-by: Michael Bolz <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/30d67c71 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/30d67c71 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/30d67c71 Branch: refs/heads/master Commit: 30d67c71f5b138577d5f499c900db34ba6177720 Parents: 081a380 Author: Klaus Straubinger <[email protected]> Authored: Fri Sep 11 08:45:05 2015 +0200 Committer: Michael Bolz <[email protected]> Committed: Fri Sep 11 09:14:06 2015 +0200 ---------------------------------------------------------------------- .../olingo/server/core/ODataDispatcher.java | 47 ++++++++++++-------- .../server/core/ODataExceptionHelper.java | 3 +- .../server/core/ODataHandlerException.java | 2 + .../server-core-exceptions-i18n.properties | 1 + .../processor/TechnicalEntityProcessor.java | 7 --- .../TechnicalPrimitiveComplexProcessor.java | 1 - .../tecsvc/processor/TechnicalProcessor.java | 2 +- .../olingo/server/core/ODataHandlerTest.java | 9 ++++ 8 files changed, 43 insertions(+), 29 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataDispatcher.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataDispatcher.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataDispatcher.java index 459c1ae..90ec8c2 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataDispatcher.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataDispatcher.java @@ -206,10 +206,9 @@ public class ODataDispatcher { // Only bound actions can have ETag control for the binding parameter. validatePreconditions(request, false); } + final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE), + RepresentationType.ACTION_PARAMETERS, false); final EdmReturnType returnType = action.getReturnType(); - final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); - checkContentTypeSupport(requestFormat, RepresentationType.ACTION_PARAMETERS); - if (returnType == null) { handler.selectProcessor(ActionVoidProcessor.class) .processActionVoid(request, response, uriInfo, requestFormat); @@ -277,8 +276,8 @@ public class ODataDispatcher { .readReferenceCollection(request, response, uriInfo, responseFormat); } else if (isCollection && httpMethod == HttpMethod.POST) { - final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); - checkContentTypeSupport(requestFormat, RepresentationType.REFERENCE); + final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE), + RepresentationType.REFERENCE, true); handler.selectProcessor(ReferenceProcessor.class) .createReference(request, response, uriInfo, requestFormat); @@ -288,8 +287,8 @@ public class ODataDispatcher { handler.selectProcessor(ReferenceProcessor.class).readReference(request, response, uriInfo, responseFormat); } else if (!isCollection && (httpMethod == HttpMethod.PUT || httpMethod == HttpMethod.PATCH)) { - final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); - checkContentTypeSupport(requestFormat, RepresentationType.REFERENCE); + final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE), + RepresentationType.REFERENCE, true); handler.selectProcessor(ReferenceProcessor.class) .updateReference(request, response, uriInfo, requestFormat); @@ -327,8 +326,8 @@ public class ODataDispatcher { .readPrimitiveValue(request, response, uriInfo, requestedContentType); } else if (method == HttpMethod.PUT && resource instanceof UriResourceProperty) { validatePreconditions(request, false); - final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); - checkContentTypeSupport(requestFormat, valueRepresentationType); + final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE), + valueRepresentationType, true); final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, handler.getCustomContentTypeSupport(), valueRepresentationType); handler.selectProcessor(PrimitiveValueProcessor.class) @@ -382,8 +381,8 @@ public class ODataDispatcher { } } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) { validatePreconditions(request, false); - final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); - checkContentTypeSupport(requestFormat, complexRepresentationType); + final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE), + complexRepresentationType, true); final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, handler.getCustomContentTypeSupport(), complexRepresentationType); if (isCollection) { @@ -425,8 +424,8 @@ public class ODataDispatcher { } } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) { validatePreconditions(request, false); - final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); - checkContentTypeSupport(requestFormat, representationType); + final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE), + representationType, true); final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, handler.getCustomContentTypeSupport(), representationType); if (isCollection) { @@ -481,14 +480,15 @@ public class ODataDispatcher { handler.selectProcessor(EntityCollectionProcessor.class) .readEntityCollection(request, response, uriInfo, requestedContentType); } else if (method == HttpMethod.POST) { - final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, handler.getCustomContentTypeSupport(), RepresentationType.ENTITY); if (isMedia) { + final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); handler.selectProcessor(MediaEntityProcessor.class) .createMediaEntity(request, response, uriInfo, requestFormat, responseFormat); } else { - checkContentTypeSupport(requestFormat, RepresentationType.ENTITY); + final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE), + RepresentationType.ENTITY, true); handler.selectProcessor(EntityProcessor.class) .createEntity(request, response, uriInfo, requestFormat, responseFormat); } @@ -504,8 +504,8 @@ public class ODataDispatcher { .readEntity(request, response, uriInfo, requestedContentType); } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) { validatePreconditions(request, false); - final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); - checkContentTypeSupport(requestFormat, RepresentationType.ENTITY); + final ContentType requestFormat = getSupportedContentType(request.getHeader(HttpHeader.CONTENT_TYPE), + RepresentationType.ENTITY, true); final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, handler.getCustomContentTypeSupport(), RepresentationType.ENTITY); handler.selectProcessor(EntityProcessor.class) @@ -542,9 +542,18 @@ public class ODataDispatcher { } } - private void checkContentTypeSupport(final ContentType requestFormat, final RepresentationType representationType) + private ContentType getSupportedContentType(final String contentTypeHeader, + final RepresentationType representationType, final boolean mustNotBeNull) throws ODataHandlerException, ContentNegotiatorException { - ContentNegotiator.checkSupport(requestFormat, handler.getCustomContentTypeSupport(), representationType); + if (contentTypeHeader == null) { + if (mustNotBeNull) { + throw new ODataHandlerException(contentTypeHeader, ODataHandlerException.MessageKeys.MISSING_CONTENT_TYPE); + } + return null; + } + final ContentType contentType = ContentType.parse(contentTypeHeader); + ContentNegotiator.checkSupport(contentType, handler.getCustomContentTypeSupport(), representationType); + return contentType; } private boolean isMedia(final UriResource pathSegment) { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataExceptionHelper.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataExceptionHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataExceptionHelper.java index 830867b..cc03922 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataExceptionHelper.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataExceptionHelper.java @@ -90,7 +90,8 @@ public class ODataExceptionHelper { serverError.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode()); } else if (ODataHandlerException.MessageKeys.ODATA_VERSION_NOT_SUPPORTED.equals(e.getMessageKey()) || ODataHandlerException.MessageKeys.INVALID_HTTP_METHOD.equals(e.getMessageKey()) - || ODataHandlerException.MessageKeys.AMBIGUOUS_XHTTP_METHOD.equals(e.getMessageKey())) { + || ODataHandlerException.MessageKeys.AMBIGUOUS_XHTTP_METHOD.equals(e.getMessageKey()) + || ODataHandlerException.MessageKeys.MISSING_CONTENT_TYPE.equals(e.getMessageKey())) { serverError.setStatusCode(HttpStatusCode.BAD_REQUEST.getStatusCode()); } else if (ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED.equals(e.getMessageKey())) { serverError.setStatusCode(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode()); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java index 62adf19..03c4f9f 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java @@ -35,6 +35,8 @@ public class ODataHandlerException extends ODataLibraryException { PROCESSOR_NOT_IMPLEMENTED, /** no parameter */ FUNCTIONALITY_NOT_IMPLEMENTED, + /** no parameter */ + MISSING_CONTENT_TYPE, /** parameter: content type */ UNSUPPORTED_CONTENT_TYPE, /** parameter: version */ http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties ---------------------------------------------------------------------- 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 f6440fb..a2b92ca 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 @@ -24,6 +24,7 @@ ODataHandlerException.HTTP_METHOD_NOT_ALLOWED=HTTP method '%1$s' not allowed for ODataHandlerException.PROCESSOR_NOT_IMPLEMENTED=No processor for interface '%1$s' registered. ODataHandlerException.FUNCTIONALITY_NOT_IMPLEMENTED=The requested functionality has not been implemented (yet). ODataHandlerException.ODATA_VERSION_NOT_SUPPORTED=OData version '%1$s' is not supported. +ODataHandlerException.MISSING_CONTENT_TYPE=The Content-Type HTTP header must be specified for this request. ODataHandlerException.UNSUPPORTED_CONTENT_TYPE=The content type '%1$s' is not supported for this request. UriParserSyntaxException.MUST_BE_LAST_SEGMENT=The segment '%1$s' must be the last segment. http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java ---------------------------------------------------------------------- diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java index 315623f..d0285c8 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java @@ -146,7 +146,6 @@ public class TechnicalEntityProcessor extends TechnicalProcessor } checkRequestFormat(requestFormat); - // if (odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).hasRespondAsync()) { TechnicalAsyncService asyncService = TechnicalAsyncService.getInstance(); TechnicalEntityProcessor processor = new TechnicalEntityProcessor(dataProvider, serviceMetadata); @@ -154,12 +153,9 @@ public class TechnicalEntityProcessor extends TechnicalProcessor AsyncProcessor<EntityProcessor> asyncProcessor = asyncService.register(processor, EntityProcessor.class); asyncProcessor.prepareFor().createEntity(request, response, uriInfo, requestFormat, responseFormat); String location = asyncProcessor.processAsync(); - // TechnicalAsyncService.acceptedResponse(response, location); - // return; } - // final UriResourceEntitySet resourceEntitySet = (UriResourceEntitySet) uriInfo.getUriResourceParts().get(0); final EdmEntitySet edmEntitySet = resourceEntitySet.getEntitySet(); @@ -227,7 +223,6 @@ public class TechnicalEntityProcessor extends TechnicalProcessor odata.createETagHelper().checkChangePreconditions(entity.getETag(), request.getHeaders(HttpHeader.IF_MATCH), request.getHeaders(HttpHeader.IF_NONE_MATCH)); - checkRequestFormat(requestFormat); final ODataDeserializer deserializer = odata.createDeserializer(requestFormat); final Entity changedEntity = deserializer.entity(request.getBody(), edmEntitySet.getEntityType()).getEntity(); @@ -592,8 +587,6 @@ public class TechnicalEntityProcessor extends TechnicalProcessor private ContextURL getContextUrl(String rawODataPath, final EdmEntitySet entitySet, final EdmEntityType entityType, final boolean isSingleEntity, final ExpandOption expand, final SelectOption select) throws ODataLibraryException { - // - // Builder builder = ContextURL.with().oDataPath(rawODataPath); builder = entitySet == null ? isSingleEntity ? builder.type(entityType) : builder.asCollection().type(entityType) : http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java ---------------------------------------------------------------------- diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java index cf4b38e..e6a8e90 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java @@ -287,7 +287,6 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor Property property = getPropertyData(entity, path); - checkRequestFormat(requestFormat); if (representationType == RepresentationType.VALUE) { final FixedFormatDeserializer deserializer = odata.createFixedFormatDeserializer(); final Object value = edmProperty.getType() == odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Binary) ? http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java ---------------------------------------------------------------------- diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java index af82eed..f61f30a 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java @@ -73,7 +73,7 @@ public abstract class TechnicalProcessor implements Processor { EdmEntitySet entitySet = null; final List<UriResource> resourcePaths = uriInfo.getUriResourceParts(); - // First must be entity set or function import. + // First must be an entity, an entity collection, a function import, or an action import. blockTypeFilters(resourcePaths.get(0)); if (resourcePaths.get(0) instanceof UriResourceEntitySet) { entitySet = ((UriResourceEntitySet) resourcePaths.get(0)).getEntitySet(); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/30d67c71/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java ---------------------------------------------------------------------- diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java index b6c6a81..031d32b 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java @@ -688,6 +688,15 @@ public class ODataHandlerTest { } @Test + public void noRequestContentType() throws Exception { + EntityProcessor processor = mock(EntityProcessor.class); + final ODataResponse response = dispatch(HttpMethod.POST, "ESAllPrim", null, + HttpHeader.CONTENT_TYPE, null, processor); + verifyZeroInteractions(processor); + assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), response.getStatusCode()); + } + + @Test public void unsupportedRequestContentType() throws Exception { EntityProcessor processor = mock(EntityProcessor.class); ErrorProcessor errorProcessor = mock(ErrorProcessor.class);
