You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ji...@apache.org on 2017/10/05 17:56:28 UTC
[geode] branch develop updated: Consolidate Http request
This is an automated email from the ASF dual-hosted git repository.
jinmeiliao pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push:
new 003bbac Consolidate Http request
003bbac is described below
commit 003bbac63cc9796a1f79706282c8647c85ee4745
Author: Jinmei Liao <ji...@pivotal.io>
AuthorDate: Thu Sep 14 14:01:52 2017 -0700
Consolidate Http request
---
.../management/internal/cli/CommandRequest.java | 13 -
.../internal/cli/commands/ConnectCommand.java | 7 +-
.../internal/web/http/support/HttpRequester.java | 222 ++++++++++++++++
.../web/http/support/SimpleHttpRequester.java | 196 ---------------
.../internal/web/shell/HttpOperationInvoker.java | 278 ++++-----------------
.../web/http/support/HttpRequesterTest.java | 149 +++++++++++
.../web/shell/HttpOperationInvokerTest.java | 73 ------
.../shell/HttpOperationInvokerSecurityTest.java | 2 -
8 files changed, 420 insertions(+), 520 deletions(-)
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandRequest.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandRequest.java
index aade959..2b19e6a 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandRequest.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandRequest.java
@@ -14,12 +14,9 @@
*/
package org.apache.geode.management.internal.cli;
-import java.net.URI;
import java.util.Collections;
import java.util.Map;
-import org.springframework.web.util.UriComponentsBuilder;
-
import org.apache.geode.annotations.TestingOnly;
import org.apache.geode.management.cli.CliMetaData;
@@ -33,10 +30,6 @@ import org.apache.geode.management.cli.CliMetaData;
*/
@SuppressWarnings("unused")
public class CommandRequest {
- protected static final String CMD_QUERY_PARAMETER = "cmd";
- protected static final String REST_API_MANAGEMENT_COMMANDS_URI = "/management/commands";
- protected static final String OPTION_SPECIFIER = "--";
-
private final byte[][] fileData;
private final GfshParseResult parseResult;
private final Map<String, String> env;
@@ -100,10 +93,4 @@ public class CommandRequest {
public Map<String, String> getParameters() {
return getParseResult().getParamValueStrings();
}
-
- public URI getHttpRequestUrl(String baseUrl) {
- return UriComponentsBuilder.fromHttpUrl(baseUrl).path(REST_API_MANAGEMENT_COMMANDS_URI)
- .queryParam(CMD_QUERY_PARAMETER, getUserInput()).build().encode().toUri();
- }
-
}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java
index cd43f00..9014b43 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java
@@ -63,7 +63,6 @@ import org.apache.geode.management.internal.cli.shell.Gfsh;
import org.apache.geode.management.internal.cli.shell.JmxOperationInvoker;
import org.apache.geode.management.internal.cli.util.ConnectionEndpoint;
import org.apache.geode.management.internal.security.ResourceConstants;
-import org.apache.geode.management.internal.web.http.support.SimpleHttpRequester;
import org.apache.geode.management.internal.web.shell.HttpOperationInvoker;
import org.apache.geode.security.AuthenticationFailedException;
import org.springframework.shell.core.annotation.CliCommand;
@@ -250,11 +249,9 @@ public class ConnectCommand implements GfshCommand {
}
}
- // this triggers the authentication check
- new SimpleHttpRequester(gfsh, CONNECT_LOCATOR_TIMEOUT_MS, gfProperties)
- .exchange(url.concat("/ping"), String.class);
-
+ // authentication check will be triggered inside the constructor
HttpOperationInvoker operationInvoker = new HttpOperationInvoker(gfsh, url, gfProperties);
+
gfsh.setOperationInvoker(operationInvoker);
LogWrapper.getInstance()
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/web/http/support/HttpRequester.java b/geode-core/src/main/java/org/apache/geode/management/internal/web/http/support/HttpRequester.java
new file mode 100644
index 0000000..7a8bfed
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/web/http/support/HttpRequester.java
@@ -0,0 +1,222 @@
+/*
+ * 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.geode.management.internal.web.http.support;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.commons.io.FileUtils;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.ClientHttpRequest;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.client.DefaultResponseErrorHandler;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import org.apache.geode.internal.GemFireVersion;
+import org.apache.geode.internal.util.IOUtils;
+import org.apache.geode.management.internal.cli.shell.Gfsh;
+import org.apache.geode.management.internal.web.http.converter.SerializableObjectHttpMessageConverter;
+import org.apache.geode.security.AuthenticationFailedException;
+import org.apache.geode.security.NotAuthorizedException;
+
+
+/**
+ * The HttpRequester class is a Adapter/facade for the Spring RestTemplate class for abstracting
+ * HTTP requests and operations.
+ * <p/>
+ *
+ * @see org.springframework.http.client.SimpleClientHttpRequestFactory
+ * @see org.springframework.web.client.RestTemplate
+ * @since GemFire 8.0
+ */
+@SuppressWarnings("unused")
+public class HttpRequester {
+ private final RestTemplate restTemplate;
+ private Properties securityProperties;
+
+ protected static final String USER_AGENT_HTTP_REQUEST_HEADER_VALUE =
+ "GemFire-Shell/v" + GemFireVersion.getGemFireVersion();
+
+ // a list of acceptable content/media types supported by Gfsh
+ private final List<MediaType> acceptableMediaTypes = Arrays.asList(MediaType.APPLICATION_JSON,
+ MediaType.TEXT_PLAIN, MediaType.APPLICATION_OCTET_STREAM);
+
+ public HttpRequester() {
+ this(null, null);
+ }
+
+ public HttpRequester(Properties securityProperties) {
+ this(securityProperties, null);
+ }
+
+ HttpRequester(Properties securityProperties, RestTemplate restTemplate) {
+ final SimpleClientHttpRequestFactory clientHttpRequestFactory =
+ new SimpleClientHttpRequestFactory();
+ this.securityProperties = securityProperties;
+ if (restTemplate == null) {
+ this.restTemplate = new RestTemplate(clientHttpRequestFactory);
+ } else {
+ this.restTemplate = restTemplate;
+ }
+
+ // add our custom HttpMessageConverter for serializing DTO Objects into the HTTP request message
+ // body and de-serializing HTTP response message body content back into DTO Objects
+ List<HttpMessageConverter<?>> converters = this.restTemplate.getMessageConverters();
+ // remove the MappingJacksonHttpConverter
+ for (int i = converters.size() - 1; i >= 0; i--) {
+ HttpMessageConverter converter = converters.get(i);
+ if (converter instanceof MappingJackson2HttpMessageConverter) {
+ converters.remove(converter);
+ }
+ }
+ converters.add(new SerializableObjectHttpMessageConverter());
+
+ this.restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
+ @Override
+ public void handleError(final ClientHttpResponse response) throws IOException {
+ String body = readBody(response);
+ final String message = String.format("The HTTP request failed with: %1$d - %2$s.",
+ response.getRawStatusCode(), body);
+
+ if (response.getRawStatusCode() == 401) {
+ throw new AuthenticationFailedException(message);
+ } else if (response.getRawStatusCode() == 403) {
+ throw new NotAuthorizedException(message);
+ } else {
+ throw new RuntimeException(message);
+ }
+ }
+
+ private String readBody(final ClientHttpResponse response) throws IOException {
+ BufferedReader responseBodyReader = null;
+ try {
+ responseBodyReader = new BufferedReader(new InputStreamReader(response.getBody()));
+
+ final StringBuilder buffer = new StringBuilder();
+ String line;
+
+ while ((line = responseBodyReader.readLine()) != null) {
+ buffer.append(line).append(Gfsh.LINE_SEPARATOR);
+ }
+
+ return buffer.toString().trim();
+ } finally {
+ IOUtils.close(responseBodyReader);
+ }
+ }
+ });
+ }
+
+ /**
+ * Gets an instance of the Spring RestTemplate to perform the HTTP operations.
+ * <p/>
+ *
+ * @return an instance of the Spring RestTemplate for performing HTTP operations.
+ * @see org.springframework.web.client.RestTemplate
+ */
+ public RestTemplate getRestTemplate() {
+ return restTemplate;
+ }
+
+ public <T> T get(URI url, Class<T> responseType) {
+ return exchange(url, HttpMethod.GET, null, null, responseType);
+ }
+
+ public <T> T post(URI url, MediaType mediaType, Object content, Class<T> responseType) {
+ return exchange(url, HttpMethod.POST, mediaType, content, responseType);
+ }
+
+ <T> T exchange(URI url, HttpMethod method, MediaType mediaType, Object content,
+ Class<T> responseType) {
+ HttpHeaders headers = new HttpHeaders();
+ addHeaderValues(headers);
+
+ HttpEntity<Object> httpEntity = new HttpEntity<>(content, headers);
+
+ final ResponseEntity<T> response = restTemplate.exchange(url, method, httpEntity, responseType);
+ return response.getBody();
+ }
+
+ public Object executeWithResponseExtractor(URI url) {
+ return restTemplate.execute(url, HttpMethod.POST, this::addHeaderValues, this::extractResponse);
+ }
+
+ void addHeaderValues(ClientHttpRequest request) {
+ addHeaderValues(request.getHeaders());
+ }
+
+ Object extractResponse(ClientHttpResponse response) throws IOException {
+ MediaType mediaType = response.getHeaders().getContentType();
+ if (mediaType.equals(MediaType.APPLICATION_JSON)) {
+ return org.apache.commons.io.IOUtils.toString(response.getBody(), "UTF-8");
+ } else {
+ Path tempFile = Files.createTempFile("fileDownload", "");
+ if (tempFile.toFile().exists()) {
+ FileUtils.deleteQuietly(tempFile.toFile());
+ }
+ Files.copy(response.getBody(), tempFile);
+ return tempFile;
+ }
+ }
+
+ void addHeaderValues(HttpHeaders headers) {
+ // update the headers
+ headers.add(HttpHeaders.USER_AGENT, USER_AGENT_HTTP_REQUEST_HEADER_VALUE);
+ headers.setAccept(acceptableMediaTypes);
+
+ if (this.securityProperties != null) {
+ for (String key : securityProperties.stringPropertyNames()) {
+ headers.add(key, securityProperties.getProperty(key));
+ }
+ }
+ }
+
+ /**
+ * build the url using the path and query params
+ *
+ * @param path : the part after the baseUrl
+ * @param queryParams this needs to be an even number of strings in the form of paramName,
+ * paramValue....
+ */
+ public static URI createURI(String baseUrl, String path, String... queryParams) {
+ UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseUrl).path(path);
+
+ if (queryParams != null) {
+ if (queryParams.length % 2 != 0) {
+ throw new IllegalArgumentException("invalid queryParams count");
+ }
+ for (int i = 0; i < queryParams.length; i += 2) {
+ builder.queryParam(queryParams[i], queryParams[i + 1]);
+ }
+ }
+ return builder.build().encode().toUri();
+ }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/web/http/support/SimpleHttpRequester.java b/geode-core/src/main/java/org/apache/geode/management/internal/web/http/support/SimpleHttpRequester.java
deleted file mode 100644
index 8c4f91f..0000000
--- a/geode-core/src/main/java/org/apache/geode/management/internal/web/http/support/SimpleHttpRequester.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * 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.geode.management.internal.web.http.support;
-
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.ResponseEntity;
-import org.springframework.http.client.SimpleClientHttpRequestFactory;
-import org.springframework.web.client.RestTemplate;
-
-import org.apache.geode.management.internal.cli.shell.Gfsh;
-import org.apache.geode.management.internal.web.shell.RestOperationErrorHandler;
-
-
-/**
- * The SimpleHttpRequester class is a Adapter/facade for the Spring RestTemplate class for
- * abstracting HTTP requests and operations.
- * <p/>
- *
- * @see org.springframework.http.client.SimpleClientHttpRequestFactory
- * @see org.springframework.web.client.RestTemplate
- * @since GemFire 8.0
- */
-@SuppressWarnings("unused")
-public class SimpleHttpRequester {
-
- protected static final int DEFAULT_CONNECT_TIMEOUT = (30 * 1000); // 30 seconds
-
- private final RestTemplate restTemplate;
-
- private String user;
-
- private String pwd;
-
- private Properties securityProperties;
-
- public SimpleHttpRequester(final Gfsh gfsh, Properties securityProperties) {
- this(gfsh, DEFAULT_CONNECT_TIMEOUT, securityProperties);
- }
-
- /**
- * Constructs an instance of the SimpleHttpRequester class with the specified connection timeout.
- * <p/>
- *
- * @param connectTimeout an integer value specifying the timeout value in milliseconds for
- * establishing the HTTP connection to the HTTP server.
- */
- public SimpleHttpRequester(final Gfsh gfsh, final int connectTimeout,
- Properties securityProperties) {
- final SimpleClientHttpRequestFactory clientHttpRequestFactory =
- new SimpleClientHttpRequestFactory();
-
- clientHttpRequestFactory.setConnectTimeout(connectTimeout);
-
- this.securityProperties = securityProperties;
- this.restTemplate = new RestTemplate(clientHttpRequestFactory);
-
- this.restTemplate.setErrorHandler(new RestOperationErrorHandler());
-
- }
-
- /**
- * Gets an instance of the Spring RestTemplate to perform the HTTP operations.
- * <p/>
- *
- * @return an instance of the Spring RestTemplate for performing HTTP operations.
- * @see org.springframework.web.client.RestTemplate
- */
- public RestTemplate getRestTemplate() {
- return restTemplate;
- }
-
- /**
- * Performs an HTTP DELETE operation on the requested resource identified/located by the specified
- * URL.
- * <p/>
- *
- * @param url a String value identifying or locating the resource intended for the HTTP operation.
- * @param urlVariables an array of variables to substitute in the URI/URL template.
- * @see org.springframework.web.client.RestTemplate#delete(String, Object...)
- */
- public void delete(final String url, final Object... urlVariables) {
- getRestTemplate().delete(url, urlVariables);
- }
-
- /**
- * Performs an HTTP GET operation on the requested resource identified/located by the specified
- * URL.
- * <p/>
- *
- * @param url a String value identifying or locating the resource intended for the HTTP operation.
- * @param urlVariables an array of variables to substitute in the URI/URL template.
- * @see org.springframework.web.client.RestTemplate#getForObject(String, Class, Object...)
- */
- public <T> T get(final String url, final Class<T> responseType, final Object... urlVariables) {
- return getRestTemplate().getForObject(url, responseType, urlVariables);
- }
-
- /**
- * Retrieves the HTTP HEADERS for the requested resource identified/located by the specified URL.
- * <p/>
- *
- * @param url a String value identifying or locating the resource intended for the HTTP operation.
- * @param urlVariables an array of variables to substitute in the URI/URL template.
- * @see org.springframework.web.client.RestTemplate#headForHeaders(String, Object...)
- */
- public HttpHeaders headers(final String url, final Object... urlVariables) {
- return getRestTemplate().headForHeaders(url, urlVariables);
- }
-
- /**
- * Request the available/allowed HTTP operations on the resource identified/located by the
- * specified URL.
- * <p/>
- *
- * @param url a String value identifying or locating the resource intended for the HTTP operation.
- * @param urlVariables an array of variables to substitute in the URI/URL template.
- * @see org.springframework.web.client.RestTemplate#optionsForAllow(String, Object...)
- */
- public Set<HttpMethod> options(final String url, final Object... urlVariables) {
- return getRestTemplate().optionsForAllow(url, urlVariables);
- }
-
- /**
- * Performs an HTTP POST operation on the requested resource identified/located by the specified
- * URL.
- * <p/>
- *
- * @param url a String value identifying or locating the resource intended for the HTTP operation.
- * @param urlVariables an array of variables to substitute in the URI/URL template.
- * @see org.springframework.web.client.RestTemplate#postForObject(String, Object, Class,
- * Object...) z
- */
- public <T> T post(final String url, final Object requestBody, final Class<T> responseType,
- final Object... urlVariables) {
- return getRestTemplate().postForObject(url, requestBody, responseType, urlVariables);
- }
-
- /**
- * Performs an HTTP PUT operation on the requested resource identifiedR/located by the specified
- * URL.
- * <p/>
- *
- * @param url a String value identifying or locating the resource intended for the HTTP operation.
- * @param urlVariables an array of variables to substitute in the URI/URL template.
- * @see org.springframework.web.client.RestTemplate#put(String, Object, Object...)
- */
- public void put(final String url, final Object requestBody, final Object... urlVariables) {
- getRestTemplate().put(url, requestBody, urlVariables);
- }
-
- /**
- * Performs an HTTP GET operation on the requested resource identified/located by the specified
- * URL.
- * <p/>
- *
- * @param url a String value identifying or locating the resource intended for the HTTP operation.
- * @param urlVariables an array of variables to substitute in the URI/URL template.
- * @see org.springframework.web.client.RestTemplate#getForObject(String, Class, Object...)
- */
- public <T> T exchange(final String url, final Class<T> responseType,
- final Object... urlVariables) {
- ResponseEntity<T> response =
- getRestTemplate().exchange(url, HttpMethod.GET, getRequestEntity(), responseType);
- return response.getBody();
- }
-
- protected HttpEntity<?> getRequestEntity() {
- HttpHeaders requestHeaders = new HttpHeaders();
- if (this.securityProperties != null) {
- requestHeaders.setAll((Map) securityProperties);
- }
- HttpEntity<?> requestEntity = new HttpEntity(requestHeaders);
- return requestEntity;
-
- }
-
-}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/HttpOperationInvoker.java b/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/HttpOperationInvoker.java
index 577280d..2b24eec 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/HttpOperationInvoker.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/HttpOperationInvoker.java
@@ -16,11 +16,6 @@ package org.apache.geode.management.internal.web.shell;
import java.io.IOException;
import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.Executors;
@@ -30,27 +25,12 @@ import java.util.concurrent.TimeUnit;
import javax.management.ObjectName;
import javax.management.QueryExp;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.Logger;
import org.springframework.core.io.Resource;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.http.client.SimpleClientHttpRequestFactory;
-import org.springframework.http.converter.HttpMessageConverter;
-import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
-import org.springframework.web.client.ResourceAccessException;
-import org.springframework.web.client.RestTemplate;
-import org.springframework.web.util.UriComponentsBuilder;
-import org.apache.geode.annotations.TestingOnly;
-import org.apache.geode.internal.GemFireVersion;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.util.IOUtils;
import org.apache.geode.management.DistributedSystemMXBean;
@@ -60,8 +40,7 @@ import org.apache.geode.management.internal.cli.CommandRequest;
import org.apache.geode.management.internal.cli.shell.Gfsh;
import org.apache.geode.management.internal.cli.shell.OperationInvoker;
import org.apache.geode.management.internal.web.domain.QueryParameterSource;
-import org.apache.geode.management.internal.web.http.converter.SerializableObjectHttpMessageConverter;
-import org.apache.geode.management.internal.web.http.support.SimpleHttpRequester;
+import org.apache.geode.management.internal.web.http.support.HttpRequester;
import org.apache.geode.management.internal.web.shell.support.HttpMBeanProxyFactory;
import org.apache.geode.management.internal.web.util.ConvertUtils;
@@ -79,27 +58,18 @@ import org.apache.geode.management.internal.web.util.ConvertUtils;
@SuppressWarnings("unused")
public class HttpOperationInvoker implements OperationInvoker {
- private static final long DEFAULT_INITIAL_DELAY = TimeUnit.SECONDS.toMillis(1);
- private static final long DEFAULT_PERIOD = TimeUnit.MILLISECONDS.toMillis(2000);
-
- private static final String REST_API_BASE_URL = "http://localhost:8080";
- private static final String REST_API_VERSION = "/v1";
- private static final String REST_API_WEB_APP_CONTEXT = "/geode-mgmt";
- private static final String REST_API_URL =
- REST_API_BASE_URL + REST_API_WEB_APP_CONTEXT + REST_API_VERSION;
- private static final String USER_AGENT_HTTP_REQUEST_HEADER_VALUE =
- "GemFire-Shell/v" + GemFireVersion.getGemFireVersion();
-
- private static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MILLISECONDS;
+ protected static final long DEFAULT_INITIAL_DELAY = TimeUnit.SECONDS.toMillis(1);
+ protected static final long DEFAULT_PERIOD = TimeUnit.MILLISECONDS.toMillis(2000);
+ protected static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MILLISECONDS;
+ protected static final String CMD_QUERY_PARAMETER = "cmd";
+ protected static final String COMMANDS_URI = "/management/commands";
+ protected static final String RESOURCES_REQUEST_PARAMETER = "resources";
// the ID of the GemFire distributed system (cluster)
private Integer clusterId = CLUSTER_ID_WHEN_NOT_CONNECTED;
- private static final String RESOURCES_REQUEST_PARAMETER = "resources";
-
// Executor for scheduling periodic Runnable task to assess the state of the Manager's HTTP
// service or Web Service
- // hosting the M&M REST API (interface)
private final ScheduledExecutorService executorService;
// a reference to the GemFire shell (Gfsh) instance using this HTTP-based OperationInvoker for
@@ -107,48 +77,21 @@ public class HttpOperationInvoker implements OperationInvoker {
// and processing
private final Gfsh gfsh;
- // a list of acceptable content/media types supported by Gfsh
- private final List<MediaType> acceptableMediaTypes = Arrays.asList(MediaType.APPLICATION_JSON,
- MediaType.TEXT_PLAIN, MediaType.APPLICATION_OCTET_STREAM);
+ private final String baseUrl;
// a Java Logger used to log severe, warning, informational and debug messages during the
// operation of this invoker
private final Logger logger = LogService.getLogger();
// the Spring RestTemplate used to executeRequest HTTP requests and make REST API calls
- private volatile RestTemplate restTemplate;
-
- // the base URL of the GemFire Manager's embedded HTTP service and REST API interface
- private final String baseUrl;
-
-
- protected Properties securityProperties;
-
- /**
- * Default no-arg constructor to create an instance of the SimpleHttpOperationInvoker class for
- * testing purposes.
- */
- @TestingOnly
- HttpOperationInvoker() {
- this(REST_API_URL);
- }
+ private volatile HttpRequester httpRequester;
- /**
- * Default, public, no-arg constructor to create an instance of the HttpOperationInvoker class for
- * testing purposes.
- */
- @TestingOnly
- private HttpOperationInvoker(final String baseUrl) {
- this.baseUrl = baseUrl;
- this.executorService = null;
- this.gfsh = null;
- this.restTemplate = null;
- }
+ private boolean connected = false;
/**
* Constructs an instance of the HttpOperationInvoker class with a reference to the GemFire shell
* (Gfsh) instance using this HTTP-based OperationInvoker to send commands to the GemFire Manager
- * via HTTP for processing along with the base URL to the GemFire Manager's embedded HTTP service
+ * via HTTP for procsessing along with the base URL to the GemFire Manager's embedded HTTP service
* hosting the HTTP (REST) interface.
*
* @param gfsh a reference to the instance of the GemFire shell (Gfsh) using this HTTP-based
@@ -161,41 +104,20 @@ public class HttpOperationInvoker implements OperationInvoker {
public HttpOperationInvoker(final Gfsh gfsh, final String baseUrl,
Properties securityProperties) {
this.gfsh = gfsh;
- this.baseUrl = StringUtils.defaultIfBlank(baseUrl, REST_API_URL);
- this.securityProperties = securityProperties;
+ this.baseUrl = baseUrl;
+ this.httpRequester = new HttpRequester(securityProperties);
+
+ // request ping and then schedule the ping to access the "alive" state, this will trigger
+ // authentication check
+ httpRequester.get(HttpRequester.createURI(baseUrl, "/ping"), String.class);
+ connected = true;
// constructs an instance of a single-threaded, scheduled Executor to send periodic HTTP
- // requests to the Manager's
- // HTTP service or Web Service to assess the "alive" state
+ // requests to the Manager's HTTP service or Web Service to assess the "alive" state
this.executorService = Executors.newSingleThreadScheduledExecutor();
-
- // constructs an instance of the Spring RestTemplate for M&M REST API (interface) operations
- this.restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory());
-
- // add our custom HttpMessageConverter for serializing DTO Objects into the HTTP request
- // message body and de-serializing HTTP response message body content back into DTO Objects
- List<HttpMessageConverter<?>> converters = this.restTemplate.getMessageConverters();
- // remove the MappingJacksonHttpConverter
- for (int i = converters.size() - 1; i >= 0; i--) {
- HttpMessageConverter converter = converters.get(i);
- if (converter instanceof MappingJackson2HttpMessageConverter) {
- converters.remove(converter);
- }
- }
- converters.add(new SerializableObjectHttpMessageConverter());
-
- // set the ResponseErrorHandler handling any errors originating from our HTTP request
- this.restTemplate.setErrorHandler(new RestOperationErrorHandler(gfsh));
-
- setupBackgroundPingRequest();
- initClusterId();
- }
-
- private void setupBackgroundPingRequest() {
- SimpleHttpRequester requester = new SimpleHttpRequester(gfsh, securityProperties);
- getExecutorService().scheduleAtFixedRate(() -> {
+ executorService.scheduleAtFixedRate(() -> {
try {
- requester.exchange(baseUrl.concat("/ping"), String.class);
+ httpRequester.get(HttpRequester.createURI(baseUrl, "/ping"), String.class);
} catch (Exception e) {
printDebug("An error occurred while connecting to the Manager's HTTP service: %1$s: ",
e.getMessage());
@@ -203,6 +125,10 @@ public class HttpOperationInvoker implements OperationInvoker {
stop();
}
}, DEFAULT_INITIAL_DELAY, DEFAULT_PERIOD, DEFAULT_TIME_UNIT);
+
+ // initialize cluster id
+ clusterId = (Integer) getAttribute(ManagementConstants.OBJECTNAME__DISTRIBUTEDSYSTEM_MXBEAN,
+ "DistributedSystemId");
}
/**
@@ -241,7 +167,7 @@ public class HttpOperationInvoker implements OperationInvoker {
* @return an instance of the ScheduledExecutorService for scheduling periodic or delayed tasks.
* @see java.util.concurrent.ScheduledExecutorService
*/
- private ScheduledExecutorService getExecutorService() {
+ protected ScheduledExecutorService getExecutorService() {
return this.executorService;
}
@@ -258,43 +184,13 @@ public class HttpOperationInvoker implements OperationInvoker {
}
/**
- * Returns a reference to the Spring RestTemplate used by this HTTP-based OperationInvoker to send
- * HTTP requests to GemFire's REST interface, making REST API calls.
- *
- * @return an instance of the Spring RestTemplate used to make REST API web service calls.
- * @see org.springframework.web.client.RestTemplate
- */
- private RestTemplate getRestTemplate() {
- return this.restTemplate;
- }
-
- /**
- * Handles resource access errors such as ConnectExceptions when the server-side process/service
- * is not listening for client connections, or the connection to the server/service fails.
- *
- * @param e the ResourceAccessException resulting in some sort of I/O error.
- * @return a user-friendly String message describing the problem and appropriate action/response
- * by the user.
- * @see #stop()
- * @see org.springframework.web.client.ResourceAccessException
- */
- protected String handleResourceAccessException(final ResourceAccessException e) {
- stop();
-
- return String.format(
- "The connection to the GemFire Manager's HTTP service @ %1$s failed with: %2$s. "
- + "Please try reconnecting or see the GemFire Manager's log file for further details.",
- baseUrl, e.getMessage());
- }
-
- /**
* Displays the message inside GemFire shell at debug level.
*
* @param message the String containing the message to display inside Gfsh.
* @see #isDebugEnabled()
* @see #printInfo(String, Object...)
*/
- private void printDebug(final String message, final Object... args) {
+ protected void printDebug(final String message, final Object... args) {
if (isDebugEnabled()) {
printInfo(message, args);
}
@@ -330,62 +226,7 @@ public class HttpOperationInvoker implements OperationInvoker {
getGfsh().printAsSevere(String.format(message, args));
}
- private <T> T get(URI url, Class<T> responseType) {
- return send(url, HttpMethod.GET, null, null, responseType);
- }
-
- private <T> T post(URI url, MediaType mediaType, Object content, Class<T> responseType) {
- return send(url, HttpMethod.POST, mediaType, content, responseType);
- }
-
-
- private <T> T send(URI url, HttpMethod method, MediaType mediaType, Object content,
- Class<T> responseType) {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.USER_AGENT, USER_AGENT_HTTP_REQUEST_HEADER_VALUE);
- headers.setAccept(acceptableMediaTypes);
- if (mediaType != null) {
- headers.setContentType(mediaType);
- }
-
- if (this.securityProperties != null) {
- for (String key : securityProperties.stringPropertyNames()) {
- headers.add(key, securityProperties.getProperty(key));
- }
- }
-
- HttpEntity<Object> httpEntity = new HttpEntity<>(content, headers);
-
- final ResponseEntity<T> response =
- getRestTemplate().exchange(url, method, httpEntity, responseType);
- return response.getBody();
- }
-
- Object extractResponse(ClientHttpResponse response) throws IOException {
- MediaType mediaType = response.getHeaders().getContentType();
- if (mediaType.equals(MediaType.APPLICATION_JSON)) {
- return org.apache.commons.io.IOUtils.toString(response.getBody(), "UTF-8");
- } else {
- Path tempFile = Files.createTempFile("fileDownload", "");
- if (tempFile.toFile().exists()) {
- FileUtils.deleteQuietly(tempFile.toFile());
- }
- Files.copy(response.getBody(), tempFile);
- return tempFile;
- }
- }
- private void addHeaderValues(org.springframework.http.client.ClientHttpRequest request) {
- // update the headers
- request.getHeaders().add(HttpHeaders.USER_AGENT, USER_AGENT_HTTP_REQUEST_HEADER_VALUE);
- request.getHeaders().setAccept(acceptableMediaTypes);
-
- if (this.securityProperties != null) {
- for (String key : securityProperties.stringPropertyNames()) {
- request.getHeaders().add(key, securityProperties.getProperty(key));
- }
- }
- }
/**
* Determines whether this HTTP-based OperationInvoker is successfully connected to the remote
@@ -395,7 +236,7 @@ public class HttpOperationInvoker implements OperationInvoker {
*/
@Override
public boolean isConnected() {
- return (getRestTemplate() != null);
+ return connected;
}
/**
@@ -411,15 +252,6 @@ public class HttpOperationInvoker implements OperationInvoker {
return isConnected();
}
-
- private URI createURI(String path) {
- try {
- return new URI(baseUrl + path);
- } catch (URISyntaxException e) {
- throw new RuntimeException(e);
- }
- }
-
/**
* Read the attribute identified by name from a remote resource identified by name. The intent of
* this method is to return the value of an attribute on an MBean located in the remote
@@ -434,12 +266,11 @@ public class HttpOperationInvoker implements OperationInvoker {
*/
@Override
public Object getAttribute(final String resourceName, final String attributeName) {
- final URI link = UriComponentsBuilder.fromHttpUrl(baseUrl).path("/mbean/attribute")
- .queryParam("resourceName", resourceName).queryParam("attributeName", attributeName).build()
- .encode().toUri();
+ final URI link = HttpRequester.createURI(baseUrl, "/mbean/attribute", "resourceName",
+ resourceName, "attributeName", attributeName);
try {
- return IOUtils.deserializeObject(get(link, byte[].class));
+ return IOUtils.deserializeObject(httpRequester.get(link, byte[].class));
} catch (IOException e) {
throw new MBeanAccessException(String.format(
"De-serializing the result of accessing attribute (%1$s) on MBean (%2$s) failed!",
@@ -451,28 +282,11 @@ public class HttpOperationInvoker implements OperationInvoker {
}
}
- /**
- * Gets the identifier of the GemFire cluster.
- *
- * @return an integer value indicating the identifier of the GemFire cluster.
- */
@Override
public int getClusterId() {
return clusterId;
}
- private void initClusterId() {
- if (isReady()) {
- try {
- clusterId = (Integer) getAttribute(ManagementConstants.OBJECTNAME__DISTRIBUTEDSYSTEM_MXBEAN,
- "DistributedSystemId");
- printDebug("Cluster ID (%1$s)", clusterId);
- } catch (Exception ignore) {
- printDebug("Failed to determine cluster ID: %1$s", ignore.getMessage());
- }
- }
- }
-
/**
* Gets a proxy to the remote DistributedSystem MXBean to access attributes and invoke operations
* on the distributed system, or the GemFire cluster.
@@ -519,9 +333,9 @@ public class HttpOperationInvoker implements OperationInvoker {
@Override
public Object invoke(final String resourceName, final String operationName, final Object[] params,
final String[] signatures) {
- final URI link = createURI("/mbean/operation");
+ final URI link = HttpRequester.createURI(baseUrl, "/mbean/operation");
- MultiValueMap<String, Object> content = new LinkedMultiValueMap<>();
+ MultiValueMap<String, Object> content = new LinkedMultiValueMap<String, Object>();
content.add("resourceName", resourceName);
content.add("operationName", operationName);
@@ -537,8 +351,8 @@ public class HttpOperationInvoker implements OperationInvoker {
}
try {
- byte[] postResult = post(link, MediaType.MULTIPART_FORM_DATA, content, byte[].class);
- return IOUtils.deserializeObject(postResult);
+ return IOUtils.deserializeObject(
+ httpRequester.post(link, MediaType.MULTIPART_FORM_DATA, content, byte[].class));
} catch (IOException e) {
throw new MBeanAccessException(String.format(
"De-serializing the result from invoking operation (%1$s) on MBean (%2$s) failed!",
@@ -565,11 +379,12 @@ public class HttpOperationInvoker implements OperationInvoker {
@Override
@SuppressWarnings("unchecked")
public Set<ObjectName> queryNames(final ObjectName objectName, final QueryExp queryExpression) {
- final URI link = createURI("/mbean/query");
+ final URI link = HttpRequester.createURI(baseUrl, "/mbean/query");
Object content = new QueryParameterSource(objectName, queryExpression);
try {
- return (Set<ObjectName>) IOUtils.deserializeObject(post(link, null, content, byte[].class));
+ return (Set<ObjectName>) IOUtils
+ .deserializeObject(httpRequester.post(link, null, content, byte[].class));
} catch (Exception e) {
throw new MBeanAccessException(String.format(
"An error occurred while querying for MBean names using ObjectName pattern (%1$s) and Query expression (%2$s)!",
@@ -585,13 +400,13 @@ public class HttpOperationInvoker implements OperationInvoker {
if (executorService != null) {
executorService.shutdown();
}
-
- restTemplate = null;
+ httpRequester = null;
+ connected = false;
}
@Override
public String toString() {
- return String.format("GemFire Manager HTTP service @ %1$s", baseUrl);
+ return String.format("GemFire Manager HTTP service @ %1$s", httpRequester);
}
@@ -604,18 +419,19 @@ public class HttpOperationInvoker implements OperationInvoker {
*/
@Override
public Object processCommand(final CommandRequest command) {
- URI link = command.getHttpRequestUrl(baseUrl);
+ URI link =
+ HttpRequester.createURI(baseUrl, COMMANDS_URI, CMD_QUERY_PARAMETER, command.getUserInput());
if (command.hasFileData()) {
- MultiValueMap<String, Object> content = new LinkedMultiValueMap<>();
+ MultiValueMap<String, Object> content = new LinkedMultiValueMap<String, Object>();
Resource[] resources = ConvertUtils.convert(command.getFileData());
for (Resource resource : resources) {
content.add(RESOURCES_REQUEST_PARAMETER, resource);
}
- return post(link, MediaType.MULTIPART_FORM_DATA, content, String.class);
+ return httpRequester.post(link, MediaType.MULTIPART_FORM_DATA, content, String.class);
}
- return getRestTemplate().execute(link, HttpMethod.POST, this::addHeaderValues,
- this::extractResponse);
+ // when no file data to upload, this handles file download over http
+ return httpRequester.executeWithResponseExtractor(link);
}
}
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/web/http/support/HttpRequesterTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/web/http/support/HttpRequesterTest.java
new file mode 100644
index 0000000..912e77f
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/web/http/support/HttpRequesterTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.geode.management.internal.web.http.support;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URI;
+import java.nio.file.Path;
+import java.util.Properties;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TemporaryFolder;
+import org.mockito.ArgumentCaptor;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.mock.http.client.MockClientHttpResponse;
+import org.springframework.web.client.RestTemplate;
+
+import org.apache.geode.test.junit.categories.IntegrationTest;
+
+@Category(IntegrationTest.class)
+public class HttpRequesterTest {
+ @Rule
+ public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ private HttpRequester requester;
+ private ClientHttpResponse response;
+ private RestTemplate restTemplate;
+ private Properties securityProps;
+ private URI uri;
+ private ResponseEntity<String> responseEntity;
+
+ @Before
+ public void setup() {
+ uri = URI.create("http://test.org/test");
+ restTemplate = mock(RestTemplate.class);
+ ResponseEntity<String> responseEntity = mock(ResponseEntity.class);
+ when(restTemplate.exchange(any(), any(), any(), eq(String.class))).thenReturn(responseEntity);
+ when(responseEntity.getBody()).thenReturn("done");
+
+ securityProps = new Properties();
+ securityProps.setProperty("user", "me");
+ securityProps.setProperty("password", "secret");
+
+ }
+
+ @Test
+ public void extractResponseOfJsonString() throws Exception {
+ String responseString = "my response";
+ requester = new HttpRequester();
+ response =
+ new MockClientHttpResponse(IOUtils.toInputStream(responseString, "UTF-8"), HttpStatus.OK);
+
+ response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
+ Object result = requester.extractResponse(response);
+ assertThat(result).isEqualTo(responseString);
+ }
+
+ @Test
+ public void extractResponseOfFileDownload() throws Exception {
+ File responseFile = temporaryFolder.newFile();
+ FileUtils.writeStringToFile(responseFile, "some file contents", "UTF-8");
+ requester = new HttpRequester();
+ response = new MockClientHttpResponse(new FileInputStream(responseFile), HttpStatus.OK);
+ response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
+ Object result = requester.extractResponse(response);
+ Path fileResult = (Path) result;
+ assertThat(fileResult).hasSameContentAs(responseFile.toPath());
+ }
+
+ @Test
+ public void createURI() throws Exception {
+ requester = new HttpRequester();
+ assertThat(requester.createURI("http://test.org", "abc").toString())
+ .isEqualTo("http://test.org/abc");
+ assertThat(requester.createURI("http://test.org", "abc", "key", "value").toString())
+ .isEqualTo("http://test.org/abc?key=value");
+
+ assertThat(requester.createURI("http://test.org", "abc", "a-b", "c d").toString())
+ .isEqualTo("http://test.org/abc?a-b=c%20d");
+
+ assertThatThrownBy(() -> requester.createURI("http://test.org", "abc", "key"))
+ .isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void get() throws Exception {
+ requester = spy(new HttpRequester(securityProps, restTemplate));
+ String result = requester.get(uri, String.class);
+
+ assertThat(result).isEqualTo("done");
+ verify(requester).exchange(uri, HttpMethod.GET, null, null, String.class);
+
+ verifyHeaderIsUpdated();
+ }
+
+ @Test
+ public void post() throws Exception {
+ requester = spy(new HttpRequester(securityProps, restTemplate));
+ String result =
+ requester.post(uri, MediaType.APPLICATION_FORM_URLENCODED, "myData", String.class);
+
+ assertThat(result).isEqualTo("done");
+ verify(requester).exchange(uri, HttpMethod.POST, MediaType.APPLICATION_FORM_URLENCODED,
+ "myData", String.class);
+
+ verifyHeaderIsUpdated();
+ }
+
+ private void verifyHeaderIsUpdated() {
+ ArgumentCaptor<HttpHeaders> headerCaptor = ArgumentCaptor.forClass(HttpHeaders.class);
+ verify(requester).addHeaderValues(headerCaptor.capture());
+
+ HttpHeaders headers = headerCaptor.getValue();
+ assertThat(headers.get("user").get(0)).isEqualTo("me");
+ assertThat(headers.get("password").get(0)).isEqualTo("secret");
+ }
+}
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/web/shell/HttpOperationInvokerTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/web/shell/HttpOperationInvokerTest.java
deleted file mode 100644
index 58f88ab..0000000
--- a/geode-core/src/test/java/org/apache/geode/management/internal/web/shell/HttpOperationInvokerTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.geode.management.internal.web.shell;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.nio.file.Path;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.rules.TemporaryFolder;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.mock.http.client.MockClientHttpResponse;
-
-import org.apache.geode.test.junit.categories.IntegrationTest;
-
-@Category(IntegrationTest.class)
-public class HttpOperationInvokerTest {
- @Rule
- public TemporaryFolder temporaryFolder = new TemporaryFolder();
-
- private HttpOperationInvoker invoker;
- private ClientHttpResponse response;
-
- @Before
- public void setup() {}
-
- @Test
- public void extractResponseOfJsonString() throws Exception {
- String responseString = "my response";
- invoker = new HttpOperationInvoker();
- response =
- new MockClientHttpResponse(IOUtils.toInputStream(responseString, "UTF-8"), HttpStatus.OK);
-
- response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
- Object result = invoker.extractResponse(response);
- assertThat(result).isEqualTo(responseString);
- }
-
- @Test
- public void extractResponseOfFileDownload() throws Exception {
- File responseFile = temporaryFolder.newFile();
- FileUtils.writeStringToFile(responseFile, "some file contents", "UTF-8");
- invoker = new HttpOperationInvoker();
- response = new MockClientHttpResponse(new FileInputStream(responseFile), HttpStatus.OK);
- response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
- Object result = invoker.extractResponse(response);
- Path fileResult = (Path) result;
- assertThat(fileResult).hasSameContentAs(responseFile.toPath());
- }
-}
diff --git a/geode-web/src/test/java/org/apache/geode/management/internal/web/shell/HttpOperationInvokerSecurityTest.java b/geode-web/src/test/java/org/apache/geode/management/internal/web/shell/HttpOperationInvokerSecurityTest.java
index 5e74033..d19b5df 100644
--- a/geode-web/src/test/java/org/apache/geode/management/internal/web/shell/HttpOperationInvokerSecurityTest.java
+++ b/geode-web/src/test/java/org/apache/geode/management/internal/web/shell/HttpOperationInvokerSecurityTest.java
@@ -18,7 +18,6 @@ package org.apache.geode.management.internal.web.shell;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -91,7 +90,6 @@ public class HttpOperationInvokerSecurityTest {
invoker = (HttpOperationInvoker) gfsh.getGfsh().getOperationInvoker();
request = mock(CommandRequest.class);
- when(request.getHttpRequestUrl(anyString())).thenCallRealMethod();
when(request.getUserInput()).thenReturn("list members");
assertThatThrownBy(() -> invoker.processCommand(request))
--
To stop receiving notification emails like this one, please contact
['"commits@geode.apache.org" <co...@geode.apache.org>'].