Repository: olingo-odata4 Updated Branches: refs/heads/master 860d418fd -> 9c61e2237
OLINGO-908: Adding 'Allow' header in situations of returning 405 for the submitted request Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/9c61e223 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/9c61e223 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/9c61e223 Branch: refs/heads/master Commit: 9c61e223756f40a0a87ebc2cf6297ef5fd69fc70 Parents: 860d418 Author: Ramesh Reddy <[email protected]> Authored: Wed Mar 16 12:27:04 2016 -0500 Committer: Ramesh Reddy <[email protected]> Committed: Wed Mar 16 12:27:04 2016 -0500 ---------------------------------------------------------------------- .../olingo/server/core/ServiceRequest.java | 56 ++++++- .../server/core/requests/ActionRequest.java | 11 +- .../server/core/requests/BatchRequest.java | 10 +- .../server/core/requests/DataRequest.java | 156 +++++++++++++------ .../server/core/requests/FunctionRequest.java | 25 ++- .../server/core/requests/MediaRequest.java | 16 +- .../server/core/requests/MetadataRequest.java | 5 +- .../core/requests/ServiceDocumentRequest.java | 6 +- .../server/example/TripPinServiceTest.java | 8 + 9 files changed, 211 insertions(+), 82 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c61e223/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceRequest.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceRequest.java index f6b3296..6242975 100644 --- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceRequest.java +++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceRequest.java @@ -81,10 +81,38 @@ public abstract class ServiceRequest { this.uriInfo = uriInfo; } - public boolean allowedMethod() { - return isGET(); + public static boolean assertHttpMethod(HttpMethod issued, HttpMethod[] allowedMethods, + ODataResponse response) throws ODataHandlerException { + boolean allowed = false; + for (HttpMethod method :allowedMethods) { + if (issued.equals(method)) { + allowed = true; + } + } + if (!allowed) { + return methodNotAllowed(response, issued, null, allowedMethods); + } + return true; } + + public boolean assertHttpMethod(ODataResponse response) throws ODataHandlerException { + boolean allowed = false; + HttpMethod issued = this.request.getMethod(); + for (HttpMethod method :allowedMethods()) { + if (issued.equals(method)) { + allowed = true; + } + } + if (!allowed) { + return methodNotAllowed(response, issued, null, allowedMethods()); + } + return true; + } + public HttpMethod[] allowedMethods() { + return new HttpMethod[] {HttpMethod.GET}; + } + public CustomContentTypeSupport getCustomContentTypeSupport() { return this.customContentType; } @@ -113,10 +141,22 @@ public abstract class ServiceRequest { public abstract ContentType getResponseContentType() throws ContentNegotiatorException; - public void methodNotAllowed() throws ODataHandlerException { - throw new ODataHandlerException("HTTP method " + this.request.getMethod() + " is not allowed.", - ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, this.request.getMethod() - .toString()); + public static boolean methodNotAllowed(ODataResponse response, HttpMethod issued, String reason, + HttpMethod... allowed) throws ODataHandlerException { + + StringBuilder sb = new StringBuilder(); + for (HttpMethod method:allowed) { + if (sb.length() > 0) { + sb.append(","); + } + sb.append(method.name()); + } + response.setHeader("Allow", sb.toString()); + if (reason == null) { + reason = "HTTP method " + issued + " is not allowed."; + } + throw new ODataHandlerException(reason, + ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, issued.name()); } public void notImplemented() throws ODataHandlerException { @@ -143,6 +183,10 @@ public abstract class ServiceRequest { protected boolean isPOST() { return this.request.getMethod() == HttpMethod.POST; } + + protected HttpMethod httpMethod() { + return this.request.getMethod(); + } private static FullQualifiedName XML10_CHAR_REPLACE_FQN = new FullQualifiedName( "org.apache.olingo.v1.xml10-incompatible-char-replacement"); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c61e223/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ActionRequest.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ActionRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ActionRequest.java index 501b110..0dc61b8 100644 --- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ActionRequest.java +++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ActionRequest.java @@ -27,6 +27,7 @@ import org.apache.olingo.commons.api.data.ContextURL; import org.apache.olingo.commons.api.data.Parameter; import org.apache.olingo.commons.api.edm.EdmAction; import org.apache.olingo.commons.api.edm.EdmReturnType; +import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataApplicationException; import org.apache.olingo.server.api.ODataLibraryException; @@ -54,9 +55,9 @@ public class ActionRequest extends OperationRequest { public void execute(ServiceHandler handler, ODataResponse response) throws ODataLibraryException, ODataApplicationException { - if (!allowedMethod()) { - methodNotAllowed(); - } + // check for valid HTTP Verb + assertHttpMethod(response); + // Actions MAY return data but MUST NOT be further composed with additional // path segments. // On success, the response is 201 Created for actions that create entities, @@ -85,9 +86,9 @@ public class ActionRequest extends OperationRequest { } @Override - public boolean allowedMethod() { + public HttpMethod[] allowedMethods() { // 11.5.4.1 Invoking an Action - only allows POST - return (isPOST()); + return new HttpMethod[] {HttpMethod.POST}; } @SuppressWarnings("unchecked") http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c61e223/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/BatchRequest.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/BatchRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/BatchRequest.java index 2215594..8394a54 100644 --- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/BatchRequest.java +++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/BatchRequest.java @@ -26,6 +26,7 @@ import java.util.UUID; import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataApplicationException; @@ -57,9 +58,8 @@ public class BatchRequest extends ServiceRequest { public void execute(ServiceHandler handler, ODataResponse response) throws ODataLibraryException, ODataApplicationException { - if (!allowedMethod()) { - methodNotAllowed(); - } + // check for valid HTTP Verb + assertHttpMethod(response); validateContentType(); boolean continueOnError = isContinueOnError(); @@ -165,8 +165,8 @@ public class BatchRequest extends ServiceRequest { } @Override - public boolean allowedMethod() { - return isPOST(); + public HttpMethod[] allowedMethods() { + return new HttpMethod[] {HttpMethod.POST}; } private void validateContentType() throws ODataApplicationException { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c61e223/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java index 45e1ed6..fecc8b8 100644 --- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java +++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java @@ -46,6 +46,7 @@ import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.ex.ODataRuntimeException; import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataApplicationException; import org.apache.olingo.server.api.ODataLibraryException; @@ -71,6 +72,7 @@ import org.apache.olingo.server.api.uri.UriResourceProperty; import org.apache.olingo.server.api.uri.UriResourceSingleton; import org.apache.olingo.server.core.ContentNegotiator; import org.apache.olingo.server.core.ContentNegotiatorException; +import org.apache.olingo.server.core.ODataHandlerException; import org.apache.olingo.server.core.ReturnRepresentation; import org.apache.olingo.server.core.ServiceHandler; import org.apache.olingo.server.core.ServiceRequest; @@ -99,8 +101,10 @@ public class DataRequest extends ServiceRequest { * This sub-categorizes the request so that code can be simplified */ interface RequestType { - public boolean allowedMethod(); - + public HttpMethod[] allowedMethods(); + + public boolean assertHttpMethod(ODataResponse response) throws ODataHandlerException; + public ContentType getResponseContentType() throws ContentNegotiatorException; public ContextURL getContextURL(OData odata) throws SerializerException; @@ -212,6 +216,7 @@ public class DataRequest extends ServiceRequest { return valueRequest; } + /* private boolean hasMediaStream() { return this.uriResourceEntitySet != null && this.uriResourceEntitySet.getEntityType().hasStream(); } @@ -219,15 +224,21 @@ public class DataRequest extends ServiceRequest { private InputStream getMediaStream() { return this.request.getBody(); } - + */ + public void setValueRequest(boolean valueRequest) { this.valueRequest = valueRequest; this.type = new ValueRequest(); } + public boolean assertHttpMethod(ODataResponse response) + throws ODataHandlerException { + return this.type.assertHttpMethod(response); + } + @Override - public boolean allowedMethod() { - return this.type.allowedMethod(); + public HttpMethod[] allowedMethods() { + return this.type.allowedMethods(); } public ContextURL getContextURL(OData odata) throws SerializerException { @@ -238,9 +249,8 @@ public class DataRequest extends ServiceRequest { public void execute(ServiceHandler handler, ODataResponse response) throws ODataLibraryException, ODataApplicationException { - if (!this.type.allowedMethod()) { - methodNotAllowed(); - } + // check for valid HTTP Verb + assertHttpMethod(response); this.type.execute(handler, response); } @@ -273,26 +283,37 @@ public class DataRequest extends ServiceRequest { class EntityRequest implements RequestType { @Override - public boolean allowedMethod() { + public boolean assertHttpMethod(ODataResponse response) throws ODataHandlerException { // the create/update/delete to navigation property is done through references // see # 11.4.6 if (!getNavigations().isEmpty() && !isGET()) { - return false; + return methodNotAllowed(response, httpMethod(), + "create/update/delete to navigation property is done through references", + allowedMethods()); } if ((isGET() || isDELETE()) && getReturnRepresentation() != ReturnRepresentation.NONE) { - return false; + return methodNotAllowed(response, httpMethod(), + "Invalid prefer header used", + allowedMethods()); } // in update, delete entity cases, predicate must be there if ((isPATCH() || isPUT() || isDELETE()) && (getKeyPredicates() == null || getKeyPredicates().isEmpty())) { - return false; + return methodNotAllowed(response, httpMethod(), + "No key predicates provided",allowedMethods()); } - return true; + return ServiceRequest.assertHttpMethod(httpMethod(), allowedMethods(), response); } @Override + public HttpMethod[] allowedMethods() { + return new HttpMethod[] { HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, + HttpMethod.PATCH, HttpMethod.DELETE }; + } + + @Override public ContentType getResponseContentType() throws ContentNegotiatorException { return ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), getODataRequest(), getCustomContentTypeSupport(), isCollection() ? RepresentationType.COLLECTION_ENTITY @@ -359,15 +380,20 @@ public class DataRequest extends ServiceRequest { class CountRequest implements RequestType { @Override - public boolean allowedMethod() { + public boolean assertHttpMethod(ODataResponse response) throws ODataHandlerException { if (getReturnRepresentation() != ReturnRepresentation.NONE) { - return false; + return methodNotAllowed(response, httpMethod(), "Invalid Prefer header used", + allowedMethods()); } - - return isGET(); + return ServiceRequest.assertHttpMethod(httpMethod(), allowedMethods(), response); } @Override + public HttpMethod[] allowedMethods() { + return new HttpMethod[] { HttpMethod.GET}; + } + + @Override public ContentType getResponseContentType() throws ContentNegotiatorException { return ContentType.TEXT_PLAIN; } @@ -390,35 +416,42 @@ public class DataRequest extends ServiceRequest { class ReferenceRequest implements RequestType { @Override - public boolean allowedMethod() { + public boolean assertHttpMethod(ODataResponse response) throws ODataHandlerException { if ((isGET() || isDELETE()) && getReturnRepresentation() != ReturnRepresentation.NONE) { - return false; + return methodNotAllowed(response, httpMethod(), "Invalid Prefer header used", + allowedMethods()); } // references are only allowed on the navigation properties if (getNavigations().isEmpty()) { - return false; + return methodNotAllowed(response, httpMethod(), + "References can be only used on navigation properties", + allowedMethods()); } // 11.4.6.1 - post allowed on only collection valued navigation if (isPOST() && !getNavigations().getLast().isCollection()) { - return false; + return methodNotAllowed(response, httpMethod(), + "POST only allowed on collection valued navigation", + allowedMethods()); } // 11.4.6.3 - PUT allowed on single valued navigation if (isPUT() && getNavigations().getLast().isCollection()) { - return false; - } - - // No defined behavior in spec - if (isPATCH()) { - return false; + return methodNotAllowed(response, httpMethod(), + "PUT only allowed on single valued navigation", allowedMethods()); } - - return true; + //PATCH is not defined in spec + return ServiceRequest.assertHttpMethod(httpMethod(), allowedMethods(), response); } @Override + public HttpMethod[] allowedMethods() { + return new HttpMethod[] { HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, + HttpMethod.DELETE }; + } + + @Override public ContentType getResponseContentType() throws ContentNegotiatorException { return ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), getODataRequest(), getCustomContentTypeSupport(), isCollection() ? RepresentationType.COLLECTION_REFERENCE @@ -486,26 +519,34 @@ public class DataRequest extends ServiceRequest { class PropertyRequest implements RequestType { @Override - public boolean allowedMethod() { - if ((isGET() || isDELETE() || isPropertyStream()) && getReturnRepresentation() != ReturnRepresentation.NONE) { - return false; + public boolean assertHttpMethod(ODataResponse response) throws ODataHandlerException { + if ((isGET() || isDELETE() || isPropertyStream()) + && getReturnRepresentation() != ReturnRepresentation.NONE) { + return methodNotAllowed(response, httpMethod(), "Invalid Prefer header used", + allowedMethods()); } // create of properties is not allowed, // only read, update, delete. Note that delete is // same as update with null - if (isPOST()) { - return false; - } // 11.4.9.4, collection properties are not supported with merge if (isPATCH() && (isCollection() || isPropertyStream())) { - return false; + return methodNotAllowed(response, httpMethod(), + "collection properties are not supported for merge", + allowedMethods()); } - return true; + + return ServiceRequest.assertHttpMethod(httpMethod(), allowedMethods(), response); } @Override + public HttpMethod[] allowedMethods() { + return new HttpMethod[] { HttpMethod.GET, HttpMethod.PUT, + HttpMethod.PATCH, HttpMethod.DELETE }; + } + + @Override public ContentType getResponseContentType() throws ContentNegotiatorException { if (isPropertyComplex()) { return ContentNegotiator.doContentNegotiation(getUriInfo().getFormatOption(), @@ -591,22 +632,31 @@ public class DataRequest extends ServiceRequest { class ValueRequest extends PropertyRequest { @Override - public boolean allowedMethod() { + public boolean assertHttpMethod(ODataResponse response) + throws ODataHandlerException { //part2-url-conventions # 4.7 // Properties of type Edm.Stream already return the raw value of // the media stream and do not support appending the $value segment. if (isPropertyStream() && isGET()) { - return false; + return methodNotAllowed(response, httpMethod(), "Edm.Stream properties do not support $value", + allowedMethods()); } - if ((isGET() || isDELETE() || isPropertyStream()) && getReturnRepresentation() != ReturnRepresentation.NONE) { - return false; + if ((isGET() || isDELETE() || isPropertyStream()) + && getReturnRepresentation() != ReturnRepresentation.NONE) { + return methodNotAllowed(response, httpMethod(), "Invalid Prefer header used", + allowedMethods()); } - return isGET() || isDELETE() || isPUT(); + return ServiceRequest.assertHttpMethod(httpMethod(), allowedMethods(), response); } @Override + public HttpMethod[] allowedMethods() { + return new HttpMethod[] { HttpMethod.GET, HttpMethod.PUT, HttpMethod.DELETE }; + } + + @Override public ContentType getResponseContentType() throws ContentNegotiatorException { RepresentationType valueRepresentationType = uriResourceProperty.getType() == odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Binary) ? @@ -651,10 +701,16 @@ public class DataRequest extends ServiceRequest { class SingletonRequest implements RequestType { @Override - public boolean allowedMethod() { - return isGET(); + public boolean assertHttpMethod(ODataResponse response) + throws ODataHandlerException { + return ServiceRequest.assertHttpMethod(httpMethod(), allowedMethods(), response); } - + + @Override + public HttpMethod[] allowedMethods() { + return new HttpMethod[] {HttpMethod.GET}; + } + @Override public ContentType getResponseContentType() throws ContentNegotiatorException { return ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), getODataRequest(), @@ -685,8 +741,14 @@ public class DataRequest extends ServiceRequest { } @Override - public boolean allowedMethod() { - return isGET(); + public boolean assertHttpMethod(ODataResponse response) + throws ODataHandlerException { + return ServiceRequest.assertHttpMethod(httpMethod(), allowedMethods(), response); + } + + @Override + public HttpMethod[] allowedMethods() { + return new HttpMethod[] {HttpMethod.GET}; } @Override http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c61e223/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/FunctionRequest.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/FunctionRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/FunctionRequest.java index 94275ca..598199a 100644 --- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/FunctionRequest.java +++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/FunctionRequest.java @@ -24,6 +24,7 @@ import java.util.List; import org.apache.olingo.commons.api.data.ContextURL; import org.apache.olingo.commons.api.edm.EdmFunction; import org.apache.olingo.commons.api.edm.EdmReturnType; +import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataApplicationException; import org.apache.olingo.server.api.ODataResponse; @@ -33,7 +34,9 @@ import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions; import org.apache.olingo.server.api.uri.UriParameter; import org.apache.olingo.server.api.uri.UriResourceFunction; import org.apache.olingo.server.core.ContentNegotiatorException; +import org.apache.olingo.server.core.ODataHandlerException; import org.apache.olingo.server.core.ServiceHandler; +import org.apache.olingo.server.core.ServiceRequest; import org.apache.olingo.server.core.responses.EntityResponse; import org.apache.olingo.server.core.responses.EntitySetResponse; import org.apache.olingo.server.core.responses.PropertyResponse; @@ -49,9 +52,8 @@ public class FunctionRequest extends OperationRequest { public void execute(ServiceHandler handler, ODataResponse response) throws ODataLibraryException, ODataApplicationException { - if (!allowedMethod()) { - methodNotAllowed(); - } + // check for valid HTTP Verb + assertHttpMethod(response); // Functions always have return per 11.5.3 if (isReturnTypePrimitive() || isReturnTypeComplex()) { @@ -71,14 +73,25 @@ public class FunctionRequest extends OperationRequest { } @Override - public boolean allowedMethod() { + public boolean assertHttpMethod(ODataResponse response) throws ODataHandlerException { // look for discussion about composable functions in odata-discussion // group with thread "Clarification on "Function" invocations" if (getFunction().isComposable()) { - return (isGET() || isPATCH() || isDELETE() || isPOST() || isPUT()); + boolean allowed = (isGET() || isPATCH() || isDELETE() || isPOST() || isPUT()); + if (!allowed) { + return methodNotAllowed(response,httpMethod(), + "Only composable functions are allowed PATCH, DELETE, POST and PUT methods", + allowedMethods()); + } } - return isGET(); + return ServiceRequest.assertHttpMethod(httpMethod(), allowedMethods(), response); } + + @Override + public HttpMethod[] allowedMethods() { + return new HttpMethod[] { HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, + HttpMethod.PATCH, HttpMethod.DELETE }; + } @SuppressWarnings("unchecked") @Override http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c61e223/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/MediaRequest.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/MediaRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/MediaRequest.java index b5626b5..f868d30 100644 --- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/MediaRequest.java +++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/MediaRequest.java @@ -24,6 +24,7 @@ import java.util.List; import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataApplicationException; import org.apache.olingo.server.api.ODataResponse; @@ -47,9 +48,10 @@ public class MediaRequest extends ServiceRequest { @Override public void execute(ServiceHandler handler, ODataResponse response) throws ODataLibraryException, ODataApplicationException { - if (!allowedMethod()) { - methodNotAllowed(); - } + + // check for valid HTTP Verb + assertHttpMethod(response); + // POST will not be here, because the media is created as part of media // entity creation if (isGET()) { @@ -91,9 +93,9 @@ public class MediaRequest extends ServiceRequest { private InputStream getMediaStream() { return this.request.getBody(); } - + @Override - public boolean allowedMethod() { - return isGET() || isPUT() || isDELETE(); - } + public HttpMethod[] allowedMethods() { + return new HttpMethod[] { HttpMethod.GET, HttpMethod.PUT, HttpMethod.DELETE }; + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c61e223/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/MetadataRequest.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/MetadataRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/MetadataRequest.java index f448942..ec38fa1 100644 --- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/MetadataRequest.java +++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/MetadataRequest.java @@ -52,9 +52,8 @@ public class MetadataRequest extends ServiceRequest { public void execute(ServiceHandler handler, ODataResponse response) throws ODataLibraryException, ODataApplicationException { - if (!allowedMethod()) { - methodNotAllowed(); - } + // check for valid HTTP Verb + assertHttpMethod(response); handler.readMetadata(this, MetadataResponse.getInstance(this, response)); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c61e223/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ServiceDocumentRequest.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ServiceDocumentRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ServiceDocumentRequest.java index c8f484d..805d859 100644 --- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ServiceDocumentRequest.java +++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ServiceDocumentRequest.java @@ -48,9 +48,9 @@ public class ServiceDocumentRequest extends ServiceRequest { public void execute(ServiceHandler handler, ODataResponse response) throws ODataLibraryException, ODataApplicationException { - if (!allowedMethod()) { - methodNotAllowed(); - } + // check for valid HTTP Verb + assertHttpMethod(response); + handler.readServiceDocument(this, ServiceDocumentResponse.getInstace(this, response, getResponseContentType())); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c61e223/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java index 114a1f3..8bb4d5a 100644 --- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java +++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java @@ -320,6 +320,14 @@ public class TripPinServiceTest { HttpResponse response = httpSend(request, 204); EntityUtils.consumeQuietly(response.getEntity()); } + + @Test + public void testAllowHeader() throws Exception { + HttpResponse response = httpGET(baseURL + "/ResetDataSource", 405); + Header[] headers = response.getHeaders("Allow"); + assertEquals("POST", headers[0].getValue()); + EntityUtils.consumeQuietly(response.getEntity()); + } @Test @Ignore public void testFunctionImport() throws Exception {
