You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ds...@apache.org on 2015/11/03 00:46:27 UTC

[7/8] incubator-geode git commit: GEODE-381 enable gfsh https usage through SSL terminated environments

GEODE-381 enable gfsh https usage through SSL terminated environments


Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/e9aa18bd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/e9aa18bd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/e9aa18bd

Branch: refs/heads/feature/GEODE-409
Commit: e9aa18bdbd8426d0d8dbede7e9ad68933f378be4
Parents: 8f96cf7
Author: Jens Deppe <jd...@gopivotal.com>
Authored: Mon Oct 5 15:01:17 2015 -0700
Committer: Jens Deppe <jd...@pivotal.io>
Committed: Fri Oct 30 09:17:14 2015 -0700

----------------------------------------------------------------------
 .../internal/cli/commands/ShellCommands.java    |   7 +-
 .../controllers/AbstractCommandsController.java |   7 +-
 .../controllers/ShellCommandsController.java    | 178 ++++++++++---------
 gemfire-web/build.gradle                        |   4 +-
 .../ShellCommandsControllerJUnitTest.java       |  47 +++--
 5 files changed, 140 insertions(+), 103 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e9aa18bd/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/ShellCommands.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/ShellCommands.java b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/ShellCommands.java
index 43e85f4..edab207 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/ShellCommands.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/ShellCommands.java
@@ -206,10 +206,13 @@ public class ShellCommands implements CommandMarker {
             url = url.replace("http:", "https:");
           }
         }
-        
+
+        // This is so that SSL termination results in https URLs being returned
+        String query = (url.startsWith("https")) ? "?scheme=https" : "";
+
         LogWrapper.getInstance().warning(String.format("Sending HTTP request for Link Index at (%1$s)...", url.concat("/index")));
 
-        LinkIndex linkIndex = new SimpleHttpRequester(CONNECT_LOCATOR_TIMEOUT_MS).get(url.concat("/index"), LinkIndex.class);
+        LinkIndex linkIndex = new SimpleHttpRequester(CONNECT_LOCATOR_TIMEOUT_MS).get(url.concat("/index").concat(query), LinkIndex.class);
 
         LogWrapper.getInstance().warning(String.format("Received Link Index (%1$s)", linkIndex.toString()));
 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e9aa18bd/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/AbstractCommandsController.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/AbstractCommandsController.java b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/AbstractCommandsController.java
index 74a9bff..41a890a 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/AbstractCommandsController.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/AbstractCommandsController.java
@@ -57,6 +57,7 @@ import org.springframework.web.bind.annotation.InitBinder;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.context.request.WebRequest;
 import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+import org.springframework.web.util.UriComponentsBuilder;
 
 /**
  * The AbstractCommandsController class is the abstract base class encapsulating common functionality across all
@@ -255,12 +256,14 @@ public abstract class AbstractCommandsController {
    * Converts the URI relative path to an absolute path based on the Servlet context information.
    * 
    * @param path the URI relative path to append to the Servlet context path.
+   * @param scheme the scheme to use for the URI
    * @return a URI constructed with all component path information.
    * @see java.net.URI
    * @see org.springframework.web.servlet.support.ServletUriComponentsBuilder
    */
-  protected /*static*/ URI toUri(final String path) {
-    return ServletUriComponentsBuilder.fromCurrentContextPath().path(REST_API_VERSION).path(path).build().toUri();
+  protected /*static*/ URI toUri(final String path, final String scheme) {
+    return ServletUriComponentsBuilder.fromCurrentContextPath()
+        .path(REST_API_VERSION).path(path).scheme(scheme).build().toUri();
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e9aa18bd/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/ShellCommandsController.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/ShellCommandsController.java b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/ShellCommandsController.java
index bf3fb06..0bac797 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/ShellCommandsController.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/web/controllers/ShellCommandsController.java
@@ -144,7 +144,7 @@ public class ShellCommandsController extends AbstractCommandsController {
    * 
    * @return a LinkIndex containing Links for all web service endpoints, REST API calls in GemFire.
    * @see com.gemstone.gemfire.management.internal.cli.i18n.CliStrings
-   * @see com.gemstone.gemfire.management.internal.web.controllers.AbstractCommandsController#toUri(String)
+   * @see AbstractCommandsController#toUri(String, String)
    * @see com.gemstone.gemfire.management.internal.web.domain.Link
    * @see com.gemstone.gemfire.management.internal.web.domain.LinkIndex
    * @see com.gemstone.gemfire.management.internal.web.http.HttpMethod
@@ -153,113 +153,117 @@ public class ShellCommandsController extends AbstractCommandsController {
   // the Spring Web MVC Controller RequestMapping Annotations.
   @RequestMapping(method = RequestMethod.GET, value = "/index", produces = MediaType.APPLICATION_XML_VALUE)
   @ResponseBody
-  public LinkIndex index() {
+  public LinkIndex index(@RequestParam(value = "scheme", required = false, defaultValue = "http") final String scheme) {
     //logger.warning(String.format("Returning Link Index for Context Path (%1$s).",
     //  ServletUriComponentsBuilder.fromCurrentContextPath().build().toString()));
     return new LinkIndex()
       // Cluster Commands
-      .add(new Link(CliStrings.STATUS_SHARED_CONFIG, toUri("/services/cluster-config")))
+      .add(new Link(CliStrings.STATUS_SHARED_CONFIG, toUri("/services/cluster-config",
+          scheme)))
       // Member Commands
-      .add(new Link(CliStrings.LIST_MEMBER, toUri("/members")))
-      .add(new Link(CliStrings.DESCRIBE_MEMBER, toUri("/members/{name}")))
+      .add(new Link(CliStrings.LIST_MEMBER, toUri("/members", scheme)))
+      .add(new Link(CliStrings.DESCRIBE_MEMBER, toUri("/members/{name}", scheme)))
       // Region Commands
-      .add(new Link(CliStrings.LIST_REGION, toUri("/regions")))
-      .add(new Link(CliStrings.DESCRIBE_REGION, toUri("/regions/{name}")))
-      .add(new Link(CliStrings.ALTER_REGION, toUri("/regions/{name}"), HttpMethod.PUT))
-      .add(new Link(CliStrings.CREATE_REGION, toUri("/regions"), HttpMethod.POST))
-      .add(new Link(CliStrings.DESTROY_REGION, toUri("/regions/{name}"), HttpMethod.DELETE))
+      .add(new Link(CliStrings.LIST_REGION, toUri("/regions", scheme)))
+      .add(new Link(CliStrings.DESCRIBE_REGION, toUri("/regions/{name}", scheme)))
+      .add(new Link(CliStrings.ALTER_REGION, toUri("/regions/{name}", scheme), HttpMethod.PUT))
+      .add(new Link(CliStrings.CREATE_REGION, toUri("/regions", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.DESTROY_REGION, toUri("/regions/{name}", scheme), HttpMethod.DELETE))
       // Index Commands
-      .add(new Link(CliStrings.LIST_INDEX, toUri("/indexes")))
-      .add(new Link(CliStrings.CLEAR_DEFINED_INDEXES, toUri("/indexes?op=clear-defined"), HttpMethod.DELETE))
-      .add(new Link(CliStrings.CREATE_INDEX, toUri("/indexes"), HttpMethod.POST))
-      .add(new Link(CliStrings.CREATE_DEFINED_INDEXES, toUri("/indexes?op=create-defined"), HttpMethod.POST))
-      .add(new Link(CliStrings.DEFINE_INDEX, toUri("/indexes?op=define"), HttpMethod.POST))
-      .add(new Link(CliStrings.DESTROY_INDEX, toUri("/indexes"), HttpMethod.DELETE))
-      .add(new Link(CliStrings.DESTROY_INDEX, toUri("/indexes/{name}"), HttpMethod.DELETE))
+      .add(new Link(CliStrings.LIST_INDEX, toUri("/indexes", scheme)))
+      .add(new Link(CliStrings.CLEAR_DEFINED_INDEXES, toUri("/indexes?op=clear-defined",
+          scheme), HttpMethod.DELETE))
+      .add(new Link(CliStrings.CREATE_INDEX, toUri("/indexes", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.CREATE_DEFINED_INDEXES, toUri("/indexes?op=create-defined",
+          scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.DEFINE_INDEX, toUri("/indexes?op=define", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.DESTROY_INDEX, toUri("/indexes", scheme), HttpMethod.DELETE))
+      .add(new Link(CliStrings.DESTROY_INDEX, toUri("/indexes/{name}", scheme), HttpMethod.DELETE))
         // Data Commands
-      .add(new Link(CliStrings.GET, toUri("/regions/{region}/data"), HttpMethod.GET))
-      .add(new Link(CliStrings.PUT, toUri("/regions/{region}/data"), HttpMethod.PUT))
-      .add(new Link(CliStrings.REMOVE, toUri("/regions/{region}/data"), HttpMethod.DELETE))
-      .add(new Link(CliStrings.EXPORT_DATA, toUri("/members/{member}/regions/{region}/data"), HttpMethod.GET))
-      .add(new Link(CliStrings.IMPORT_DATA, toUri("/members/{member}/regions/{region}/data"), HttpMethod.POST))
-      .add(new Link(CliStrings.LOCATE_ENTRY, toUri("/regions/{region}/data/location"), HttpMethod.GET))
-      .add(new Link(CliStrings.QUERY, toUri("/regions/data/query"), HttpMethod.GET))
-      .add(new Link(CliStrings.REBALANCE, toUri("/regions/data?op=rebalance"), HttpMethod.POST))
+      .add(new Link(CliStrings.GET, toUri("/regions/{region}/data", scheme), HttpMethod.GET))
+      .add(new Link(CliStrings.PUT, toUri("/regions/{region}/data", scheme), HttpMethod.PUT))
+      .add(new Link(CliStrings.REMOVE, toUri("/regions/{region}/data", scheme), HttpMethod.DELETE))
+      .add(new Link(CliStrings.EXPORT_DATA, toUri("/members/{member}/regions/{region}/data", scheme), HttpMethod.GET))
+      .add(new Link(CliStrings.IMPORT_DATA, toUri("/members/{member}/regions/{region}/data", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.LOCATE_ENTRY, toUri("/regions/{region}/data/location", scheme), HttpMethod.GET))
+      .add(new Link(CliStrings.QUERY, toUri("/regions/data/query", scheme), HttpMethod.GET))
+      .add(new Link(CliStrings.REBALANCE, toUri("/regions/data?op=rebalance", scheme), HttpMethod.POST))
       // Function Commands
-      .add(new Link(CliStrings.LIST_FUNCTION, toUri("/functions")))
-      .add(new Link(CliStrings.DESTROY_FUNCTION, toUri("/functions/{id}"), HttpMethod.DELETE))
-      .add(new Link(CliStrings.EXECUTE_FUNCTION, toUri("/functions/{id}"), HttpMethod.POST))
+      .add(new Link(CliStrings.LIST_FUNCTION, toUri("/functions", scheme)))
+      .add(new Link(CliStrings.DESTROY_FUNCTION, toUri("/functions/{id}", scheme), HttpMethod.DELETE))
+      .add(new Link(CliStrings.EXECUTE_FUNCTION, toUri("/functions/{id}", scheme), HttpMethod.POST))
       // Client Commands
-      .add(new Link(CliStrings.LIST_CLIENTS, toUri("/clients")))
-      .add(new Link(CliStrings.DESCRIBE_CLIENT, toUri("/clients/{clientID}")))
+      .add(new Link(CliStrings.LIST_CLIENTS, toUri("/clients", scheme)))
+      .add(new Link(CliStrings.DESCRIBE_CLIENT, toUri("/clients/{clientID}", scheme)))
       // Config Commands
-      .add(new Link(CliStrings.ALTER_RUNTIME_CONFIG, toUri("/config"), HttpMethod.POST))
-      .add(new Link(CliStrings.DESCRIBE_CONFIG, toUri("/members/{member}/config")))
-      .add(new Link(CliStrings.EXPORT_CONFIG, toUri("/config")))
-      .add(new Link(CliStrings.EXPORT_SHARED_CONFIG, toUri("/config/cluster")))
-      .add(new Link(CliStrings.IMPORT_SHARED_CONFIG, toUri("/config/cluster"), HttpMethod.POST))
+      .add(new Link(CliStrings.ALTER_RUNTIME_CONFIG, toUri("/config", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.DESCRIBE_CONFIG, toUri("/members/{member}/config", scheme)))
+      .add(new Link(CliStrings.EXPORT_CONFIG, toUri("/config", scheme)))
+      .add(new Link(CliStrings.EXPORT_SHARED_CONFIG, toUri("/config/cluster", scheme)))
+      .add(new Link(CliStrings.IMPORT_SHARED_CONFIG, toUri("/config/cluster", scheme), HttpMethod.POST))
       // Deploy Commands
-      .add(new Link(CliStrings.LIST_DEPLOYED, toUri("/deployed")))
-      .add(new Link(CliStrings.DEPLOY, toUri("/deployed"), HttpMethod.POST))
-      .add(new Link(CliStrings.UNDEPLOY, toUri("/deployed"), HttpMethod.DELETE))
+      .add(new Link(CliStrings.LIST_DEPLOYED, toUri("/deployed", scheme)))
+      .add(new Link(CliStrings.DEPLOY, toUri("/deployed", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.UNDEPLOY, toUri("/deployed", scheme), HttpMethod.DELETE))
       // Disk Store Commands
-      .add(new Link(CliStrings.LIST_DISK_STORE, toUri("/diskstores")))
-      .add(new Link(CliStrings.BACKUP_DISK_STORE, toUri("/diskstores?op=backup"), HttpMethod.POST))
-      .add(new Link(CliStrings.COMPACT_DISK_STORE, toUri("/diskstores/{name}?op=compact"), HttpMethod.POST))
-      .add(new Link(CliStrings.CREATE_DISK_STORE, toUri("/diskstores"), HttpMethod.POST))
-      .add(new Link(CliStrings.DESCRIBE_DISK_STORE, toUri("/diskstores/{name}")))
-      .add(new Link(CliStrings.DESTROY_DISK_STORE, toUri("/diskstores/{name}"), HttpMethod.DELETE))
-      .add(new Link(CliStrings.REVOKE_MISSING_DISK_STORE, toUri("/diskstores/{id}?op=revoke"), HttpMethod.POST))
-      .add(new Link(CliStrings.SHOW_MISSING_DISK_STORE, toUri("/diskstores/missing")))
+      .add(new Link(CliStrings.LIST_DISK_STORE, toUri("/diskstores", scheme)))
+      .add(new Link(CliStrings.BACKUP_DISK_STORE, toUri("/diskstores?op=backup", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.COMPACT_DISK_STORE, toUri("/diskstores/{name}?op=compact",
+          scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.CREATE_DISK_STORE, toUri("/diskstores", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.DESCRIBE_DISK_STORE, toUri("/diskstores/{name}", scheme)))
+      .add(new Link(CliStrings.DESTROY_DISK_STORE, toUri("/diskstores/{name}", scheme), HttpMethod.DELETE))
+      .add(new Link(CliStrings.REVOKE_MISSING_DISK_STORE, toUri("/diskstores/{id}?op=revoke", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.SHOW_MISSING_DISK_STORE, toUri("/diskstores/missing", scheme)))
       // Durable Client Commands
-      .add(new Link(CliStrings.LIST_DURABLE_CQS, toUri("/durable-clients/{durable-client-id}/cqs")))
-      .add(new Link(CliStrings.COUNT_DURABLE_CQ_EVENTS, toUri("/durable-clients/{durable-client-id}/cqs/events")))
-      .add(new Link(CliStrings.COUNT_DURABLE_CQ_EVENTS, toUri("/durable-clients/{durable-client-id}/cqs/{durable-cq-name}/events")))
-      .add(new Link(CliStrings.CLOSE_DURABLE_CLIENTS, toUri("/durable-clients/{durable-client-id}?op=close"), HttpMethod.POST))
-      .add(new Link(CliStrings.CLOSE_DURABLE_CQS, toUri("/durable-clients/{durable-client-id}/cqs/{durable-cq-name}?op=close"), HttpMethod.POST))
+      .add(new Link(CliStrings.LIST_DURABLE_CQS, toUri("/durable-clients/{durable-client-id}/cqs", scheme)))
+      .add(new Link(CliStrings.COUNT_DURABLE_CQ_EVENTS, toUri("/durable-clients/{durable-client-id}/cqs/events", scheme)))
+      .add(new Link(CliStrings.COUNT_DURABLE_CQ_EVENTS, toUri("/durable-clients/{durable-client-id}/cqs/{durable-cq-name}/events", scheme)))
+      .add(new Link(CliStrings.CLOSE_DURABLE_CLIENTS, toUri("/durable-clients/{durable-client-id}?op=close", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.CLOSE_DURABLE_CQS, toUri("/durable-clients/{durable-client-id}/cqs/{durable-cq-name}?op=close", scheme), HttpMethod.POST))
       // Launcher Lifecycle Commands
-      .add(new Link(CliStrings.STATUS_LOCATOR, toUri("/members/{name}/locator")))
-      .add(new Link(CliStrings.STATUS_SERVER, toUri("/members/{name}/server")))
+      .add(new Link(CliStrings.STATUS_LOCATOR, toUri("/members/{name}/locator", scheme)))
+      .add(new Link(CliStrings.STATUS_SERVER, toUri("/members/{name}/server", scheme)))
       // Miscellaneous Commands
-      .add(new Link(CliStrings.CHANGE_LOGLEVEL, toUri("/groups/{groups}/loglevel"), HttpMethod.POST))
-      .add(new Link(CliStrings.CHANGE_LOGLEVEL, toUri("/members/{members}/loglevel"), HttpMethod.POST))
-      .add(new Link(CliStrings.CHANGE_LOGLEVEL, toUri("/members/{members}/groups/{groups}/loglevel"), HttpMethod.POST))
-      .add(new Link(CliStrings.EXPORT_LOGS, toUri("/logs")))
-      .add(new Link(CliStrings.EXPORT_STACKTRACE, toUri("/stacktraces")))
-      .add(new Link(CliStrings.GC, toUri("/gc"), HttpMethod.POST))
-      .add(new Link(CliStrings.GC, toUri("/members/{member}/gc"), HttpMethod.POST))
-      .add(new Link(CliStrings.NETSTAT, toUri("/netstat")))
-      .add(new Link(CliStrings.SHOW_DEADLOCK, toUri("/deadlocks")))
-      .add(new Link(CliStrings.SHOW_LOG, toUri("/members/{member}/log")))
-      .add(new Link(CliStrings.SHOW_METRICS, toUri("/metrics")))
-      .add(new Link(CliStrings.SHUTDOWN, toUri("/shutdown"), HttpMethod.POST)) // verb!
+      .add(new Link(CliStrings.CHANGE_LOGLEVEL, toUri("/groups/{groups}/loglevel", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.CHANGE_LOGLEVEL, toUri("/members/{members}/loglevel", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.CHANGE_LOGLEVEL, toUri("/members/{members}/groups/{groups}/loglevel", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.EXPORT_LOGS, toUri("/logs", scheme)))
+      .add(new Link(CliStrings.EXPORT_STACKTRACE, toUri("/stacktraces", scheme)))
+      .add(new Link(CliStrings.GC, toUri("/gc", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.GC, toUri("/members/{member}/gc", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.NETSTAT, toUri("/netstat", scheme)))
+      .add(new Link(CliStrings.SHOW_DEADLOCK, toUri("/deadlocks", scheme)))
+      .add(new Link(CliStrings.SHOW_LOG, toUri("/members/{member}/log", scheme)))
+      .add(new Link(CliStrings.SHOW_METRICS, toUri("/metrics", scheme)))
+      .add(new Link(CliStrings.SHUTDOWN, toUri("/shutdown", scheme), HttpMethod.POST)) // verb!
       // Queue Commands
-      .add(new Link(CliStrings.CREATE_ASYNC_EVENT_QUEUE, toUri("/async-event-queues"), HttpMethod.POST))
-      .add(new Link(CliStrings.LIST_ASYNC_EVENT_QUEUES, toUri("/async-event-queues")))
+      .add(new Link(CliStrings.CREATE_ASYNC_EVENT_QUEUE, toUri("/async-event-queues", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.LIST_ASYNC_EVENT_QUEUES, toUri("/async-event-queues", scheme)))
       // PDX Commands
-      .add(new Link(CliStrings.CONFIGURE_PDX, toUri("/pdx"), HttpMethod.POST))
+      .add(new Link(CliStrings.CONFIGURE_PDX, toUri("/pdx", scheme), HttpMethod.POST))
       //.add(new Link(CliStrings.PDX_DELETE_FIELD, toUri("/pdx/type/field"), HttpMethod.DELETE))
-      .add(new Link(CliStrings.PDX_RENAME, toUri("/pdx/type"), HttpMethod.POST))
+      .add(new Link(CliStrings.PDX_RENAME, toUri("/pdx/type", scheme), HttpMethod.POST))
       // Shell Commands
-      .add(new Link(MBEAN_ATTRIBUTE_LINK_RELATION, toUri("/mbean/attribute")))
-      .add(new Link(MBEAN_OPERATION_LINK_RELATION, toUri("/mbean/operation"), HttpMethod.POST))
-      .add(new Link(MBEAN_QUERY_LINK_RELATION, toUri("/mbean/query"), HttpMethod.POST))
-      .add(new Link(PING_LINK_RELATION, toUri("/ping"), HttpMethod.GET))
-      .add(new Link(CliStrings.VERSION, toUri("/version")))
+      .add(new Link(MBEAN_ATTRIBUTE_LINK_RELATION, toUri("/mbean/attribute", scheme)))
+      .add(new Link(MBEAN_OPERATION_LINK_RELATION, toUri("/mbean/operation", scheme), HttpMethod.POST))
+      .add(new Link(MBEAN_QUERY_LINK_RELATION, toUri("/mbean/query", scheme), HttpMethod.POST))
+      .add(new Link(PING_LINK_RELATION, toUri("/ping", scheme), HttpMethod.GET))
+      .add(new Link(CliStrings.VERSION, toUri("/version", scheme)))
       // WAN Gateway Commands
-      .add(new Link(CliStrings.LIST_GATEWAY, toUri("/gateways")))
-      .add(new Link(CliStrings.CREATE_GATEWAYRECEIVER, toUri("/gateways/receivers"), HttpMethod.POST))
-      .add(new Link(CliStrings.CREATE_GATEWAYSENDER, toUri("/gateways/senders"), HttpMethod.POST))
-      .add(new Link(CliStrings.LOAD_BALANCE_GATEWAYSENDER, toUri("/gateways/senders/{id}?op=load-balance"), HttpMethod.POST))
-      .add(new Link(CliStrings.PAUSE_GATEWAYSENDER, toUri("/gateways/senders/{id}?op=pause"), HttpMethod.POST))
-      .add(new Link(CliStrings.RESUME_GATEWAYSENDER, toUri("/gateways/senders/{id}?op=resume"), HttpMethod.POST))
-      .add(new Link(CliStrings.START_GATEWAYRECEIVER, toUri("/gateways/receivers?op=start"), HttpMethod.POST))
-      .add(new Link(CliStrings.START_GATEWAYSENDER, toUri("/gateways/senders?op=start"), HttpMethod.POST))
-      .add(new Link(CliStrings.STATUS_GATEWAYRECEIVER, toUri("/gateways/receivers")))
-      .add(new Link(CliStrings.STATUS_GATEWAYSENDER, toUri("/gateways/senders/{id}")))
-      .add(new Link(CliStrings.STOP_GATEWAYRECEIVER, toUri("/gateways/receivers?op=stop"), HttpMethod.POST))
-      .add(new Link(CliStrings.STOP_GATEWAYSENDER, toUri("/gateways/senders/{id}?op=stop"), HttpMethod.POST))
-      ;
+      .add(new Link(CliStrings.LIST_GATEWAY, toUri("/gateways", scheme)))
+      .add(new Link(CliStrings.CREATE_GATEWAYRECEIVER, toUri("/gateways/receivers", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.CREATE_GATEWAYSENDER, toUri("/gateways/senders", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.LOAD_BALANCE_GATEWAYSENDER, toUri("/gateways/senders/{id}?op=load-balance", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.PAUSE_GATEWAYSENDER, toUri("/gateways/senders/{id}?op=pause", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.RESUME_GATEWAYSENDER, toUri("/gateways/senders/{id}?op=resume", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.START_GATEWAYRECEIVER, toUri("/gateways/receivers?op=start", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.START_GATEWAYSENDER, toUri("/gateways/senders?op=start", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.STATUS_GATEWAYRECEIVER, toUri("/gateways/receivers", scheme)))
+      .add(new Link(CliStrings.STATUS_GATEWAYSENDER, toUri("/gateways/senders/{id}", scheme)))
+      .add(new Link(CliStrings.STOP_GATEWAYRECEIVER, toUri("/gateways/receivers?op=stop", scheme), HttpMethod.POST))
+      .add(new Link(CliStrings.STOP_GATEWAYSENDER, toUri("/gateways/senders/{id}?op=stop", scheme), HttpMethod.POST))
+        ;
   }
 
   @RequestMapping(method = { RequestMethod.GET, RequestMethod.HEAD }, value = "/ping")

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e9aa18bd/gemfire-web/build.gradle
----------------------------------------------------------------------
diff --git a/gemfire-web/build.gradle b/gemfire-web/build.gradle
index b9629d3..f0de25a 100755
--- a/gemfire-web/build.gradle
+++ b/gemfire-web/build.gradle
@@ -4,13 +4,15 @@ dependencies {
   runtime 'org.springframework:spring-aspects:3.2.12.RELEASE'
   runtime 'org.springframework:spring-oxm:3.2.12.RELEASE'
   runtime 'commons-fileupload:commons-fileupload:1.3.1'
+
+  testCompile 'org.springframework:spring-test:3.2.12.RELEASE'
   
   provided 'javax.servlet:javax.servlet-api:3.1.0'
   
   // have to use output since we exclude the dependent classes from jar :(
   provided project(path: ':gemfire-core', configuration: 'classesOutput')
   
-  provided project(':gemfire-core')
+  testRuntime project(':gemfire-core')
 
   provided project(path: ':gemfire-junit', configuration: 'testOutput')
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/e9aa18bd/gemfire-web/src/test/java/com/gemstone/gemfire/management/internal/web/controllers/ShellCommandsControllerJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-web/src/test/java/com/gemstone/gemfire/management/internal/web/controllers/ShellCommandsControllerJUnitTest.java b/gemfire-web/src/test/java/com/gemstone/gemfire/management/internal/web/controllers/ShellCommandsControllerJUnitTest.java
index c02b3ee..07d1012 100644
--- a/gemfire-web/src/test/java/com/gemstone/gemfire/management/internal/web/controllers/ShellCommandsControllerJUnitTest.java
+++ b/gemfire-web/src/test/java/com/gemstone/gemfire/management/internal/web/controllers/ShellCommandsControllerJUnitTest.java
@@ -19,7 +19,6 @@ package com.gemstone.gemfire.management.internal.web.controllers;
 import static org.junit.Assert.*;
 
 import java.lang.reflect.Method;
-import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -38,9 +37,15 @@ import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
+import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.shell.core.CommandMarker;
 import org.springframework.shell.core.annotation.CliCommand;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
 
 /**
  * The ShellCommandsControllerJUnitTest class is a test suite of test cases testing the contract and functionality of the
@@ -59,11 +64,10 @@ public class ShellCommandsControllerJUnitTest {
 
   @BeforeClass
   public static void setupBeforeClass() {
-    controller = new ShellCommandsController() {
-      @Override protected URI toUri(final String path) {
-        return URI.create(UriUtils.encode(path));
-      }
-    };
+    controller = new ShellCommandsController();
+    MockHttpServletRequest request = new MockHttpServletRequest();
+    request.setContextPath("gemfire");
+    RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
   }
 
   @AfterClass
@@ -99,6 +103,10 @@ public class ShellCommandsControllerJUnitTest {
   }
 
   protected List<String> getControllerWebServiceEndpoints() {
+    RequestAttributes requestAttrs = RequestContextHolder.getRequestAttributes();
+    HttpServletRequest servletRequest = ((ServletRequestAttributes) requestAttrs).getRequest();
+    String scheme = servletRequest.getScheme();
+
     try {
       Set<Class<?>> controllerClasses = ClasspathScanLoadHelper.loadAndGet(
         "com.gemstone.gemfire.management.internal.web.controllers", AbstractCommandsController.class, true);
@@ -112,7 +120,7 @@ public class ShellCommandsControllerJUnitTest {
               RequestMapping requestMappingAnnotation = method.getAnnotation(RequestMapping.class);
 
               String webServiceEndpoint = String.format("%1$s %2$s", requestMappingAnnotation.method()[0],
-                requestMappingAnnotation.value()[0]);
+                UriUtils.decode(controller.toUri(requestMappingAnnotation.value()[0], scheme).toString()));
 
               String[] requestParameters = requestMappingAnnotation.params();
 
@@ -136,7 +144,7 @@ public class ShellCommandsControllerJUnitTest {
 
   @Test
   public void testUniqueIndex() {
-    LinkIndex linkIndex = controller.index();
+    LinkIndex linkIndex = controller.index("https");
 
     List<String> conflicts = new ArrayList<>();
     Map<String, String> uriRelationMapping = new HashMap<>(linkIndex.size());
@@ -161,7 +169,7 @@ public class ShellCommandsControllerJUnitTest {
     assertNotNull(commands);
     assertFalse(commands.isEmpty());
 
-    LinkIndex linkIndex = controller.index();
+    LinkIndex linkIndex = controller.index("https");
 
     assertNotNull(linkIndex);
     assertFalse(linkIndex.isEmpty());
@@ -190,7 +198,7 @@ public class ShellCommandsControllerJUnitTest {
     assertNotNull(controllerWebServiceEndpoints);
     assertFalse(controllerWebServiceEndpoints.isEmpty());
 
-    LinkIndex linkIndex = controller.index();
+    LinkIndex linkIndex = controller.index("http");
 
     assertNotNull(linkIndex);
     assertFalse(linkIndex.isEmpty());
@@ -208,8 +216,25 @@ public class ShellCommandsControllerJUnitTest {
     missingControllerWebServiceEndpoints.removeAll(controllerWebServiceEndpoints);
 
     assertTrue(String.format(
-      "The Management REST API Web Service Controllers in (%1$s) are missing the following REST API Web Service Endpoint(s): %2$s!",
+        "The Management REST API Web Service Controllers in (%1$s) are missing the following REST API Web Service Endpoint(s): %2$s!",
         getClass().getPackage().getName(), missingControllerWebServiceEndpoints), missingControllerWebServiceEndpoints.isEmpty());
   }
 
+  @Test
+  public void testIndexUrisHaveCorrectScheme() {
+    String versionCmd = "version";
+    List<String> controllerWebServiceEndpoints = getControllerWebServiceEndpoints();
+
+    assertNotNull(controllerWebServiceEndpoints);
+    assertFalse(controllerWebServiceEndpoints.isEmpty());
+
+    String testScheme = "xyz";
+    LinkIndex linkIndex = controller.index(testScheme);
+
+    assertNotNull(linkIndex);
+    assertFalse(linkIndex.isEmpty());
+
+    assertTrue(String.format("Link does not have correct scheme %1$s", linkIndex.find(versionCmd)),
+        testScheme.equals(linkIndex.find(versionCmd).getHref().getScheme()));
+  }
 }