Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Serverless plugin to deploy WSGI applications (Flask/Django/Pyramid etc.) and bundle Python packages

License

NotificationsYou must be signed in to change notification settings

logandk/serverless-wsgi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

npm package

serverlessTestsCoverage Status

A Serverless Framework plugin to build your deploy Python WSGI applications using Serverless. CompatibleWSGI application frameworks include Flask, Django and Pyramid - for a complete list, see:http://wsgi.readthedocs.io/en/latest/frameworks.html.

Features

  • Transparently converts API Gateway and ALB requests to and from standard WSGI requests
  • Supports anything you'd expect from WSGI such as redirects, cookies, file uploads etc.
  • Automatically downloads Python packages that you specify inrequirements.txt and deploys them along with your application
  • Convenientwsgi serve command for serving your application locally during development
  • Includes CLI commands for remote execution of Python code (wsgi exec), shell commands (wsgi command), Flask CLI commands (wsgi flask) and Django management commands (wsgi manage)
  • Supports both APIGatewayV1 and APIGatewayV2 payloads

Install

sls plugin install -n serverless-wsgi

This will automatically add the plugin topackage.json and the plugins section ofserverless.yml.

Flask configuration example

This example assumes that you have intialized your application asapp insideapi.py.

project├── api.py├── requirements.txt└── serverless.yml

api.py

A regular Flask application.

fromflaskimportFlaskapp=Flask(__name__)@app.route("/cats")defcats():return"Cats"@app.route("/dogs/<id>")defdog(id):return"Dog"

serverless.yml

Load the plugin and set thecustom.wsgi.app configuration inserverless.yml to themodule path of your Flask application.

All functions that will use WSGI need to havewsgi_handler.handler set as the Lambda handler anduse the defaultlambda-proxy integration for API Gateway. This configuration example treatsAPI Gateway as a transparent proxy, passing all requests directly to your Flask application,and letting the application handle errors, 404s etc.

Note: The WSGI handler was calledwsgi.handler earlier, but was renamed towsgi_handler.handlerin1.7.0. The old name is still supported but using it will cause a deprecation warning.

service:exampleprovider:name:awsruntime:python3.6plugins:  -serverless-wsgifunctions:api:handler:wsgi_handler.handlerevents:      -http:ANY /      -http:ANY /{proxy+}custom:wsgi:app:api.app

requirements.txt

Add Flask to the application bundle.

Flask==1.0.2

Deployment

Simply run the serverless deploy command as usual:

$ sls deployServerless: Using Python specified in "runtime": python3.6Serverless: Packaging Python WSGI handler...Serverless: Packaging required Python packages...Serverless: Linking required Python packages...Serverless: Packaging service...Serverless: Excluding development dependencies...Serverless: Unlinking required Python packages...Serverless: Uploading CloudFormation file to S3...Serverless: Uploading artifacts...Serverless: Uploading service .zip file to S3 (864.57 KB)...Serverless: Validating template...Serverless: Updating Stack...Serverless: Checking Stack update progress.................Serverless: Stack update finished...

Other frameworks

Setcustom.wsgi.app inserverless.yml according to your WSGI callable:

Usage

Automatic requirement packaging

You'll need to include any packages that your application uses in the bundlethat's deployed to AWS Lambda. This plugin helps you out by doing this automatically,as long as you specify your required packages in arequirements.txt file in the rootof your Serverless service path:

Flask==1.0.2requests==2.21.0

For more information, seehttps://pip.pypa.io/en/latest/user_guide/#requirements-files.

Theserverless-wsgi plugin itself depends onwerkzeug and will package it automatically,even ifwerkzeug is not present in yourrequirements.txt.

You can use the requirement packaging functionality ofserverless-wsgi without the WSGIhandler itself by including the plugin in yourserverless.yml configuration, without specifyingthecustom.wsgi.app setting. This will omit the WSGI handler from the package, but includeany requirements specified inrequirements.txt.

If you don't want to use automatic requirement packaging you can setcustom.wsgi.packRequirements to false:

custom:wsgi:app:api.apppackRequirements:false

In order to pass additional arguments topip when installing requirements, thepipArgs configurationoption is available:

custom:wsgi:app:api.apppipArgs:--no-deps

For a more advanced approach to packaging requirements, consider usinghttps://github.com/UnitedIncome/serverless-python-requirements.When theserverless-python-requirements is added toserverless.yml, thepackRequirements optionis set tofalse by default.

If you havepackRequirements set tofalse, or if you useserverless-python-requirements, remember to addwerkzeug explicitly in yourrequirements.txt.

Python version

Python is used for packaging requirements and serving the app when invokingsls wsgi serve. Bydefault, the current runtime setting is expected to be the name of the Python binary inPATH,for instancepython3.6. If this is not the name of your Python binary, override it using thepythonBin option:

custom:wsgi:app:api.apppythonBin:python3

Local server

For convenience, asls wsgi serve command is provided to run your WSGI applicationlocally. This command requires thewerkzeug Python package to be installed,and acts as a simple wrapper for starting werkzeug's built-in HTTP server.

By default, the server will start on port 5000.(Note: macOSreserves port 5000for AirPlay by default, see below for instructions on changing the port.)

$ sls wsgi serve * Running on http://localhost:5000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active!

Configure the port using the-p parameter:

$ sls wsgi serve -p 8000 * Running on http://localhost:8000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active!

When running locally, an environment variable namedIS_OFFLINE will be set toTrue.So, if you want to know when the application is running locally, checkos.environ["IS_OFFLINE"].

Remote command execution

Thewsgi exec command lets you execute Python code remotely:

$ sls wsgi exec -c "import math; print((1 + math.sqrt(5)) / 2)"1.618033988749895$ cat count.pyfor i in range(3):    print(i)$ sls wsgi exec -f count.py012

Thewsgi command command lets you execute shell commands remotely:

$ sls wsgi command -c "pwd"/var/task$ cat script.sh#!/bin/bashecho "dlrow olleh" | rev$ sls wsgi command -f script.shhello world

Thewsgi flask command lets you executeFlask CLI custom commands remotely:

$ sls wsgi flask -c "my command"Hello world!

Thewsgi manage command lets you execute Django management commands remotely:

$ sls wsgi manage -c "check --list-tags"admincachesdatabasemodelsstaticfilestemplatesurls

All commands havelocal equivalents that let you run commands throughsls invoke local ratherthansls invoke, i.e. on the local machine instead of through Lambda. Thelocal commands (sls wsgi command local,sls wsgi exec local,sls wsgi flask local andsls wsgi manage local) take the same argumentsas their remote counterparts documented above.

Explicit routes

If you'd like to be explicit about which routes and HTTP methods should pass through to yourapplication, see the following example:

service:exampleprovider:name:awsruntime:python3.6plugins:  -serverless-wsgifunctions:api:handler:wsgi_handler.handlerevents:      -http:path:catsmethod:getintegration:lambda-proxy      -http:path:dogs/{id}method:getintegration:lambda-proxycustom:wsgi:app:api.app

Custom domain names

If you use custom domain names with API Gateway, you might have a base path that isat the beginning of your path, such as the stage (/dev,/stage,/prod). In this case, settheAPI_GATEWAY_BASE_PATH environment variable to letserverless-wsgi know.E.g, if you deploy your WSGI application tohttps://mydomain.com/api/myservice,setAPI_GATEWAY_BASE_PATH toapi/myservice (no/ first).

The example below uses theserverless-domain-managerplugin to handle custom domains in API Gateway:

service:exampleprovider:name:awsruntime:python3.6environment:API_GATEWAY_BASE_PATH:${self:custom.customDomain.basePath}plugins:  -serverless-wsgi  -serverless-domain-managerfunctions:api:handler:wsgi_handler.handlerevents:      -http:ANY /      -http:ANY {proxy+}custom:wsgi:app:api.appcustomDomain:basePath:${opt:stage}domainName:mydomain.name.comstage:${opt:stage}createRoute53Record:true

Note: TheAPI_GATEWAY_BASE_PATH configuration is only needed when using the payload V1. In the V2, the path does not have thebasePath in the beginning.

Using CloudFront

If you're configuring CloudFront manually in front of your API and settingthe Path in the CloudFront Origin to include your stage name, you'll needto strip it out from the path supplied to WSGI. This is so that your appdoesn't generate URLs starting with/production.

Pass theSTRIP_STAGE_PATH=yes environment variable to your applicationto set this:

service:exampleprovider:name:awsruntime:python3.6environment:STRIP_STAGE_PATH:yes

File uploads

In order to accept file uploads from HTML forms, make sure to addmultipart/form-data tothe list of content types withBinary Support in your API Gateway API. Theserverless-apigw-binaryServerless plugin can be used to automate this process.

Keep in mind that, when building Serverless applications, uploadingdirectly to S3from the browser is usually the preferred approach.

Raw context and event

The raw context and event from AWS Lambda are both accessible through the WSGIrequest. The following example shows how to access them when using Flask:

fromflaskimportFlask,requestapp=Flask(__name__)@app.route("/")defindex():print(request.environ['serverless.context'])print(request.environ['serverless.event'])

For more information on these objects, read the documentation oneventsand theinvocation context.

Text MIME types

By default, all MIME types starting withtext/ and the following whitelist are sentthrough API Gateway in plain text. All other MIME types will have their response bodybase64 encoded (and theisBase64Encoded API Gateway flag set) in order to bedelivered by API Gateway as binary data (remember to add any binary MIME types thatyou're using to theBinary Support list in API Gateway).

This is the default whitelist of plain text MIME types:

  • application/json
  • application/javascript
  • application/xml
  • application/vnd.api+json
  • image/svg+xml

In order to add additional plain text MIME types to this whitelist, use thetextMimeTypes configuration option:

custom:wsgi:app:api.apptextMimeTypes:      -application/custom+json      -application/vnd.company+json

Preventing cold starts

Common ways to keep lambda functions warm includescheduled eventsand theWarmUP plugin. Both these event sourcesare supported by default and will be ignored byserverless-wsgi.

Alternative directory structure

If you have several functions inserverless.yml and want to organize them indirectories, e.g.:

project├── web│   ├── api.py│   └── requirements.txt├── serverless.yml└── another_function.py

In this case, tellserverless-wsgi where to find the handler by prepending thedirectory:

service:exampleprovider:name:awsruntime:python3.6plugins:  -serverless-wsgifunctions:api:handler:wsgi_handler.handlerevents:      -http:ANY /      -http:ANY {proxy+}another_function:handler:another_function.handlercustom:wsgi:app:web/api.app

Requirements will now be installed intoweb/, rather than at in the service root directory.

The same rule applies when using theindividually: true flag in thepackage settings, togetherwith themodule option provided byserverless-python-requirements. In that case, both the requirementsand the WSGI handler will be installed intoweb/, if the function is configured withmodule: "web".

Usage without Serverless

The AWS API Gateway to WSGI mapping module is available on PyPI in theserverless-wsgi package.

Use this package if you need to deploy Python Lambda functions to handleAPI Gateway events directly, without using the Serverless framework.

pip install serverless-wsgi

Initialize your WSGI application and in your Lambda event handler, callthe request mapper:

importapp# Replace with your actual applicationimportserverless_wsgi# If you need to send additional content types as text, add then directly# to the whitelist:## serverless_wsgi.TEXT_MIME_TYPES.append("application/custom+json")defhandler(event,context):returnserverless_wsgi.handle_request(app.app,event,context)

Thanks

Thanks toZappa, which has been both theinspiration and source of several implementations that went into this project.

Thanks tochalice for therequirement packaging implementation.

About

Serverless plugin to deploy WSGI applications (Flask/Django/Pyramid etc.) and bundle Python packages

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors35

Languages


[8]ページ先頭

©2009-2025 Movatter.jp