Skip to content

Commit

Permalink
Attempt to recover from Error: 415, Unsupported Media Type.
Browse files Browse the repository at this point in the history
  • Loading branch information
niccolozanotti committed Sep 4, 2024
1 parent eed8fc1 commit fd22761
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 41 deletions.
118 changes: 79 additions & 39 deletions lambda_function.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
from flask import Flask, request, jsonify
import json
from flask import Flask, request
from flask_cors import CORS
from flask.ctx import AppContext
from werkzeug.test import EnvironBuilder
from werkzeug.wrappers import Request
from datetime import datetime, timezone
import csv
import boto3


app = Flask(__name__)
CORS(app, resources={r"/*": {"origins": "*"}}, supports_credentials=True)

today = datetime.today()

# Initialize the S3 client
s3 = boto3.client('s3')
BUCKET_NAME = 'ugo-people-tracker' # S3 bucket name
LOG_FILE_KEY = f'{today.strftime("%Y-%m-%d")}-logs.csv' # One log file for each day


# In-memory storage for current occupants
occupants = set()
Expand All @@ -23,28 +22,36 @@
@app.route('/people/register', methods=['POST'])
def register():
data = request.json
name = data['name']
occupants.add(name)
log_action(name, 'register')
return jsonify({"status": "registered", "occupants": list(occupants)})
name = data.get('name')
if name:
occupants.add(name)
log_action(name, 'register')
return json.dumps({"status": "registered", "occupants": list(occupants)}), 200, {
'Content-Type': 'application/json'}
else:
return json.dumps({"error": "Name is required"}), 400, {'Content-Type': 'application/json'}


@app.route('/people/unregister', methods=['POST'])
def unregister():
data = request.json
name = data['name']
occupants.discard(name) # set.discard() avoids KeyError if name not in set
log_action(name, 'unregister')
return jsonify({"status": "unregistered", "occupants": list(occupants)})
name = data.get('name')
if name:
occupants.discard(name)
log_action(name, 'unregister')
return json.dumps({"status": "unregistered", "occupants": list(occupants)}), 200, {
'Content-Type': 'application/json'}
else:
return json.dumps({"error": "Name is required"}), 400, {'Content-Type': 'application/json'}


@app.route('/people/status', methods=['GET'])
def status():
return jsonify({
return json.dumps({
"status": "open" if occupants else "closed",
"occupants": list(occupants),
"count": len(occupants)
})
}), 200, {'Content-Type': 'application/json'}


def log_action(name, action):
Expand All @@ -54,7 +61,9 @@ def log_action(name, action):


def append_log_to_s3(log_entry):
log_file = f'/tmp/{today.strftime("%Y-%m-%d")}-logs.csv' # Temporary file path
today = datetime.today()
LOG_FILE_KEY = f'{today.strftime("%Y-%m-%d")}-logs.csv'
log_file = f'/tmp/{LOG_FILE_KEY}' # Temporary file path

# Download the existing log file from S3 if it exists
try:
Expand All @@ -74,28 +83,59 @@ def append_log_to_s3(log_entry):
s3.upload_file(log_file, BUCKET_NAME, LOG_FILE_KEY)


def my_lambda_function(event):
# Extract the required data from the event
path = event['path']
http_method = event['httpMethod']
query_params = event.get('queryStringParameters', {})
body = event.get('body', {})

# Mimic Flask's request context
with app.test_request_context(path=path, method=http_method, query_string=query_params, data=body):
# Route the request to the Flask app
response = app.full_dispatch_request()
return {
'statusCode': response.status_code,
'body': response.get_data(as_text=True),
'headers': dict(response.headers)
}


def lambda_handler(event, context):
result = my_lambda_function(event)
return result

# Print the event for debugging
print(f"Received event: {json.dumps(event)}")

# Extract relevant information from the event
http_method = event['httpMethod']
path = event['path']
headers = event.get('headers', {})

# Process the body
body = event.get('body', '{}')
if isinstance(body, str):
try:
body = json.loads(body)
except json.JSONDecodeError:
pass # Keep body as string if it's not JSON

# Ensure Content-Type is set
headers['Content-Type'] = 'application/json'

# Create a WSGI environment
environ = EnvironBuilder(
path=path,
method=http_method,
headers=headers,
data=json.dumps(body) if isinstance(body, dict) else body,
).get_environ()

# Create a request object
req = Request(environ)

# Push an application context
with AppContext(app):
# Handle the request
with app.request_context(environ):
try:
# Dispatch the request to Flask
response = app.full_dispatch_request()

return {
'statusCode': response.status_code,
'body': response.get_data(as_text=True),
'headers': dict(response.headers)
}
except Exception as e:
print(f"Error: {str(e)}")
return {
'statusCode': 500,
'body': json.dumps({"error": "Internal server error"}),
'headers': {'Content-Type': 'application/json'}
}


# For local testing
if __name__ == '__main__':
app.run(debug=True)
app.run(debug=True)
5 changes: 3 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Flask
flask
boto3
flask_cors
flask_cors
werkzeug

0 comments on commit fd22761

Please sign in to comment.