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

Update BINARY_SUPPORT to use Content-Encoding to identify if data is binary #2170

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Zappa Changelog

## next
## 0.52.0
* Remove dateutil version restriction
* Fix failed downloads of wheel packages with non-alphanumeric characters
* Last release from Miserlou/Zappa
* Removed references to zappa.io

## 0.51.0
Expand Down
2 changes: 1 addition & 1 deletion zappa/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
'Zappa (and AWS Lambda) support the following versions of Python: {}'.format(formatted_supported_versions))
raise RuntimeError(err_msg)

__version__ = '0.51.0'
__version__ = '0.52.0'
3 changes: 2 additions & 1 deletion zappa/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2122,7 +2122,8 @@ def load_settings(self, settings_file=None, session=None):
runtime=self.runtime,
tags=self.tags,
endpoint_urls=self.stage_config.get('aws_endpoint_urls',{}),
xray_tracing=self.xray_tracing
xray_tracing=self.xray_tracing,
no_venv=self.vargs.get("no_venv") if self.vargs else None
)

for setting in CUSTOM_SETTINGS:
Expand Down
47 changes: 26 additions & 21 deletions zappa/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ def __init__(self,
runtime='python3.6', # Detected at runtime in CLI
tags=(),
endpoint_urls={},
xray_tracing=False
xray_tracing=False,
no_venv=False
):
"""
Instantiate this new Zappa instance, loading any custom credentials if necessary.
Expand Down Expand Up @@ -289,6 +290,7 @@ def __init__(self,
self.endpoint_urls = endpoint_urls
self.xray_tracing = xray_tracing

self.no_venv = no_venv
# Some common invocations, such as DB migrations,
# can take longer than the default.

Expand Down Expand Up @@ -522,34 +524,37 @@ def create_lambda_zip( self,
if not 'concurrent' in exclude:
exclude.append('concurrent')

def splitpath(path):
parts = []
(path, tail) = os.path.split(path)
while path and tail:
parts.append(tail)
to_exclude = []
if not self.no_venv:
def splitpath(path):
parts = []
(path, tail) = os.path.split(path)
parts.append(os.path.join(path, tail))
return list(map(os.path.normpath, parts))[::-1]
split_venv = splitpath(venv)
split_cwd = splitpath(cwd)

# Ideally this should be avoided automatically,
# but this serves as an okay stop-gap measure.
if split_venv[-1] == split_cwd[-1]: # pragma: no cover
print(
"Warning! Your project and virtualenv have the same name! You may want "
"to re-create your venv with a new name, or explicitly define a "
"'project_name', as this may cause errors."
)
while path and tail:
parts.append(tail)
(path, tail) = os.path.split(path)
parts.append(os.path.join(path, tail))
return list(map(os.path.normpath, parts))[::-1]
split_venv = splitpath(venv)
split_cwd = splitpath(cwd)

# Ideally this should be avoided automatically,
# but this serves as an okay stop-gap measure.
if split_venv[-1] == split_cwd[-1]: # pragma: no cover
print(
"Warning! Your project and virtualenv have the same name! You may want "
"to re-create your venv with a new name, or explicitly define a "
"'project_name', as this may cause errors."
)
to_exclude = [split_venv[-1]]

# First, do the project..
temp_project_path = tempfile.mkdtemp(prefix='zappa-project')
temp_project_path = tempfile.mkdtemp(prefix='zappa-project')

if not slim_handler:
# Slim handler does not take the project files.
if minify:
# Related: https://github.com/Miserlou/Zappa/issues/744
excludes = ZIP_EXCLUDES + exclude + [split_venv[-1]]
excludes = ZIP_EXCLUDES + exclude + to_exclude
copytree(cwd, temp_project_path, metadata=False, symlinks=False, ignore=shutil.ignore_patterns(*excludes))
else:
copytree(cwd, temp_project_path, metadata=False, symlinks=False)
Expand Down
27 changes: 21 additions & 6 deletions zappa/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,13 +549,28 @@ def handler(self, event, context):
zappa_returndict.setdefault('statusDescription', response.status)

if response.data:
if settings.BINARY_SUPPORT and \
not response.mimetype.startswith("text/") \
and response.mimetype != "application/json":
zappa_returndict['body'] = base64.b64encode(response.data).decode('utf-8')
zappa_returndict["isBase64Encoded"] = True
content_encoding = response.headers.get("Content-Encoding", None)
binary_encodings = ("gzip", "compress", "deflate", "br")
if settings.BINARY_SUPPORT and content_encoding in binary_encodings:
try:
zappa_returndict["body"] = base64.b64encode(response.data).decode("utf8")
zappa_returndict["isBase64Encoded"] = True
except UnicodeDecodeError as e:
logger.exception(e)
logger.error(f"Unable to decode resulting base64 encoded response.data as 'utf8': response.data={response.data}")
logger.warning("Using response.get_data(as_text=True)")
zappa_returndict["body"] = response.get_data(as_text=True)
else:
zappa_returndict['body'] = response.get_data(as_text=True)
try:
zappa_returndict["body"] = response.get_data(as_text=True)
except UnicodeDecodeError:
# If data can't be decoded as utf-8, try processing as binary
logger.warning(
"UnicodeDecodeError on response.get_data(as_text=True), "
"unable to decode response.data as 'utf8': encoding as base64 isBase64Encoded=True"
)
zappa_returndict["body"] = base64.b64encode(response.data).decode("utf8")
zappa_returndict["isBase64Encoded"] = True

zappa_returndict['statusCode'] = response.status_code
if 'headers' in event:
Expand Down