From a62c920b7f6c05dc177895ddfdd49fa4e1e33d6e Mon Sep 17 00:00:00 2001 From: toepkerd <120457569+toepkerd@users.noreply.github.com> Date: Tue, 16 Apr 2024 16:30:52 -0700 Subject: [PATCH] Adding Max HTTP Response Size IT (#901) * Adding integ test for HTTP response max size setting Signed-off-by: Dennis Toepker * misc build fixes Signed-off-by: Dennis Toepker --------- Signed-off-by: Dennis Toepker Co-authored-by: Dennis Toepker --- .../core/setting/PluginSettings.kt | 8 +- notifications/notifications/build.gradle | 1 + .../integtest/MaxHTTPResponseSizeIT.kt | 102 ++++++++++++++++++ 3 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 notifications/notifications/src/test/kotlin/org/opensearch/integtest/MaxHTTPResponseSizeIT.kt diff --git a/notifications/core/src/main/kotlin/org/opensearch/notifications/core/setting/PluginSettings.kt b/notifications/core/src/main/kotlin/org/opensearch/notifications/core/setting/PluginSettings.kt index cb1af620..74dfd3e9 100644 --- a/notifications/core/src/main/kotlin/org/opensearch/notifications/core/setting/PluginSettings.kt +++ b/notifications/core/src/main/kotlin/org/opensearch/notifications/core/setting/PluginSettings.kt @@ -153,9 +153,9 @@ internal object PluginSettings { private const val DEFAULT_SOCKET_TIMEOUT_MILLISECONDS = 50000 /** - * Default maximum HTTP response string length + * Default maximum HTTP response size */ - private val DEFAULT_MAX_HTTP_RESPONSE_SIZE = SETTING_HTTP_MAX_CONTENT_LENGTH.getDefault(Settings.EMPTY).getBytes().toInt() + private val DEFAULT_MAX_HTTP_RESPONSE_SIZE = SETTING_HTTP_MAX_CONTENT_LENGTH.getDefault(Settings.EMPTY).bytes.toInt() /** * Default email header length. minimum value from 100 reference emails @@ -235,7 +235,7 @@ internal object PluginSettings { var socketTimeout: Int /** - * Maximum HTTP response string length + * Maximum HTTP response size */ @Volatile var maxHttpResponseSize: Int @@ -513,7 +513,7 @@ internal object PluginSettings { val clusterMaxHttpResponseSize = clusterService.clusterSettings.get(MAX_HTTP_RESPONSE_SIZE) if (clusterMaxHttpResponseSize != null) { log.debug("$LOG_PREFIX:$MAX_HTTP_RESPONSE_SIZE_KEY -autoUpdatedTo-> $clusterMaxHttpResponseSize") - socketTimeout = clusterSocketTimeout + maxHttpResponseSize = clusterMaxHttpResponseSize } val clusterAllowedConfigTypes = clusterService.clusterSettings.get(ALLOWED_CONFIG_TYPES) if (clusterAllowedConfigTypes != null) { diff --git a/notifications/notifications/build.gradle b/notifications/notifications/build.gradle index 7d45e886..8dc64127 100644 --- a/notifications/notifications/build.gradle +++ b/notifications/notifications/build.gradle @@ -233,6 +233,7 @@ integTest { if (usingRemoteCluster) { filter { excludeTestsMatching "org.opensearch.integtest.send.SendTestMessageWithMockServerIT" + excludeTestsMatching "org.opensearch.integtest.MaxHTTPResponseSizeIT" } } } diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/MaxHTTPResponseSizeIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/MaxHTTPResponseSizeIT.kt new file mode 100644 index 00000000..6aadd64f --- /dev/null +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/MaxHTTPResponseSizeIT.kt @@ -0,0 +1,102 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.integtest + +import com.sun.net.httpserver.HttpServer +import org.junit.AfterClass +import org.junit.Assert +import org.junit.BeforeClass +import org.opensearch.core.rest.RestStatus +import org.opensearch.notifications.NotificationPlugin +import org.opensearch.rest.RestRequest +import java.net.InetAddress +import java.net.InetSocketAddress + +internal class MaxHTTPResponseSizeIT : PluginRestTestCase() { + fun `test HTTP response has truncated size`() { + // update max http response size setting + val updateSettingJsonString = """ + { + "transient": { + "opensearch.notifications.core.max_http_response_size": "8" + } + } + """.trimIndent() + + val updateSettingsResponse = executeRequest( + RestRequest.Method.PUT.name, + "/_cluster/settings", + updateSettingJsonString, + RestStatus.OK.status + ) + Assert.assertNotNull(updateSettingsResponse) + logger.info("update settings response: $updateSettingsResponse") + Thread.sleep(1000) + + val url = "http://${server.address.hostString}:${server.address.port}/webhook" + + val createRequestJsonString = """ + { + "config":{ + "name":"this is a sample config name", + "description":"this is a sample config description", + "config_type":"webhook", + "is_enabled":true, + "webhook":{ + "url":"$url", + "header_params": { + "Content-type": "text/plain" + } + } + } + } + """.trimIndent() + val configId = createConfigWithRequestJsonString(createRequestJsonString) + Assert.assertNotNull(configId) + Thread.sleep(1000) + + // send test message + val sendResponse = executeRequest( + RestRequest.Method.POST.name, + "${NotificationPlugin.PLUGIN_BASE_URI}/feature/test/$configId", + "", + RestStatus.OK.status + ) + + logger.info("response: $sendResponse") + + val statusText = sendResponse.getAsJsonArray("status_list")[0].asJsonObject["delivery_status"].asJsonObject["status_text"].asString + + // we set the max HTTP response size to 8 bytes, which means the expected string length of the response is 8 / 2 (bytes per Java char) = 4 + Assert.assertEquals(4, statusText.length) + } + + companion object { + private lateinit var server: HttpServer + + @JvmStatic + @BeforeClass + fun setupWebhook() { + server = HttpServer.create(InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0) + + server.createContext("/webhook") { + val response = "This is a longer than usual response that should be truncated" + it.sendResponseHeaders(200, response.length.toLong()) + val os = it.responseBody + os.write(response.toByteArray()) + os.close() + } + + server.start() + } + + @JvmStatic + @AfterClass + fun stopMockServer() { + server.stop(1) + } + } +}