Repository: localstack/localstack

Issue:
OpenSearch is not gzipped when Accept-Encoding: gzip is defined
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Current Behavior

In version 1.4.0 OpenSearch is returning invalid responses when specifying gzip encoding. This was working in 1.3.1. The proxied response is not gzip encoded even though the content-encoding response header says its gzip. Reproduction steps show the differences between the output directly from OpenSearch vs the proxied result.

### Expected Behavior

Returning properly encoded responses.

### How are you starting LocalStack?

With a docker-compose file

### Steps To Reproduce

```
version: "3.9"

services:
  opensearch:
    container_name: opensearch
    image: opensearchproject/opensearch:2.3.0
    environment:
      - node.name=opensearch
      - cluster.name=opensearch-docker-cluster
      - discovery.type=single-node
      - bootstrap.memory_lock=true
      - "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
      - "DISABLE_SECURITY_PLUGIN=true"
    ports:
      - "9200:9200"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data01:/usr/share/opensearch/data

  localstack:
    container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}"
    image: localstack/localstack
    ports:
      - "4566:4566"
    depends_on:
      - opensearch
    environment:
      - OPENSEARCH_CUSTOM_BACKEND=http://opensearch:9200
      - DEBUG=${DEBUG- }
      - PERSISTENCE=${PERSISTENCE- }
      - DOCKER_HOST=unix:///var/run/docker.sock
    volumes:
      - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack"
      - "/var/run/docker.sock:/var/run/docker.sock"

volumes:
  data01:
    driver: local
```

1. Run docker compose
```sh
docker-compose up -d
```

2. Create the OpenSearch domain:
```
awslocal opensearch create-domain --domain-name my-domain
```

3. Test - Notice content length and output
```
curl -v -X GET my-domain.us-east-1.opensearch.localhost.localstack.cloud:4566/  -H 'Accept-Encoding: gzip' --output -
curl -v -X GET localhost:9200/ -H 'Accept-Encoding: gzip' --output -
```


### Environment

```markdown
- OS:
- LocalStack: latest 1.4.0
```


### Anything else?

_No response_


Discussion:
Welcome to LocalStack! Thanks for reporting your first issue and our team will be working towards fixing the issue for you or reach out for more background information. We recommend joining our [Slack Community](https://localstack.cloud/contact/) for real-time help and drop a message to LocalStack Pro Support if you are a Pro user! If you are willing to contribute towards fixing this issue, please have a look at our [contributing guidelines](https://github.com/localstack/.github/blob/main/CONTRIBUTING.md) and our [contributing guide](https://docs.localstack.cloud/contributing/).

Resolving patch:
diff --git a/localstack/services/opensearch/cluster.py b/localstack/services/opensearch/cluster.py
--- a/localstack/services/opensearch/cluster.py
+++ b/localstack/services/opensearch/cluster.py
@@ -14,7 +14,7 @@
     EngineType,
     ValidationException,
 )
-from localstack.http.client import SimpleRequestsClient
+from localstack.http.client import SimpleStreamingRequestsClient
 from localstack.http.proxy import ProxyHandler
 from localstack.services.edge import ROUTER
 from localstack.services.infra import DEFAULT_BACKEND_HOST
@@ -229,7 +229,7 @@ def register_cluster(
     forward_url = config.OPENSEARCH_CUSTOM_BACKEND or forward_url
 
     # if the opensearch security plugin is enabled, only TLS connections are allowed, but the cert cannot be verified
-    client = SimpleRequestsClient()
+    client = SimpleStreamingRequestsClient()
     client.session.verify = False
     endpoint = ProxyHandler(forward_url, client)
 
@@ -416,7 +416,8 @@ def _base_settings(self, dirs) -> CommandSettings:
             "http.publish_port": self.port,
             "transport.port": "0",
             "network.host": self.host,
-            "http.compression": "false",
+            # TODO this breaks the cluster check?!
+            "http.compression": "true",
             "path.data": f'"{dirs.data}"',
             "path.repo": f'"{dirs.backup}"',
             "discovery.type": "single-node",


Test patch:
diff --git a/tests/integration/test_opensearch.py b/tests/integration/test_opensearch.py
--- a/tests/integration/test_opensearch.py
+++ b/tests/integration/test_opensearch.py
@@ -1,3 +1,4 @@
+import gzip
 import json
 import logging
 import os
@@ -473,6 +474,13 @@ def test_describe_domains(self, opensearch_domain, aws_client):
         assert len(response["DomainStatusList"]) == 1
         assert response["DomainStatusList"][0]["DomainName"] == opensearch_domain
 
+    def test_gzip_responses(self, opensearch_endpoint):
+        gzip_response = requests.get(opensearch_endpoint, stream=True)
+        # get the raw data, don't let requests decode the response
+        raw_data = b"".join(chunk for chunk in gzip_response.raw.stream(1024, decode_content=False))
+        # force the gzip decoding here (which would raise an exception if it's not actually gzip)
+        assert gzip.decompress(raw_data)
+
     def test_domain_version(self, opensearch_domain, opensearch_create_domain, aws_client):
         response = aws_client.opensearch.describe_domain(DomainName=opensearch_domain)
         assert "DomainStatus" in response