CORS implementation for Python
Python Shell
Latest commit 9eb64ae May 13, 2015 @monsur Merge pull request #3 from optimizely/master
Turn cors-python into PyPi distributable python package.

README.md

cors-python

A server-side CORS implementation for Python. This library is an early alpha release. Testing and feedback welcome!

Details

CORS can easily be enabled by setting the Access-Control-Allow-Origin: * response header. And for many resources that is sufficient. But if your API goes beyond simple requests, there are many edge cases that can make CORS difficult to work with.

This library aims to make CORS easy: give it your request info, and it spits out the CORS response headers. All the details of handling preflights are managed for you. Its features include:

  • Configure all aspects of CORS. Make your API as open as you like.
  • Custom validators give you control over exactly which origins, methods and headers are allowed.
  • Ease-of-use. Sits on top of your application with ~ 2 lines of code (see example below).
  • Errors can either fire immediately or pass through to your app.
  • Supports the "Vary" header, which is sometimes needed to avoid caching by proxy servers.
  • Can be adapted to work with most apps.

Installation

Nothing fancy for now, just copy the cors/ directory over.

Usage

See the app engine app under the "examples" directory for a sample usage.

For WSGI-compatible apps, you can wrap you application with the cors_application.py middleware:

webapp = webapp2.WSGIApplication([('/', MainHandler)])
corsapp = CorsApplication(webapp, CorsOptions())

The CorsOptions class accepts the following properties:

allow_origins (Validator) - The origins that are allowed. Set to True to allow all origins, or to a list of valid origins. Defaults to True, which allows all origins, and appends the Access-Control-Allow-Origin: * response header.

allow_credentials (bool) - Whether or not the app supports credentials. If True, appends the Access-Control-Allow-Credentials: true header. Defaults to False.

allow_methods (Validator) - The HTTP methods that are allowed. Set to True to allow all methods, or to a list of allowed methods. Defauts to ['HEAD', 'GET', 'PUT', 'POST', 'DELETE'], which appends the Access-Control-Allow-Methods: HEAD, GET, PUT, POST, DELETE response header.

allow_headers (Validator) - The HTTP request headers that are allowed. Set to True to allow all headers, or to a list of allowed headers. Defaults to True, which appends the Access-Control-Allow-Headers response header.

expose_headers (list of strings) - List of response headers to expose to the client. Defaults to None. Appends the Access-Control-Expose-Headers response header.

max_age (int) - The maximum time (in seconds) to cache the preflight response. Defaults to None, which doesn't append any response headers. Appends the Access-Control-Max-Age header when set.

vary (bool) - Set to True if the Vary: Origin header should be appended to the response, False otherwise. The Vary header is useful when used in conjunction with a list of valid origins, and tells downstream proxy servers not to cache the response based on Origin. The default value is False for '*' origins, True otherwise.

allow_non_cors_requests (bool) - Whether non-CORS requests should be allowed. Defaults to True.

continue_on_error (bool) - Whether an invalid CORS request should trigger an error, or continue processing. Defaults to False.

Validators

A few options above are marked as the special type "Validator". This type is used to validate the origin, http method, and header values. The actual type of the property can be set to various values, depending on the need:

  • Boolean: A value of True indicates that all values are allowed. A value of False indicates that no value is allowed.

  • List of strings: The list of valid values. For example, the default list of HTTP methods is ['HEAD', 'GET', 'PUT', 'POST', 'DELETE'].

  • Regex (coming soon) - A regular expression to validate the value. Could be useful for validating a set of subdomains (i.e. http://..foo.com) or custom headers (i.e. x-prefix-.)

  • Function (coming soon) - Allows you to write your own function to validate the input.

Integrating with your own app

If the WSGI middleware does not meet your needs, you can always integrate with the CORS library by writing your own handler. Your handler should call the CorsHandler class in order to do the heavy lifting. See cors_application.py for an example of how to integrate with this library.