Repository: Miserlou/Zappa

Issue:
Bug using slim_handler when project name begins with an 's'
<!--- Provide a general summary of the issue in the Title above -->
## Context
<!--- Provide a more detailed introduction to the issue itself, and why you consider it to be a bug -->
When a project name starts with a lowercase 's' and the project uses Zappa's slim_handler, Zappa tries to fetch a non-existent file from S3
<!--- Also, please make sure that you are running Zappa _from a virtual environment_ and are using Python 2.7 --> 

## Expected Behavior
<!--- Tell us what should happen -->
Zappa's slim_handler should download zip files that begin with 's' (ex: saffron_current_project.zip)
## Actual Behavior
<!--- Tell us what happens instead -->
Zappa strips the leading 's' and attempts to pull 'affron_current_project.zip' from S3

## Possible Fix
<!--- Not obligatory, but suggest a fix or reason for the bug -->
At handler.py:161, instead of using lstrip (which will strip based on the individual characters within 's3://') we could try using a regular expression 
`remote_bucket, remote_file = re.sub('^s3://', '', project_zip_path).split('/', 1)`

## Steps to Reproduce
<!--- Provide a link to a live example, or an unambiguous set of steps to -->
<!--- reproduce this bug include code to reproduce, if relevant -->
1. Enable slim_handler
2. Make first character in project name a lowercase 's'
3. Attempt to load the remote zip by calling the lambda function

## Your Environment
<!--- Include as many relevant details about the environment you experienced the bug in -->
* Zappa version used: 0.42.0
* Operating System and Python version: Linux/Python3.6
* The output of `pip freeze`:
appdirs==1.4.3
argcomplete==1.8.2
awscli==1.11.91
base58==0.2.4
boto==2.47.0
boto3==1.4.4
botocore==1.5.40
click==6.7
colorama==0.3.7
defusedxml==0.5.0
Django==1.11.1
django-allauth==0.32.0
django-filter==1.0.4
django-redis==4.8.0
django-rest-auth==0.9.1
django-storages==1.5.2
djangorestframework==3.6.3
docutils==0.13.1
durationpy==0.4
factory-boy==2.8.1
Faker==0.7.12
future==0.16.0
futures==3.1.1
hjson==2.0.2
jmespath==0.9.2
kappa==0.6.0
lambda-packages==0.15.0
Markdown==2.6.8
oauthlib==2.0.2
packaging==16.8
placebo==0.8.1
psycopg2==2.7.1
pyasn1==0.2.3
pyparsing==2.2.0
python-dateutil==2.6.0
python-slugify==1.2.4
python3-openid==3.1.0
pytz==2017.2
PyYAML==3.12
redis==2.10.5
requests==2.14.2
requests-oauthlib==0.8.0
rsa==3.4.2
s3transfer==0.1.10
six==1.10.0
toml==0.9.2
tqdm==4.11.2
troposphere==1.9.3
Unidecode==0.4.20
Werkzeug==0.12
wsgi-request-logger==0.4.6
zappa==0.42.0

* Link to your project (optional):
* Your `zappa_settings.py`: 
{
  "production": {
    "slim_handler": true,
    "exclude": ["*.gz", "*.rar", "deploy*", "lib64*"],
    "django_settings": "saffron.settings",
    "s3_bucket": "mybucket",
    "aws_region": "us-east-1",
    "project_name": "saffron",
    "debug": "true",
    "runtime": "python3.6",
  }
}


Discussion:
This is a hilarious and incredible bug. @mcrowson :)
Lol for sure! I think I might see the problem. In the load_remote_project_zip function in handler.py I should have os.path.join instead of assuming unix paths. I am still traveling and won't have a chance to get to this for a few days if someone else wants to try that approach. 
Lol ok scratch that, it is probably a good thing to do anyhow but of course the lambda environment is unix. Now that I think about it there is probably similar code (I don't feel like scrolling through on my phone to find it) when the project zip gets created. Either that or take a look at when the project zip path is added to the zappa_settings.py file. 

Resolving patch:
diff --git a/zappa/handler.py b/zappa/handler.py
--- a/zappa/handler.py
+++ b/zappa/handler.py
@@ -158,7 +158,7 @@ def load_remote_project_zip(self, project_zip_path):
                 boto_session = self.session
 
             # Download the zip
-            remote_bucket, remote_file = project_zip_path.lstrip('s3://').split('/', 1)
+            remote_bucket, remote_file = parse_s3_url(project_zip_path)
             s3 = boto_session.resource('s3')
 
             zip_path = '/tmp/{0!s}'.format(remote_file)


Test patch: