Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow to set a signature host for tunnel usage with async client #862

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions opensearchpy/helpers/asyncsigner.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
# GitHub history for details.

from typing import Any, Dict, Optional, Union
from urllib.parse import parse_qs, urlencode, urlparse


class AWSV4SignerAsyncAuth:
Expand All @@ -34,15 +35,17 @@
url: str,
query_string: Optional[str] = None,
body: Optional[Union[str, bytes]] = None,
headers: Optional[Dict[str, str]] = None,
) -> Dict[str, str]:
return self._sign_request(method, url, query_string, body)
return self._sign_request(method, url, query_string, body, headers)

def _sign_request(
self,
method: str,
url: str,
query_string: Optional[str],
body: Optional[Union[str, bytes]],
headers: Optional[Dict[str, str]],
) -> Dict[str, str]:
"""
This method helps in signing the request by injecting the required headers.
Expand All @@ -53,10 +56,12 @@
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest

signature_host = self._fetch_url(url, headers or dict()) # type: ignore

# create an AWS request object and sign it using SigV4Auth
aws_request = AWSRequest(
method=method,
url=url,
url=signature_host,
data=body,
)

Expand All @@ -80,3 +85,26 @@

# copy the headers from AWS request object into the prepared_request
return dict(aws_request.headers.items())

def _fetch_url(self, url, headers): # type: ignore
"""
This is a util method that helps in reconstructing the request url.
:param prepared_request: unsigned request
:return: reconstructed url
"""
url = urlparse(url)
path = url.path or "/"

# fetch the query string if present in the request
querystring = ""
if url.query:
querystring = "?" + urlencode(

Check warning on line 101 in opensearchpy/helpers/asyncsigner.py

View check run for this annotation

Codecov / codecov/patch

opensearchpy/helpers/asyncsigner.py#L101

Added line #L101 was not covered by tests
parse_qs(url.query, keep_blank_values=True), doseq=True
)

# fetch the host information from headers
headers = {key.lower(): value for key, value in headers.items()}
location = headers.get("host") or url.netloc

# construct the url and return
return url.scheme + "://" + location + path + querystring
1 change: 1 addition & 0 deletions test_opensearchpy/test_async/test_signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ def _sign_request(
url: str,
query_string: Optional[str] = None,
body: Optional[Union[str, bytes]] = None,
headers: Optional[Dict[str, str]] = None,
) -> Dict[str, str]:
nonlocal signed_url
signed_url = url
Expand Down
Loading