def lambda_handler(event, context):
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "zappa_settings")
import django
django.setup()
# This is a normal HTTP request
if event.get('method', None):
handler = LambdaHandler()
environ = create_wsgi_request(event)
response = handler(environ)
returnme = {'Content': response.content}
for item in response.items():
returnme[item[0]] = item[1]
returnme['Status'] = response.status_code
if response.status_code != 200:
# So that we can always match on the first few characters
# ex '{"AAA": "404'
# returnme['AAA'] = str(response.status_code)
# returnme['errorMessage'] = str(response.status_code)
# returnme['errorType'] = str(response.status_code)
# returnme['stackTrace'] = str(response.status_code)
# error_json = json.dumps(returnme, sort_keys=True)
# print "Error JSON:"
# print error_json
content = response.content
content = "<!DOCTYPE html>" + str(response.status_code) + response.content
b64_content = base64.b64encode(content)
print b64_content
raise Exception(b64_content)
print returnme
return returnme
# This is a management command invocation.
elif event.get('command', None):
from django.core import management
# Couldn't figure out how to get the value into stdout with StringIO..
# Read the log for now. :[]
management.call_command(*event['command'].split(' '))
return {}
#.........这里部分代码省略.........
else:
try: # Support both for tests
from zappa.ext.django import get_django_wsgi
except ImportError as e: # pragma: no cover
from django_zappa_app import get_django_wsgi
# Get the Django WSGI app from our extension
app_function = get_django_wsgi(settings.DJANGO_SETTINGS)
trailing_slash = True
app = ZappaWSGIMiddleware(app_function)
# This is a normal HTTP request
if event.get('method', None):
# If we just want to inspect this,
# return this event instead of processing the request
# https://your_api.aws-api.com/?event_echo=true
event_echo = getattr(settings, "EVENT_ECHO", True)
if event_echo and 'event_echo' in event['params'].values():
return {'Content': str(event) + '\n' + str(context), 'Status': 200}
if settings.DOMAIN:
# If we're on a domain, we operate normally
script_name = ''
else:
# But if we're not, then our base URL
# will be something like
# https://blahblahblah.execute-api.us-east-1.amazonaws.com/dev
# So, we need to make sure the WSGI app knows this.
script_name = '/' + settings.API_STAGE
# Create the environment for WSGI and handle the request
environ = create_wsgi_request(event,
script_name=script_name,
trailing_slash=trailing_slash
)
# We are always on https on Lambda, so tell our wsgi app that.
environ['HTTPS'] = 'on'
environ['wsgi.url_scheme'] = 'https'
# Execute the application
response = Response.from_app(app, environ)
# This is the object we're going to return.
# Pack the WSGI response into our special dictionary.
zappa_returndict = dict(response.headers)
if 'Content' not in zappa_returndict and response.data:
zappa_returndict['Content'] = response.data
zappa_returndict['Status'] = response.status_code
# To ensure correct status codes, we need to
# pack the response as a deterministic B64 string and raise it
# as an error to match our APIGW regex.
# The DOCTYPE ensures that the page still renders in the browser.
exception = None
if response.status_code in ERROR_CODES:
content = u"<!DOCTYPE html>" + unicode(response.status_code) + unicode('<meta charset="utf-8" />') + response.data.encode('utf-8')
exception = base64.b64encode(content)
# Internal are changed to become relative redirects
# so they still work for apps on raw APIGW and on a domain.
elif 300 <= response.status_code < 400 and hasattr(response, 'Location'):
# Location is by default relative on Flask. Location is by default
def handler(self, event, context):
"""
An AWS Lambda function which parses specific API Gateway input into a
WSGI request, feeds it to our WSGI app, procceses the response, and returns
that back to the API Gateway.
"""
time_start = datetime.datetime.now()
settings = self.settings
# The app module
app_module = importlib.import_module(settings.APP_MODULE)
# The application
app_function = getattr(app_module, settings.APP_FUNCTION)
app = ZappaWSGIMiddleware(app_function)
# This is a normal HTTP request
if event.get('method', None):
# If we just want to inspect this,
# return this event instead of processing the request
# https://your_api.aws-api.com/?event_echo=true
event_echo = getattr(settings, "EVENT_ECHO", True)
if event_echo:
if 'event_echo' in list(event['params'].values()):
return {'Content': str(event) + '\n' + str(context), 'Status': 200}
# Create the environment for WSGI and handle the request
environ = create_wsgi_request(event, script_name='',
trailing_slash=False)
# We are always on https on Lambda, so tell our wsgi app that.
environ['wsgi.url_scheme'] = 'https'
response = Response.from_app(app, environ)
zappa_returndict = dict()
if response.data:
zappa_returndict['Content'] = response.data
# Pack the WSGI response into our special dictionary.
for (header_name, header_value) in response.headers:
zappa_returndict[header_name] = header_value
zappa_returndict['Status'] = response.status_code
# To ensure correct status codes, we need to
# pack the response as a deterministic B64 string and raise it
# as an error to match our APIGW regex.
# The DOCTYPE ensures that the page still renders in the browser.
exception = None
if response.status_code in [400, 401, 403, 404, 500]:
content = "<!DOCTYPE html>" + str(response.status_code) + response.data
exception = base64.b64encode(content)
# Internal are changed to become relative redirects
# so they still work for apps on raw APIGW and on a domain.
elif response.status_code in [301, 302]:
# Location is by default relative on Flask. Location is by default
# absolute on Werkzeug. We can set autocorrect_location_header on
# the response to False, but it doesn't work. We have to manually
# remove the host part.
location = response.location
hostname = 'https://' + environ['HTTP_HOST']
if location.startswith(hostname):
exception = location[len(hostname):]
# Calculate the total response time,
# and log it in the Common Log format.
time_end = datetime.datetime.now()
delta = time_end - time_start
response_time_ms = delta.total_seconds() * 1000
response.content = response.data
common_log(environ, response, response_time=response_time_ms)
# Finally, return the response to API Gateway.
if exception: # pragma: no cover
raise Exception(exception)
else:
return zappa_returndict
#.........这里部分代码省略.........
else:
try: # Support both for tests
from zappa.ext.django import get_django_wsgi
except ImportError as e: # pragma: no cover
from django_zappa_app import get_django_wsgi
# Get the Django WSGI app from our extension
app_function = get_django_wsgi(settings.DJANGO_SETTINGS)
trailing_slash = True
app = ZappaWSGIMiddleware(app_function)
# This is a normal HTTP request
if event.get('method', None):
# If we just want to inspect this,
# return this event instead of processing the request
# https://your_api.aws-api.com/?event_echo=true
event_echo = getattr(settings, "EVENT_ECHO", True)
if event_echo and 'event_echo' in event['params'].values():
return {'Content': str(event) + '\n' + str(context), 'Status': 200}
if settings.DOMAIN:
# If we're on a domain, we operate normally
script_name = ''
else:
# But if we're not, then our base URL
# will be something like
# https://blahblahblah.execute-api.us-east-1.amazonaws.com/dev
# So, we need to make sure the WSGI app knows this.
script_name = '/' + settings.API_STAGE
# Create the environment for WSGI and handle the request
environ = create_wsgi_request(
event,
script_name=script_name,
trailing_slash=trailing_slash
)
# We are always on https on Lambda, so tell our wsgi app that.
environ['HTTPS'] = 'on'
environ['wsgi.url_scheme'] = 'https'
environ['lambda.context'] = context
# Execute the application
response = Response.from_app(app, environ)
# This is the object we're going to return.
# Pack the WSGI response into our special dictionary.
zappa_returndict = dict(response.headers)
if 'Content' not in zappa_returndict and response.data:
zappa_returndict['Content'] = response.data
zappa_returndict['Status'] = response.status_code
# To ensure correct status codes, we need to
# pack the response as a deterministic B64 string and raise it
# as an error to match our APIGW regex.
# The DOCTYPE ensures that the page still renders in the browser.
exception = None
if response.status_code in ERROR_CODES:
content = collections.OrderedDict()
content['http_status'] = response.status_code
content['content'] = base64.b64encode(response.data.encode('utf-8'))
exception = json.dumps(content)
#.........这里部分代码省略.........
logger.error("Cannot find a function to process the triggered event.")
return result
# This is an API Gateway authorizer event
elif event.get('type') == u'TOKEN':
whole_function = self.settings.AUTHORIZER_FUNCTION
if whole_function:
app_function = self.import_module_and_get_function(whole_function)
policy = self.run_function(app_function, event, context)
return policy
else:
logger.error("Cannot find a function to process the authorization request.")
raise Exception('Unauthorized')
# Normal web app flow
try:
# Timing
time_start = datetime.datetime.now()
# This is a normal HTTP request
if event.get('httpMethod', None):
if settings.DOMAIN:
# If we're on a domain, we operate normally
script_name = ''
else:
# But if we're not, then our base URL
# will be something like
# https://blahblahblah.execute-api.us-east-1.amazonaws.com/dev
# So, we need to make sure the WSGI app knows this.
script_name = '/' + settings.API_STAGE
# Create the environment for WSGI and handle the request
environ = create_wsgi_request(
event,
script_name=script_name,
trailing_slash=self.trailing_slash,
binary_support=settings.BINARY_SUPPORT
)
# We are always on https on Lambda, so tell our wsgi app that.
environ['HTTPS'] = 'on'
environ['wsgi.url_scheme'] = 'https'
environ['lambda.context'] = context
# Execute the application
response = Response.from_app(self.wsgi_app, environ)
# This is the object we're going to return.
# Pack the WSGI response into our special dictionary.
zappa_returndict = dict()
if response.data:
if settings.BINARY_SUPPORT:
if not response.mimetype.startswith("text/") \
or response.mimetype != "application/json":
zappa_returndict['body'] = base64.b64encode(response.data)
zappa_returndict["isBase64Encoded"] = "true"
else:
zappa_returndict['body'] = response.data
else:
zappa_returndict['body'] = response.data
zappa_returndict['statusCode'] = response.status_code
zappa_returndict['headers'] = {}
for key, value in response.headers:
def lambda_handler(event, context):
"""
An AWS Lambda function which parses specific API Gateway input into a WSGI request,
feeds it to Django, procceses the Django response, and returns that
back to the API Gateway.
"""
# Django requires settings and an explicit call to setup()
# if being used from inside a python context.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "zappa_settings")
import django
django.setup()
from django.conf import settings
# This is a normal HTTP request
if event.get('method', None):
# If we just want to inspect this,
# return this event instead of processing the request
# https://your_api.aws-api.com/?event_echo=true
event_echo = getattr(settings, "EVENT_ECHO", True)
if event_echo:
if 'event_echo' in event['params'].values():
return {'Content': str(event) + '\n' + str(context), 'Status': 200}
# This doesn't matter, but Django's handler requires it.
def start(a, b):
return
# Create the environment for WSGI and handle the request
environ = create_wsgi_request(event, script_name=settings.SCRIPT_NAME)
handler = WSGIHandler()
response = handler(environ, start)
# Prepare the special dictionary which will be returned to the API GW.
returnme = {'Content': response.content}
# Pack the WSGI response into our special dictionary.
for item in response.items():
returnme[item[0]] = item[1]
returnme['Status'] = response.status_code
# Parse the WSGI Cookie and pack it.
cookie = response.cookies.output()
if ': ' in cookie:
returnme['Set-Cookie'] = response.cookies.output().split(': ')[1]
# To ensure correct status codes, we need to
# pack the response as a deterministic B64 string and raise it
# as an error to match our APIGW regex.
# The DOCTYPE ensures that the page still renders in the browser.
if response.status_code in [400, 401, 403, 500]:
content = response.content
content = "<!DOCTYPE html>" + str(response.status_code) + response.content
b64_content = base64.b64encode(content)
raise Exception(b64_content)
# Internal are changed to become relative redirects
# so they still work for apps on raw APIGW and on a domain.
elif response.status_code in [301, 302]:
location = returnme['Location']
location = '/' + location.replace("http://zappa/", "")
raise Exception(location)
else:
return returnme
# This is a management command invocation.
elif event.get('command', None):
from django.core import management
# Couldn't figure out how to get the value into stdout with StringIO..
# Read the log for now. :[]
management.call_command(*event['command'].split(' '))
return {}
def lambda_handler(event, context=None, settings_name="zappa_settings"): # NoQA
"""
An AWS Lambda function which parses specific API Gateway input into a WSGI request.
The request get fed it to Django, processes the Django response, and returns that
back to the API Gateway.
"""
time_start = datetime.datetime.now()
# If in DEBUG mode, log all raw incoming events.
if settings.DEBUG:
logger.info('Zappa Event: {}'.format(event))
# This is a normal HTTP request
if event.get('method', None):
# Create the environment for WSGI and handle the request
environ = create_wsgi_request(event, script_name=settings.SCRIPT_NAME)
# We are always on https on Lambda, so tell our wsgi app that.
environ['HTTPS'] = 'on'
environ['wsgi.url_scheme'] = 'https'
wrap_me = get_wsgi_application()
app = ZappaWSGIMiddleware(wrap_me)
# Execute the application
response = Response.from_app(app, environ)
response.content = response.data
# Prepare the special dictionary which will be returned to the API GW.
returnme = {'Content': response.data}
# Pack the WSGI response into our special dictionary.
for (header_name, header_value) in response.headers:
returnme[header_name] = header_value
returnme['Status'] = response.status_code
# To ensure correct status codes, we need to
# pack the response as a deterministic B64 string and raise it
# as an error to match our APIGW regex.
# The DOCTYPE ensures that the page still renders in the browser.
exception = None
if response.status_code in ERROR_CODES:
content = u"<!DOCTYPE html>" + unicode(response.status_code) + unicode('<meta charset="utf-8" />') + response.data.encode('utf-8')
b64_content = base64.b64encode(content)
exception = (b64_content)
# Internal are changed to become relative redirects
# so they still work for apps on raw APIGW and on a domain.
elif 300 <= response.status_code < 400 and response.has_header('Location'):
location = returnme['Location']
location = '/' + location.replace("http://zappa/", "")
exception = location
# Calculate the total response time,
# and log it in the Common Log format.
time_end = datetime.datetime.now()
delta = time_end - time_start
response_time_ms = delta.total_seconds() * 1000
common_log(environ, response, response_time=response_time_ms)
# Finally, return the response to API Gateway.
if exception:
raise Exception(exception)
else:
return returnme
# This is a management command invocation.
elif event.get('command', None):
from django.core import management
# Couldn't figure out how to get the value into stdout with StringIO..
# Read the log for now. :[]
management.call_command(*event['command'].split(' '))
return {}
elif event.get('detail'):
module, function = event['detail'].rsplit('.', 1)
app_module = importlib.import_module(module)
app_function = getattr(app_module, function)
# Execute the function!
app_function()
return
else:
logger.error('Unhandled event: {}'.format(json.dumps(event)))
def lambda_handler(event, context, settings_name="zappa_settings"):
"""
An AWS Lambda function which parses specific API Gateway input into a WSGI request,
feeds it to Django, procceses the Django response, and returns that
back to the API Gateway.
"""
time_start = datetime.datetime.now()
logging.basicConfig()
logger = logging.getLogger()
logger.setLevel(logging.INFO)
# Django requires settings and an explicit call to setup()
# if being used from inside a python context.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", settings_name)
import django
django.setup()
from django.conf import settings
# If in DEBUG mode, log all raw incoming events.
if settings.DEBUG:
logger.info('Zappa Event: {}'.format(event))
# This is a normal HTTP request
if event.get('method', None):
# If we just want to inspect this,
# return this event instead of processing the request
# https://your_api.aws-api.com/?event_echo=true
event_echo = getattr(settings, "EVENT_ECHO", True)
if event_echo:
if 'event_echo' in event['params'].values():
return {'Content': str(event) + '\n' + str(context), 'Status': 200}
# If Let's Encrypt is defined in the settings,
# and the path is your.domain.com/.well-known/acme-challenge/{{lets_encrypt_challenge_content}},
# return a 200 of lets_encrypt_challenge_content.
lets_encrypt_challenge_path = getattr(settings, "LETS_ENCRYPT_CHALLENGE_PATH", None)
lets_encrypt_challenge_content = getattr(settings, "LETS_ENCRYPT_CHALLENGE_CONTENT", None)
if lets_encrypt_challenge_path:
if len(event['params']) == 3:
if event['params']['parameter_1'] == '.well-known' and \
event['params']['parameter_2'] == 'acme-challenge' and \
event['params']['parameter_3'] == lets_encrypt_challenge_path:
return {'Content': lets_encrypt_challenge_content, 'Status': 200}
# This doesn't matter, but Django's handler requires it.
def start(a, b):
return
# Create the environment for WSGI and handle the request
environ = create_wsgi_request(event, script_name=settings.SCRIPT_NAME)
handler = WSGIHandler()
response = handler(environ, start)
# Prepare the special dictionary which will be returned to the API GW.
returnme = {'Content': response.content}
# Pack the WSGI response into our special dictionary.
for item in response.items():
returnme[item[0]] = item[1]
returnme['Status'] = response.status_code
# Parse the WSGI Cookie and pack it.
cookie = response.cookies.output()
if ': ' in cookie:
returnme['Set-Cookie'] = response.cookies.output().split(': ')[1]
# To ensure correct status codes, we need to
# pack the response as a deterministic B64 string and raise it
# as an error to match our APIGW regex.
# The DOCTYPE ensures that the page still renders in the browser.
exception = None
if response.status_code in [400, 401, 403, 500]:
content = response.content
content = "<!DOCTYPE html>" + str(response.status_code) + response.content
b64_content = base64.b64encode(content)
exception = (b64_content)
# Internal are changed to become relative redirects
# so they still work for apps on raw APIGW and on a domain.
elif response.status_code in [301, 302]:
location = returnme['Location']
location = '/' + location.replace("http://zappa/", "")
exception = location
# Calculate the total response time,
# and log it in the Common Log format.
time_end = datetime.datetime.now()
delta = time_end - time_start
response_time_ms = delta.total_seconds() * 1000
common_log(environ, response, response_time=response_time_ms)
# Finally, return the response to API Gateway.
if exception:
raise Exception(exception)
else:
return returnme
# This is a management command invocation.
#.........这里部分代码省略.........
def lambda_handler(event, context, settings_name="zappa_settings"):
""" An AWS Lambda function which parses specific API Gateway input into a
WSGI request, feeds it to Flask, procceses the Flask response, and returns
that back to the API Gateway.
"""
# Loading settings from a python module
settings = importlib.import_module(settings_name)
# The flask-app module
app_module = importlib.import_module(settings.APP_MODULE)
# The flask-app
app = getattr(app_module, settings.APP_OBJECT)
app.config.from_object('zappa_settings')
app.wsgi_app = ZappaWSGIMiddleware(app.wsgi_app)
# This is a normal HTTP request
if event.get('method', None):
# If we just want to inspect this,
# return this event instead of processing the request
# https://your_api.aws-api.com/?event_echo=true
event_echo = getattr(settings, "EVENT_ECHO", True)
if event_echo:
if 'event_echo' in list(event['params'].values()):
return {'Content': str(event) + '\n' + str(context), 'Status': 200}
# TODO: Enable Let's Encrypt
# # If Let's Encrypt is defined in the settings,
# # and the path is your.domain.com/.well-known/acme-challenge/{{lets_encrypt_challenge_content}},
# # return a 200 of lets_encrypt_challenge_content.
# lets_encrypt_challenge_path = getattr(settings, "LETS_ENCRYPT_CHALLENGE_PATH", None)
# lets_encrypt_challenge_content = getattr(settings, "LETS_ENCRYPT_CHALLENGE_CONTENT", None)
# if lets_encrypt_challenge_path:
# if len(event['params']) == 3:
# if event['params']['parameter_1'] == '.well-known' and \
# event['params']['parameter_2'] == 'acme-challenge' and \
# event['params']['parameter_3'] == lets_encrypt_challenge_path:
# return {'Content': lets_encrypt_challenge_content, 'Status': 200}
# Create the environment for WSGI and handle the request
environ = create_wsgi_request(event, script_name=settings.SCRIPT_NAME,
trailing_slash=False)
# We are always on https on Lambda, so tell our wsgi app that.
environ['wsgi.url_scheme'] = 'https'
response = Response.from_app(app, environ)
# This doesn't work. It should probably be set right after creation, not
# at such a late stage.
# response.autocorrect_location_header = False
zappa_returndict = dict()
if response.data:
zappa_returndict['Content'] = response.data
# Pack the WSGI response into our special dictionary.
for (header_name, header_value) in response.headers:
zappa_returndict[header_name] = header_value
zappa_returndict['Status'] = response.status_code
# TODO: No clue how to handle the flask-equivalent of this. Or is this
# something entirely specified by the middleware?
# # Parse the WSGI Cookie and pack it.
# cookie = response.cookies.output()
# if ': ' in cookie:
# zappa_returndict['Set-Cookie'] = response.cookies.output().split(': ')[1]
# To ensure correct status codes, we need to
# pack the response as a deterministic B64 string and raise it
# as an error to match our APIGW regex.
# The DOCTYPE ensures that the page still renders in the browser.
if response.status_code in [400, 401, 403, 404, 500]:
content = "<!DOCTYPE html>" + str(response.status_code) + response.data
b64_content = base64.b64encode(content)
raise Exception(b64_content)
# Internal are changed to become relative redirects
# so they still work for apps on raw APIGW and on a domain.
elif response.status_code in [301, 302]:
# Location is by default relative on Flask. Location is by default
# absolute on Werkzeug. We can set autocorrect_location_header on
# the response to False, but it doesn't work. We have to manually
# remove the host part.
location = response.location
hostname = 'https://' + environ['HTTP_HOST']
if location.startswith(hostname):
location = location[len(hostname):]
raise Exception(location)
else:
return zappa_returndict
请发表评论