Skip to main content
This is a pre-production deployment of Warehouse. Changes made here affect the production instance of PyPI (
Help us improve Python packaging - Donate today!

WSGI for Cross Origin Resource Sharing (CORS)

Project Description


This is a WSGI middleware that answers CORS preflight requests and adds
the needed header to the response. For CORS see:


Either plug it in programmatically as in this pyramid example:

.. code:: python

def app(global_config, **settings):
""" This function returns a WSGI application.

It is usually called by the PasteDeploy framework during
``paster serve``.

def get_root(request):
return {}

config = Configurator(root_factory=get_root, settings=settings)
# whatever it takes to config your app goes here

from wsgicors import CORS
return CORS(config.make_wsgi_app(), headers="*", methods="*", maxage="180", origin="*")

or plug it into your wsgi pipeline via paste ini to let it serve by
waitress for instance:


use = egg:mysuperapp#app

# wsgi server configuration

use = egg:waitress#main
host =
port = 6543

pipeline =

use = egg:wsgicors#middleware
# define a "free" policy
free_methods=HEAD, OPTIONS, GET

# define a "subdom" policy
subdom_origin= https://*
subdom_expose_headers=Foo, Doom

# define a combination of policies, they are evaluated in the order given by the policy keyword
# the first that matches the request's origin will be used
# policy matching strategy
# matchstrategy=firstmatch

Keywords are:

- ``origin``
- ``headers``
- ``methods``
- ``credentials``
- ``maxage``

for ``origin``:

- use ``copy`` which will copy whatever origin the request comes from
- a space separated list of hostnames - they can also contain wildcards
like ``*`` or ``?`` (fnmatch lib is used for matching). If a match is
found the original host is returned.
- any other literal will be be copied verbatim (like ``*`` for instance
to allow any source)

for ``headers``:

- use ``*`` which will allow whatever header is asked for
- any other literal will be be copied verbatim

for ``expose_headers``:

- use ``*`` to allow access to any header the client might wish to access
- any other literal will be be copied verbatim

for ``methods``:

- use ``*`` which will allow whatever method is asked for
- any other literal will be be copied verbatim (like
``POST, PATCH, PUT, DELETE`` for instance)

for ``credentials``:

- use ``true``
- anything else will be ignored (that is no response header for
``Access-Control-Allow-Credentials`` is sent)

for ``maxage``:

- give the number of seconds the answer can be used by a client,
anything nonempty will be copied verbatim

As can be seen in the example above, a policy needs to be created with
the ``policy`` keyword. The options need then be prefixed with the
policy name and a ``_``.
The ``policy`` keyword itself can be a comma separated list. If so the origin of the request is matched against the origins defined in the policies and the first matching is the policy used.
An alternative matching strategy would be ``verbmatch``, that selects the first of the listed that also matches the request method. To switch between the strategies use the

``matchstrategy`` keyword:

- use ``firstmatch`` (the default) to select the first of the policies that matches on the ``origin`` keyword
- use ``verbmatch`` to select the first of the policies that matches on the ``methods`` and ``origin`` keyword


Version 0.7.0
- ``verbmulti`` matching strategy, that matches the first listed policy that also matches the requested METHOD
- relaxed dependency on lru_cache version

Version 0.6.0
- support for multiple policies
- caching of matching results

Version 0.5.1
- check for request being preflight
- reworked tests

Version 0.5.0

- support for Access-Control-Expose-Headers
- Header ``Vary`` is set to ``Origin`` if origin policy differs from ``*``

Version 0.4.1

- py3 utf-8 related setup fixes

Version 0.4

- python3 compatibility

Version 0.3

- ``origin`` now takes space separated list of hostnames. They can be
filename patterns like \*.domain.tld

Version 0.2

- Access-Control-Allow-Credentials is now returned in the actual
reponse if specified by policy


“wsgicors” is written and maintained by Norman Krämer.


The following people contributed directly or indirectly to this project:

- `Julien De Vos <>`_
- `Ryan Shaw <>`_
- `David Douard <>`_
- `MattSANU <>`_
- `Sami Salonen <>`_
- `Sami Salonen <>`_
- `Wouter Claeys <>`_
Please add yourself here when you submit your first pull request.

Release History

This version
History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


Download Files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Filename, Size & Hash SHA256 Hash Help File Type Python Version Upload Date
(13.8 kB) Copy SHA256 Hash SHA256
Source None Feb 26, 2017

Supported By

Elastic Elastic Search Pingdom Pingdom Monitoring Dyn Dyn DNS Sentry Sentry Error Logging CloudAMQP CloudAMQP RabbitMQ Kabu Creative Kabu Creative UX & Design Fastly Fastly CDN DigiCert DigiCert EV Certificate Google Google Cloud Servers