encode/apistar

Name: apistar

Owner: Encode

Description: A smart Web API framework, designed for Python 3. ?

Created: 2017-03-17 15:42:12.0

Updated: 2018-01-18 14:55:20.0

Pushed: 2018-01-17 18:06:18.0

Homepage: https://discuss.apistar.org/

Size: 1854

Language: Python

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

API Star ????

A smart Web API framework, designed for Python 3.

Build Status codecov Package version Python versions

Community: https://discuss.apistar.org/ ? ? ? ? ?

screenshot


Features

Why should you consider using API Star for your next Web API project?


Table of Contents


Quickstart

Install API Star:

p3 install apistar

Create a new project:

istar new .
py
s.py
t app.py
 apistar import Include, Route
 apistar.frameworks.wsgi import WSGIApp as App
 apistar.handlers import docs_urls, static_urls


welcome(name=None):
if name is None:
    return {'message': 'Welcome to API Star!'}
return {'message': 'Welcome to API Star, %s!' % name}


es = [
Route('/', 'GET', welcome),
Include('/docs', docs_urls),
Include('/static', static_urls)


= App(routes=routes)


_name__ == '__main__':
app.main()

Run the application:

istar run
ing at http://localhost:8080/

Run the tests:

istar test
s.py ..
= 2 passed in 0.05 seconds =====

View the interactive API documentation:

en http://localhost:8080/docs/

screenshot

Choosing a framework

API Star allows you to either use a standard threaded WSGI application, or an asyncio application.

WSGI

The benefit of choosing a standard WSGI application is that you'll get better ecosystem support. The SQLAlchemy and Django ORM backends are available, and you can use a large range of existing Python libraries.

To start a new wsgi project use:

p install apistar
istar new .

The application import line in the code will look like this:

 apistar.frameworks.wsgi import WSGIApp as App
ASyncIO

The benefit of an asyncio application is the potential for higher throughput, as you can avoid making thread-blocking calls in favour of co-operative concurrency using async/await. However you'll need to make sure that you only use async components for any blocking operations, such as calls to the database, reading from disk, or making a network request.

To start a new asyncio project use:

p install apistar[asyncio]
istar new . --framework asyncio

The application import line in the code will look like this:

 apistar.frameworks.asyncio import ASyncIOApp as App

You may now include either regular or async handler functions…

welcome(name=None):
# A regular handler function that contains no asynchronous operations.
...

c def welcome(name=None):
# An async handler, that may use `async/await` syntax for performing asynchronous operations.
...

HTTP

Requests

API Star allows you to dynamically inject various information about the incoming request into your views using type annotation.

 apistar import http

show_request(request: http.Request):
return {
    'method': request.method,
    'url': request.url,
    'headers': dict(request.headers)
}

show_query_params(query_params: http.QueryParams):
return {
    'params': dict(query_params)
}

show_user_agent(user_agent: http.Header):
return {
    'user-agent': user_agent
}

Some of the components you might use most often:

| Component | Description | | —————— | ———– | | http.Request | The HTTP request. Includes .method, .url, and .headers attributes. | | http.Headers | The request headers, returned as a dictionary-like object. | | http.Header | Lookup a single request header, corresponding to the argument name.
Returns a string or None. | | http.QueryParams | The request query parameters, returned as a dictionary-like object. | | http.QueryParam | Lookup a single query parameter, corresponding to the argument name.
Returns a string or None. | | http.Body | The request body. Returns a bytestring. | | http.RequestData | The parsed request data. Data type will depend on the Content-Type of the request. |

Responses

By default API star expects view to return plain data, and will return 200 OK responses.

create_project():
return {'name': 'new project', 'id': 123}

You can instead set the status code or headers by returning a Response.

create_project():
data = {'name': 'new project', 'id': 123}
headers = {'Location': 'http://example.com/project/123/'}
return Response(data, status=201, headers=headers)
URL Routing

Use {curly_braces} in your URL conf to include a URL path parameter.

echo_username(username):
return {'message': f'Welcome, {username}!'}

= App(routes=[
Route('/{username}/', 'GET', echo_username)

Use Include to include a list of routes.

_routes = [
Route('/', 'GET', list_users),
Route('/', 'POST', create_user),
Route('/{user_id}', 'PUT', edit_user),
Route('/{user_id}', 'DELETE', delete_user)


es = [
Include('/users', user_routes),
...


= App(routes=routes)

Use type annotation on the view method to include typed URL path parameters.

s = {0: 'penny', 1: 'benny', 2: 'jenny'}

echo_username(user_id: int):
username = users[user_id]
return {'message': f'Welcome, {username}!'}

= App(routes=[
Route('/{user_id}/', 'GET', echo_username)

Parameters which do not correspond to a URL path parameter will be treated as query parameters for scalar types such as int or str, or part of the request body for composite types of dict and list.

echo_username(username):
if username is None:
    return {'message': 'Welcome!'}
return {'message': f'Welcome, {username}!'}

= App(routes=[
Route('/hello/', 'GET', echo_username)

Reversing URLS

Rather than build URLs by hand, it is possible to generate URLs based on the endpoint, using reverse_url().

 apistar import reverse_url

get_player_details(player_name):
score = get_score(player_name)
return {'name': player_name, 'score': score}

get_all_players():
players = get_players()
player_list = [
    {
        'name': player.name,
        'url': reverse_url('get_player_details', player_name=player.name)
    }
    for player in players
]
return {'players': player_list}

= App(routes=[
Route('/players/', 'GET', get_all_players),
Route('/players/{player_name}/', 'GET', get_player_details),

Command Routing

In addition to routing URLs, you can also route commands, to make additional functionality available directly to the command line client.

For example…

 apistar import Command
 apistar.frameworks.wsgi import WSGIApp as App



es = [
...


ands = [
Command('create_user', create_user),
Command('delete_user', delete_user)


= App(routes=routes, commands=commands)

Type System

API Star comes with a type system that allows you to express constraints on the expected inputs and outputs of your interface.

Here?s a quick example of what the type system in API Star looks like:

 apistar import typesystem

s Rating(typesystem.Integer):
minimum = 1
maximum = 5


s ProductSize(typesystem.Enum):
enum = ['small', 'medium', 'large']


s Product(typesystem.Object):
properties = {
    'name': typesystem.string(max_length=100),  # Use lowercase functions for inline declarations.
    'rating': Rating,
    'in_stock': typesystem.Boolean,
    'size': ProductSize,
}
Data Validation

The main benefit of expressing our data constraints in a type system is that we can then use those types as annotations on our handler functions.

create_product(product: Product):
...

es = [
Route('/create_product/', 'POST', create_product)

Serialization

In addition to using the typesystem types for input validation, you can also use them to serialize the return values of your handler functions.

rt typing


list_products() -> typing.List[Product]:
queryset = ...  # Query returning products from a data store.
return [Product(record) for record in queryset]
API Reference

The following typesystem types are currently supported:

String

Validates string data. A subclass of str.

Number

Validates numeric data. A subclass of float.

Integer

Validates integer data. A subclass of int.

Boolean

Validates boolean input. Returns either True or False.

Enum

Validates string input, against a list of valid choices. A subclass of str.

Object

Validates dictionary or object input. A subclass of dict.

Note that child properties are considered to be required if they do not have a default value.

Array

Validates list or tuple input. A subclass of list.

Generating API Schemas

API Star is designed to be able to map well onto API description formats, known as “API Schemas”.

There is currently provisional support for writing Swagger, RAML, or CoreJSON typesystems. See #69 for more details on work still to be done here.

The default output format is the built-in CoreJSON support:

istar schema
ype":"document", ...}

The OpenAPI (Swagger) and RAML codecs are optional, and require installation of additional packages:

Swagger
p install openapi-codec
istar schema --format openapi
agger": "2.0", "info": ...}
RAML
p install raml-codec
istar schema --format raml
ML 0.8


Building Websites

Although API Star is designed primarily with Web APIs in mind, it is a general purpose framework, and does also give you the tools you need to build regular websites.

Templates

API Star includes a templating component, that allows you to return templated responses, using Jinja2.

templates/index.html:

l>
<body>
    <h1>Hello, {{ username }}</h1>
</body>
ml>

app.py:

 apistar import Route, annotate, render_template
 apistar.frameworks.wsgi import WSGIApp as App
 apistar.renderers import HTMLRenderer

otate(renderers=[HTMLRenderer()])
hello(username: str):
return render_template('index.html', username=username)

es = [
Route('/', 'GET', hello)


ings = {
'TEMPLATES': {
    'ROOT_DIR': 'templates',     # Include the 'templates/' directory.
    'PACKAGE_DIRS': ['apistar']  # Include the built-in apistar templates.
}


= App(routes=routes, settings=settings)

Returning a string response from a view will default to using the text/json content type. This means you will need to override this so that your HTML views use the text/html content type in their responses. There are a couple of ways you can do this, including:

  1. by annotating your handler function so that it uses the HTMLRenderer (as shown above)
  2. by returning a Response, including an explicit Content-Type header (see Renderers section for an example)
Static Files

For serving static files, API Star uses whitenoise.

First make sure to install the whitenoise package.

p install whitenoise

Next, you'll then need to include the serve_static handler in your routes. This function expects to take a single URL argument, named path.

 apistar import Route
 apistar.handlers import serve_static

es = [
# ...
Route('/static/{path}', 'GET', serve_static)

Finally, include the directory that you'd like to serve static files from in your settings, like so:

ings = {
'STATICS': {
    'ROOT_DIR': 'statics',       # Include the 'statics/' directory.
    'PACKAGE_DIRS': ['apistar']  # Include the built-in apistar static files.
}


= App(routes=routes, settings=settings)
HTTP Sessions

API Star supports persistent HTTP sessions. You can access the session as a dictionary-like object. The session is made available by including the http.Session class as an annotation on a handler. For example:

 apistar import Response, http

login(username: str, password: str, session: http.Session):
if authenticate(username, password):
    session['username'] = username
    return Response(status=302, headers={'location': '/'})
else:
    ...

logout(session: http.Session):
if 'username' in session:
    del session['username']
return Response(status=302, headers={'location': '/'})

homepage(session: http.Session):
username = session.get('username')
...

The default implementation stores the session information in local memory, which isn't suitable for anything other than development and testing. For production you'll need to implement a session store that integrates with some kind of persistent storage.

 apistar import Component
 apistar.interfaces import SessionStore
 myproject import RedisSessionStore  # A SessionStore implementation.

es = [
...


onents = [
Component(SessionStore, init=RedisSessionStore)


= App(routes=routes, components=components)

Renderers & Parsers

Renderers and parsers are responsible for handling the translation of incoming or outgoing bytestreams.

For example, when returning a response we'll often simply return a native Python datastructure such as a dict or list. A renderer class is then responsible for generating the bytes that should be used for the response body.

Renderers

API Star defaults to returning JSON responses. You can alter this behaviour by configuring the renderers that should be supported.

Configuring the installed renderers

We can install one or more renderers by adding them to our settings. The RENDERERS setting should be a list. For example if most of our handlers return HTML responses, we might use the following:

ings = {
'RENDERERS': [HTMLRenderer()]

Alternatively we can specify the renderers to use on a specific handler function.

 apistar import annotate
 apistar.renderers import JSONRenderer
 myproject.renderers import CSVRenderer

otate(renderers=[JSONRenderer(), CSVRenderer()])
download_current_dataset():
# Return some data, formatted either as JSON or CSV,
# depending on the request Accept header.
...
How a renderer is determined

API Star uses HTTP content negotiation to determine which renderer should be returned. The Accept header is inspected, and one of the available installed renderers is selected. If the Accept header doesn't match any of the installed renderers then a 406 Not Acceptable response will be returned.

You can disable the content negotiation by including an explicit content_type argument when returning a Response. For example…

content = template.render(...)
return http.Response(content, content_type='text/html')
Parsers

Parsers are responsible for taking the incoming request body, and returning the data structure it represents, given the Content-Type of the request.

By default API Star supports parsing JSON or form encoded requests.

Configuring the installed parsers

We can install one or more parsers by adding them to our settings. The PARSERS setting should be a list. For example if we want to disable form parsing, and only support JSON requests, we can do the following:

ings = {
'PARSERS': [JSONParser()]

Alternatively we can specify the parsers to use on a specific handler function.

 apistar import annotate
 apistar.parsers import MultiPartParser

otate(parsers=[MultiPartParser()])
file_upload():
# Handles a file upload, using a multipart encoded request.
...

Authentication & Permissions

Authentication is the mechanism of associating an incoming request with a set of identifying credentials, such as the user the request came from, or the token that it was signed with. Permissions are the processes of using those credentials to determine if the request should be permitted.

Authentication

The Auth component provides information about the currently authenticated user.

 apistar.interfaces import Auth

display_user(auth: Auth):
return {
    'is_authenticated': auth.is_authenticated(),
    'user': auth.get_display_name()
}

It provides the following interface:

In our example above we haven't yet configured any authentication policy, so our auth argument will always be set to an instance of Unauthenticated.

Requests to our endpoint will currently return a response like this:


"is_authenticated": false,
"user": null

Creating an authentication class

In order to authenticate our incoming requests we need to create an authentication class.

An authentication class must implement the authenticate method, and should return a subclass of Auth, or None if the request was not authenticated.

The authenticate method can accept any installed components in its signature.

rt base64
 apistar import http
 apistar.authentication import Authenticated

s BasicAuthentication():
def authenticate(self, authorization: http.Header):
    """
    Determine the user associated with a request, using HTTP Basic Authentication.
    """
    if authorization is None:
        return None

    scheme, token = authorization.split()
    if scheme.lower() != 'basic':
        return None

    username, password = base64.b64decode(token).decode('utf-8').split(':')
    return Authenticated(username)

Note that the Authenticated class provides a shortcut which you can use instead of implementing a subclass of Auth.

Configuring the authentication policy

We can install one or more authentication policies by adding them to our settings. The AUTHENTICATION setting should be a list. Each authentication policy will be attempted in turn.

ings = {
'AUTHENTICATION': [BasicAuthentication()]

Alternatively we can specify authentication policies on a specific handler function.

 apistar import annotate
 apistar.interfaces import Auth
 myproject.authentication import BasicAuthentication

otate(authentication=[BasicAuthentication()])
display_user(auth: Auth):
# There are no required permissions set on this handler, so all requests
# will be allowed.
# Requests that have successfully authenticated using basic authentication
# will include user credentials in `auth`.
...
Permissions

Typically you'll want to either permit or deny an incoming request, based on the authentication credentials provided.

API Star provides a single built-in IsAuthenticated permission class, or you can implement your own for more complex cases.

Creating a permissions class

A permissions class should implement a has_permission() method, and return either True or False depending on if the request should be permitted or not.

For example, if our user model includes an is_admin field, we might want to allow certain operations only for those users.

s IsAdminUser():
def has_permission(self, auth: Auth):
    if not auth.is_authenticated():
        return False
    return auth.user.is_admin
Configuring the permissions policy

Configuring permissions is very similar to configuring authentication, you can do so globally, using the settings…

ings = {
'AUTHENTICATION': [BasicAuthentication()],
'PERMISSIONS': [IsAuthenticted()]

Or configure permissions on a specific handler…

otate(
authentication=[BasicAuthentication()],
permissions=[IsAuthenticated()]

display_user(auth: Auth):
# Only authenticated requests will be allowed to access this handler.
...

Settings & Environment

Application settings

Application settings are configured at the point of instantiating the app.

es = [
# ...


ings = {
'TEMPLATES': {
    'ROOT_DIR': 'templates',
    'PACKAGE_DIRS': ['apistar']
}


= App(routes=routes, settings=settings)

You can include the application settings in a view, by using the Settings type annotation:

 apistar import Settings


debug_settings(settings: Settings):
"""
Return a JSON response containing the application settings dictionary.
"""
return settings

More typically you'll want to include settings into the build method of custom components, so that you can control their initialization, based on the application settings.

Environment

Typically you'll want to follow the “twelve-factor app” pattern and store configuration variables in the environment, rather than keeping them under source control.

API Star provides an Environment class that allows you to load the environment, and ensure that it is correctly configured.

 apistar import environment, typesystem


s Env(environment.Environment):
properties = {
    'DEBUG': typesystem.boolean(default=False),
    'DATABASE_URL': typesystem.string(default='sqlite://')
}

= Env()

Once you have an Environment instance, you can use it when creating the application settings.

ings = {
'DATABASE': {
    'URL': env['DATABASE_URL']
}


Testing

API Star includes the py.test testing framework. You can run all tests in a tests.py module or a tests/ directory, by using the following command:

istar test

The simplest way to test a view is to call it directly.

 app import hello_world

test_hello_world():
assert hello_world() == {"hello": "world"}

There is also a test client, that allows you to make HTTP requests directly to your application, using the requests library.

 app import app
 apistar import TestClient

test_hello_world():
client = TestClient(app)
response = client.get('/hello_world/')
assert response.status_code == 200
assert response.json() == {"hello": "world"}

Requests made using the test client may use either relative URLs, or absolute URLs. In either case, all requests will be directed at your application, rather than making external requests.

onse = client.get('http://www.example.com/hello_world/')

Backends

SQLAlchemy

API Star has optional support for SQLAlchemy. To use this you first need to install sqlalchemy and your chosen database driver.

p install sqlalchemy
p install psycopg2

Settings

You then need to add the database config to your settings, and install the additional components and commands for SQLAlchemy:

 sqlalchemy.ext.declarative import declarative_base
 sqlalchemy import Column, Integer, String
 apistar.frameworks.wsgi import WSGIApp as App
 apistar.backends import sqlalchemy_backend

 = declarative_base()

s Customer(Base):
__tablename__ = "Customer"
id = Column(Integer, primary_key=True)
name = Column(String)

es = [
# ...


nfigure database settings.
ings = {
"DATABASE": {
    "URL": "postgresql://:@localhost/apistar",
    "METADATA": Base.metadata
}


= App(
routes=routes,
settings=settings,
commands=sqlalchemy_backend.commands,  # Install custom commands.
components=sqlalchemy_backend.components  # Install custom components.

A few common driver configurations are listed below.

Database | Driver | URL format ———- | ————————— | —————- PostgreSQL | psycopg2 | postgresql://<username>:<password>@localhost/example MySQL | pymysql | mysql+pymysql://<username>:<password>@localhost/example SQLite | sqlite3 (Python built-in) | sqlite:///example.db

Creating the database tables

Before starting you app you will likely need to create the database tables declared in your MetaData which you can do with the following command:

istar create_tables

Migrations If you wish to use alembic migrations with sql alchemy you can use the following package

https://github.com/colanconnon/apistar_alembic_migrations

Interacting with the database

To interact with the database, use the Session component. This will automatically handle commit/rollback behavior, depending on if the view returns normally, or raises an exception:

 apistar.backends.sqlalchemy_backend import Session

create_customer(session: Session, name: str):
customer = Customer(name=name)
session.add(customer)
session.flush()  # Flush the changes to the database. This will populate the customer id.
return {'id': customer.id, 'name': customer.name}

list_customers(session: Session):
queryset = session.query(Customer).all()
return [
    {'id': customer.id, 'name': customer.name}
    for customer in queryset
]

To instead access the basic database configuration information in a handler, use the SQLAlchemy component.

This has the following attributes:

Django ORM

API Star has optional support for Django ORM. To use this you first need to install django and your chosen database driver.

p install django
p install psycopg2

Settings

You then need to add the database config to your settings and the django migration commands:

 apistar.frameworks.wsgi import WSGIApp as App
 apistar.backends import django_orm


es = [
 ...


nfigure database settings.
ings = {
'DATABASES': {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': '...',
        'HOST': 'localhost',
        'USER': '...',
        'PASSWORD': ''
    }
},
'INSTALLED_APPS': ['project',]



= App(
routes=routes,
settings=settings,
commands=django_orm.commands,  # Install custom commands.
components=django_orm.components  # Install custom components.

Migrations

You also need to manually create the migrations directory inside the project directory.

Before starting you app you will likely need to make migrations and then migrate which you can do with the following commands:

istar makemigrations
istar migrate

Create a new model

To create a new Django model you will want to create a new models.py file and declare it.

 django.db import models

s Customer(models.Model):
name = models.CharField(max_length=255)

Accessing the database

To interact with the database, use the Session component. This will automatically handle commit/rollback behavior, depending on if the view returns normally, or raises an exception:

 apistar.backends.django_orm import Session

create_customer(session: Session, name: str):
customer = session.Customer(name=name)
customer.save()
return {'id': customer.id, 'name': customer.name}

list_customers(session: Session):
queryset = session.Customer.objects.all()
return [
    {'id': customer.id, 'name': customer.name}
    for customer in queryset
]

Components

You can create new components to inject into your views. For example:

rt base64

s User(object):
"""
A component representing the user that the incoming request is associated with.
"""
def __init__(self, username):
    self.username = username


authenticate_user(authorization: http.Header):
"""
Determine the user associated with a request, using HTTP Basic Authentication.
"""
if authorization is None:
    return None
scheme, token = authorization.split()
if scheme.lower() != 'basic':
    return None
username, password = base64.b64decode(token).decode('utf-8').split(':')
return User(username)

Next, register your component with the application:

 apistar import Component

onents = [
Component(User, init=authenticate_user)


= App(
routes=routes,
components=components

You can then use your component in a view:

say_hello(user: User):
return {'hello': user.username}
Component Reference

A complete listing of the available built-in components:

Component | Description ——————————-|————- http.Method | The HTTP method of the request, such as GET. http.Host | The host component of the request URL, such as 'example.com'. http.Port | The port number that the request is made to, such as 443. http.Scheme | The scheme component of the request URL, such as 'https'. http.Path | The path component of the request URL, such as /api/v1/my_view/. http.QueryString | The query component of the request URL, such as page=2. http.URL | The full URL of the request, such as https://example.com/api/v1/my_view/?page=2. http.Body | The body of the request, as a bytestring. http.QueryParams | A multi-dict containing the request query parameters. http.QueryParam | A single request query parameter, corresponding to the keyword argument name. Automatically used for data arguments. http.Headers | A multi-dict containing the request headers parameters. http.Header | A single request query parameter, corresponding to the keyword argument name. http.Request | The full request instance. interfaces.App | The current application. interfaces.Console | The console interface. Supports the .echo(message) interface. interfaces.CommandLineClient | The command line parsing component. Supports the .parse(args) interface. interfaces.Injector | Makes the dependency injection available to handler. Supports the .run(func) interface. interfaces.Router | The router for the application instance. Supports the reverse_url(name, **values) interface. interfaces.Schema | The CoreAPI schema used to represent the API. interfaces.StaticFiles | The static files component. Supports the get_url(path) interface. interfaces.Templates | The template environment. Supports the get_template(path) interface. types.KeywordArgs | A dictionary containing all the matched URL path arguments, or parsed command line parameters. types.ParamName | A string representing the keyword argument with which a component is being injected into the view. May be for components that vary depending on the parameter name used. types.PathWildcard | A string. May be used for URL path components that should support full wildcard matches, allowing '/' characters. types.Settings | A dictionary containing the application settings. types.WSGIEnviron | A dictionary containing the raw WSGI environ of the incoming request.


Performance

API Star dynamically determines exactly what does and does not need to run for any given view, based on the annotations it includes. This means that it can be incredibly efficient.

For a simple JSON serialization test case, the TechEmpower benchmarks rank API Star as achieving the highest throughput of any Python, JavaScript, Ruby, or Go framework.

Benchmarks

We'll be working towards adding further test case types to the TechEmpower benchmarks in the coming weeks, and including results from both WSGIApp and ASyncIOApp deployment modes.

Its also important to recognize that raw latency or throughput numbers are typically not the most important factor to take into consideration when choosing a framework. Having said that, one aim for API Star is to hit the sweet spot for both performance and for productivity.


Deployment

The Development Server

A development server is available, using the run command:

istar run
ecify the port or interface via --port and --host
rve on port 9001 and use IPv6 only
istar run --port 9001 --host ::1
 you don't like the Werkzeug web debugger, turn it off
istar run --no-debugger
Running in Production
Running a WSGIApp project

For WSGI applications, the recommended production deployment is Gunicorn, using the Meinheld worker.

p install gunicorn
p install meinheld
nicorn app:app --workers=4 --bind=0.0.0.0:5000 --pid=pid --worker-class=meinheld.gmeinheld.MeinheldWorker

Typically you'll want to run as many workers as you have CPU cores on the server.

Running an ASyncIOApp project

For asyncio applications, use uvicorn.

icorn app:app --workers=4 --bind=0.0.0.0:5000 --pid=pid

Again, you'll typically want to run as many workers as you have CPU cores on the server.

“Serverless” deployments

API Star can also be deployed on so called “serverless” platforms. A good option for using API Star with this style of deployment is Zappa, which allows you to deploy any Python WSGI server onto AWS Lambda.

Note that only WSGIApp is supported using Zappa. You cannot run an ASyncIOApp under this deployment, as a standard WSGI interface is expected.

For Zappa to execute it needs to be provided with the path to your app instance in its app_function key. Given that your app is contained within app.py, e.g.

p.py
= App(routes=routes, settings=settings)

Your zappa_settings.json configuration file should then look something like this:


"dev": {
    "app_function": "app.app",
    "aws_region": "us-east-1",
    "profile_name": "default",
    "s3_bucket": "<a-unique-s3-bucket-name>",
    "keep_warm": false
},
"prod": {
    "app_function": "app.app",
    "aws_region": "us-east-1",
    "profile_name": "default",
    "s3_bucket": "<a-unique-s3-bucket-name>",
    "debug": false,
    "log_level": "WARNING",
    "apigateway_description": "Description of your app on AWS API Gateway",
    "lambda_description": "Description of your app on AWS Lambda",
}

See Zappa's installation instructions for full configuration details.

Notes
ault]
access_key_id = 'xxx'
secret_access_key = 'xxx'

To successfully run zappa deploy you will need an IAM user on your AWS account with the a sufficiently permissive policy attached. See the discussions on Zappa's minimum policy requirements for more details.


Changelog

0.3 Release

Note: Because we now support configurable renderers, there's a difference in the behaviour of returning plain data, or a Response without a content_type set. Previously we would return HTML for strings/bytes, and JSON for anything else. Now, JSON is the default for everything, unless alternative renderers are specified. See the “Renderers & Parsers” and “Requests & Responses” section for more detail.

0.2 Release

Development

To work on the API Star codebase, you'll want to clone the repository, and create a Python virtualenv with the project requirements installed:

t clone git@github.com:tomchristie/apistar.git
 apistar
scripts/setup

To run the continuous integration tests and code linting:

scripts/test
scripts/lint

API Star is BSD licensed code.
Designed & built in Brighton, England.

— ?? —


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.