From a812fd97808299ed90e388e83c469d5f3d8348c3 Mon Sep 17 00:00:00 2001 From: Jozef Gloncak Date: Tue, 18 Feb 2014 14:05:44 +0100 Subject: [PATCH] Exception for URI /restconf/operations/module_name:rpc ended with slash If URI of type /restconf/operations/module_name:rpc ends with slash character (/) then exception with HTTP return code 404 and text "Identifier IDENTIFIER_NAME can't contain slash character (/). If slash is part of identifier name then use %2F placeholder." Change-Id: Idbed90515280b414c10d28dc608faeee24986a29 Signed-off-by: Jozef Gloncak --- .../sal/rest/api/RestconfService.java | 4 ++-- .../sal/restconf/impl/ControllerContext.xtend | 8 ++++++- .../sal/restconf/impl/RestconfImpl.xtend | 22 ++++++++++++++----- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java index f6c39bf8c5..0683c45ebc 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java @@ -94,14 +94,14 @@ public interface RestconfService { @Consumes({Draft02.MediaTypes.OPERATION+JSON, Draft02.MediaTypes.OPERATION+XML, Draft02.MediaTypes.DATA+JSON, Draft02.MediaTypes.DATA+XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML}) - public StructuredData invokeRpc(@PathParam("identifier") String identifier, CompositeNode payload); + public StructuredData invokeRpc(@Encoded @PathParam("identifier") String identifier, CompositeNode payload); @POST @Path("/operations/{identifier:.+}") @Produces({Draft02.MediaTypes.OPERATION+JSON, Draft02.MediaTypes.OPERATION+XML, Draft02.MediaTypes.DATA+JSON, Draft02.MediaTypes.DATA+XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML}) - public StructuredData invokeRpc(@PathParam("identifier") String identifier, @DefaultValue("") String noPayload); + public StructuredData invokeRpc(@Encoded @PathParam("identifier") String identifier, @DefaultValue("") String noPayload); @GET @Path("/config/{identifier:.+}") diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend index 482dcf8e8b..9b5c507811 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend @@ -356,7 +356,6 @@ class ControllerContext implements SchemaServiceListener { private def toUriString(Object object) { if(object === null) return ""; -// return object.toString.replace("/",URI_SLASH_PLACEHOLDER) return URLEncoder.encode(object.toString,URI_ENCODING_CHAR_SET) } @@ -620,6 +619,13 @@ class ControllerContext implements SchemaServiceListener { decodedPathArgs.add(URLDecoder.decode(pathArg, URI_ENCODING_CHAR_SET)) } return decodedPathArgs + } + + def urlPathArgDecode(String pathArg) { + if (pathArg !== null) { + return URLDecoder.decode(pathArg, URI_ENCODING_CHAR_SET) + } + return null } } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend index cfbce736fb..e09dc7ac01 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend @@ -230,10 +230,7 @@ class RestconfImpl implements RestconfService { } override invokeRpc(String identifier, CompositeNode payload) { - val rpc = identifier.rpcDefinition - if (rpc === null) { - throw new ResponseException(NOT_FOUND, "RPC does not exist."); - } + val rpc = resolveIdentifierInInvokeRpc(identifier) if (rpc.QName.namespace.toString == SAL_REMOTE_NAMESPACE && rpc.QName.localName == SAL_REMOTE_RPC_SUBSRCIBE) { val value = normalizeNode(payload, rpc.input, null) val pathNode = value?.getFirstSimpleByName(QName.create(rpc.QName, "path")) @@ -267,7 +264,22 @@ class RestconfImpl implements RestconfService { if (!noPayload.nullOrEmpty) { throw new ResponseException(UNSUPPORTED_MEDIA_TYPE, "Content-Type contains unsupported Media Type."); } - return callRpc(identifier.rpcDefinition, null) + val rpc = resolveIdentifierInInvokeRpc(identifier) + return callRpc(rpc, null) + } + + def resolveIdentifierInInvokeRpc(String identifier) { + if (identifier.indexOf("/") === -1) { + val identifierDecoded = identifier.urlPathArgDecode + val rpc = identifierDecoded.rpcDefinition + if (rpc !== null) { + return rpc + } + throw new ResponseException(NOT_FOUND, "RPC does not exist."); + } + val slashErrorMsg = String.format("Identifier %n%s%ncan't contain slash character (/). + + If slash is part of identifier name then use %2F placeholder.",identifier) + throw new ResponseException(NOT_FOUND, slashErrorMsg); } private def StructuredData callRpc(RpcDefinition rpc, CompositeNode payload) { -- 2.36.6