Initial commit

This commit is contained in:
2023-05-15 21:02:21 -07:00
commit 37a0247acc
4 changed files with 99 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
venv
urlshorten.zip

16
README.md Normal file
View File

@@ -0,0 +1,16 @@
# URL Shortener
There are many; this is mine.
## Bundling for upload
Create a virtual environment
python -m venv venv
source venv/bin/activate
Install dependencies
python -m pip install -r requirements.txt
Zip it all up
cd venv/lib/python3.10/site-packages
zip -r ../../../../urlshorten.zip .
cd ../../../../
zip -g urlshorten.zip urlshorten.py

5
requirements.txt Normal file
View File

@@ -0,0 +1,5 @@
certifi==2023.5.7
charset-normalizer==3.1.0
idna==3.4
requests==2.29.0
urllib3==1.26.15

76
urlshorten.py Normal file
View File

@@ -0,0 +1,76 @@
import boto3
import os
import requests
from base64 import b64decode
from botocore.exceptions import ClientError
dynamodb = boto3.resource('dynamodb', region_name='us-west-2')
ENCRYPTED = os.environ['RECAPTCHA_SECRET']
# Decrypt code should run once and variables stored outside of the function
# handler so that these are decrypted once per container
RECAPTCHA_SECRET = boto3.client('kms').decrypt(CiphertextBlob=b64decode(ENCRYPTED))['Plaintext']
def lambda_handler(event, context):
table = dynamodb.Table('urlshorten')
if 'from' in event and 'to' in event:
captcha_data = {
'secret': RECAPTCHA_SECRET,
'response': event['g-recaptcha-response'],
'remoteip': event['remoteip']
}
verify = requests.get('https://www.google.com/recaptcha/api/siteverify',
params=captcha_data)
if not (verify.status_code == 200 and verify.json()['success']):
return {
'status': 'error',
'error': verify.json()
}
ssl = event['to'][:5].lower() == 'https'
url = ('https://' if ssl else 'http://') + event['to'].split('://')[-1]
try:
table.put_item(
Item={
'key': event['from'],
'value': url
},
ConditionExpression='attribute_not_exists(#key)',
ExpressionAttributeNames={
'#key': 'key'
}
)
except ClientError as e:
return {
'status': 'error',
'error': e.response['Error']
}
except KeyError:
return {
'status': 'error',
'error': 'Invalid Request',
'location': '/'
}
else:
return {
'status': 'ok'
}
try:
response = table.get_item(Key={ 'key': event['shortUrl'] })
location = response['Item']['value']
except ClientError as e:
return e.response['Error']
except KeyError:
return {
'location': '/'
}
else:
return {
'location': response['Item']['value']
}