Skip to content

Commit

Permalink
Improve documentation and clarify how to use app-configuration (#277)
Browse files Browse the repository at this point in the history
* some trivial fixes to remove pytest DeprecationWarnings

* we're not using the `static_` directory; this suppresses a warning at
documentation make time

* put every senctence on a new line; this doesn't impact the formatting of
the end result, but does make document manipulation and searching easier
with various UNIX tools.

* put every sentence on its own line

* added dedicated documentation on configuration options, locations and
default values

* added some more corss referenes. building the doc now requires the
sphinxcontrib-httpdomain package to be installed.

* elaborated a bit more on the naming of the configuration options across
locations
  • Loading branch information
bbbart authored Sep 7, 2020
1 parent 285cf12 commit aa822c3
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 57 deletions.
63 changes: 25 additions & 38 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,13 @@ Flask-CORS
|Build Status| |Latest Version| |Supported Python versions|
|License|

A Flask extension for handling Cross Origin Resource Sharing (CORS),
making cross-origin AJAX possible.

This package has a simple philosophy, when you want to enable CORS, you
wish to enable it for all use cases on a domain. This means no mucking
around with different allowed headers, methods, etc. By default,
submission of cookies across domains is disabled due to the security
implications, please see the documentation for how to enable
credential'ed requests, and please make sure you add some sort of
`CSRF <http://en.wikipedia.org/wiki/Cross-site_request_forgery>`__
protection before doing so!
A Flask extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible.

This package has a simple philosophy: when you want to enable CORS, you wish to enable it for all use cases on a domain.
This means no mucking around with different allowed headers, methods, etc.

By default, submission of cookies across domains is disabled due to the security implications.
Please see the documentation for how to enable credential'ed requests, and please make sure you add some sort of `CSRF <http://en.wikipedia.org/wiki/Cross-site_request_forgery>`__ protection before doing so!

Installation
------------
Expand All @@ -28,14 +24,15 @@ Install the extension with using pip, or easy\_install.
Usage
-----

This package exposes a Flask extension which by default enables CORS support on all routes, for all origins and methods. It allows parameterization of all CORS headers on a per-resource level. The package also contains a decorator, for those who prefer this approach.
This package exposes a Flask extension which by default enables CORS support on all routes, for all origins and methods.
It allows parameterization of all CORS headers on a per-resource level.
The package also contains a decorator, for those who prefer this approach.

Simple Usage
~~~~~~~~~~~~

In the simplest case, initialize the Flask-Cors extension with default
arguments in order to allow CORS for all domains on all routes. See the
full list of options in the `documentation <https://flask-cors.corydolphin.com/en/latest/api.html#extension>`__.
In the simplest case, initialize the Flask-Cors extension with default arguments in order to allow CORS for all domains on all routes.
See the full list of options in the `documentation <https://flask-cors.corydolphin.com/en/latest/api.html#extension>`__.

.. code:: python
Expand All @@ -53,10 +50,8 @@ full list of options in the `documentation <https://flask-cors.corydolphin.com/e
Resource specific CORS
^^^^^^^^^^^^^^^^^^^^^^

Alternatively, you can specify CORS options on a resource and origin
level of granularity by passing a dictionary as the `resources` option,
mapping paths to a set of options. See the
full list of options in the `documentation <https://flask-cors.corydolphin.com/en/latest/api.html#extension>`__.
Alternatively, you can specify CORS options on a resource and origin level of granularity by passing a dictionary as the `resources` option, mapping paths to a set of options.
See the full list of options in the `documentation <https://flask-cors.corydolphin.com/en/latest/api.html#extension>`__.

.. code:: python
Expand All @@ -70,10 +65,9 @@ full list of options in the `documentation <https://flask-cors.corydolphin.com/e
Route specific CORS via decorator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This extension also exposes a simple decorator to decorate flask routes
with. Simply add ``@cross_origin()`` below a call to Flask's
``@app.route(..)`` to allow CORS on a given route. See the
full list of options in the `decorator documentation <https://flask-cors.corydolphin.com/en/latest/api.html#decorator>`__.
This extension also exposes a simple decorator to decorate flask routes with.
Simply add ``@cross_origin()`` below a call to Flask's ``@app.route(..)`` to allow CORS on a given route.
See the full list of options in the `decorator documentation <https://flask-cors.corydolphin.com/en/latest/api.html#decorator>`__.

.. code:: python
Expand All @@ -85,14 +79,12 @@ full list of options in the `decorator documentation <https://flask-cors.corydol
Documentation
-------------

For a full list of options, please see the full
`documentation <https://flask-cors.corydolphin.com/en/latest/api.html>`__
For a full list of options, please see the full `documentation <https://flask-cors.corydolphin.com/en/latest/api.html>`__

Troubleshooting
---------------

If things aren't working as you expect, enable logging to help understand
what is going on under the hood, and why.
If things aren't working as you expect, enable logging to help understand what is going on under the hood, and why.

.. code:: python
Expand All @@ -102,25 +94,20 @@ what is going on under the hood, and why.
Tests
-----

A simple set of tests is included in ``test/``. To run, install nose,
and simply invoke ``nosetests`` or ``python setup.py test`` to exercise
the tests.
A simple set of tests is included in ``test/``.
To run, install nose, and simply invoke ``nosetests`` or ``python setup.py test`` to exercise the tests.

Contributing
------------

Questions, comments or improvements? Please create an issue on
`Github <https://github.com/corydolphin/flask-cors>`__, tweet at
`@corydolphin <https://twitter.com/corydolphin>`__ or send me an email.
I do my best to include every contribution proposed in any way that I
can.
Questions, comments or improvements?
Please create an issue on `Github <https://github.com/corydolphin/flask-cors>`__, tweet at `@corydolphin <https://twitter.com/corydolphin>`__ or send me an email.
I do my best to include every contribution proposed in any way that I can.

Credits
-------

This Flask extension is based upon the `Decorator for the HTTP Access
Control <http://flask.pocoo.org/snippets/56/>`__ written by Armin
Ronacher.
This Flask extension is based upon the `Decorator for the HTTP Access Control <http://flask.pocoo.org/snippets/56/>`__ written by Armin Ronacher.

.. |Build Status| image:: https://api.travis-ci.org/corydolphin/flask-cors.svg?branch=master
:target: https://travis-ci.org/corydolphin/flask-cors
Expand Down
32 changes: 16 additions & 16 deletions docs/api.rst
Original file line number Diff line number Diff line change
@@ -1,37 +1,33 @@
API Docs
==========

This package exposes a Flask extension which by default enables CORS support on all routes, for all origins and methods. It allows parameterization of all CORS headers on a per-resource level. The package also contains a decorator, for those who prefer this approach.
This package exposes a Flask extension which by default enables CORS support on all routes, for all origins and methods.
It allows parameterization of all CORS headers on a per-resource level. The package also contains a decorator, for those who prefer this approach.

Extension
~~~~~~~~~

This is the suggested approach to enabling CORS. The default configuration
will work well for most use cases.
This is the suggested approach to enabling CORS.
The default configuration will work well for most use cases.

.. autoclass:: flask_cors.CORS

Decorator
~~~~~~~~~

If the `CORS` extension does not satisfy your needs, you may find the
decorator useful. It shares options with the extension, and should be simple
to use.
If the `CORS` extension does not satisfy your needs, you may find the decorator useful.
It shares options with the extension, and should be simple to use.

.. autofunction:: flask_cors.cross_origin


Using `CORS` with cookies
~~~~~~~~~~~~~~~~~~~~~~~~~

By default, Flask-CORS does not allow cookies to be submitted across sites,
since it has potential security implications. If you wish to enable cross-site
cookies, you may wish to add some sort of
`CSRF <http://en.wikipedia.org/wiki/Cross-site_request_forgery>`__
protection to keep you and your users safe.
By default, Flask-CORS does not allow cookies to be submitted across sites, since it has potential security implications.
If you wish to enable cross-site cookies, you may wish to add some sort of `CSRF <http://en.wikipedia.org/wiki/Cross-site_request_forgery>`__ protection to keep you and your users safe.

To allow cookies or authenticated requests to be made
cross origins, simply set the `supports_credentials` option to `True`. E.G.
To allow cookies or authenticated requests to be made cross origins, simply set the `supports_credentials` option to `True`. E.g.

.. code:: python
Expand All @@ -47,13 +43,17 @@ cross origins, simply set the `supports_credentials` option to `True`. E.G.
return "Hello, %s" % session['username']
The above code enables Flask backend to accept cookies to be submitted from cross origin sites. But if you are sending Xhr requests (ajax calls) to a cross-origin server, by default chrome or any modern browser won't send cookies and session with the request. You should use ``withCredentials = True`` while sending Xhr request to enable that. You should keep in mind about the necessary security concerns. Related MDN doc: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
The above code enables Flask backend to accept cookies to be submitted from cross origin sites.
But if you are sending Xhr requests (ajax calls) to a cross-origin server, by default chrome or any modern browser won't send cookies and session with the request.
You should use ``withCredentials = True`` while sending Xhr request to enable that.
You should keep in mind about the necessary security concerns.
Related MDN doc: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials

Using `CORS` with Blueprints
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Flask-CORS supports blueprints out of the box. Simply pass a `blueprint`
instance to the CORS extension, and everything will just work.
Flask-CORS supports blueprints out of the box.
Simply pass a `blueprint` instance to the CORS extension, and everything will just work.

.. literalinclude:: ../examples/blueprints_based_example.py
:language: python
Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx']
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinxcontrib.httpdomain']

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
Expand Down Expand Up @@ -126,7 +126,7 @@
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
#html_static_path = ['_static']

# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
Expand Down
122 changes: 122 additions & 0 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
Configuration
=============

Flask-CORS can be configured at four different locations.
Configuration values are determined in the following order:

#. Resource level settings (e.g when passed as a dictionary)
#. Keyword argument settings
#. App level configuration settings (e.g. CORS_*)
#. :ref:`Default settings <cors_default_values>`

See :ref:`below <locations>` for more information.

Configuration options
~~~~~~~~~~~~~~~~~~~~~

Configuration options are consistently named across the various :ref:`locations <locations>` where they can be set.
A configuration option called *example* can be set with the resource dictionary key *example*, as the keyword argument *example* or as the Flask app configuration key *CORS_EXAMPLE*.

The configuration options recognised by Flask-CORS are:

CORS_ALLOW_HEADERS (:py:class:`~typing.List` or :py:class:`str`)
Headers to accept from the client.
Headers in the :http:header:`Access-Control-Request-Headers` request header (usually part of the preflight OPTIONS request) maching headers in this list will be included in the :http:header:`Access-Control-Allow-Headers` response header.

CORS_ALWAYS_SEND (:py:class:`bool`)
Usually, if a request doesn't include an :http:header:`Origin` header, the client did not request CORS.
This means we can ignore this request.

However, if this is true, a most-likely-to-be-correct value is still set.

CORS_AUTOMATIC_OPTIONS (:py:class:`bool`)
Only applies to the :py:meth:`flask_cors.cross_origin` decorator.
If True, Flask-CORS will override Flask’s default OPTIONS handling to return CORS headers for OPTIONS requests.

CORS_EXPOSE_HEADERS (:py:class:`~typing.List` or :py:class:`str`)
The CORS spec requires the server to give explicit permissions for the client to read headers in CORS responses (via the :http:header:`Access-Control-Expose-Headers` header).
This specifies the headers to include in this header.

CORS_INTERCEPT_EXCEPTIONS (:py:class:`bool`)
Whether to deal with Flask exception handlers or leave them alone (with respect to CORS headers).

CORS_MAX_AGE (:py:class:`~datetime.timedelta`, :py:class:`int` or :py:class:`str`)
The maximum time for which this CORS request may be cached.
This value is set as the :http:header:`Access-Control-Max-Age` header.

CORS_METHODS (:py:class:`~typing.List` or :py:class:`str`)
The method(s) which the allowed origins are allowed to access.
These are included in the :http:header:`Access-Control-Allow-Methods` response headers to the preflight OPTIONS requests.

.. _cors_origins_setting:

CORS_ORIGINS (:py:class:`~typing.List`, :py:class:`str` or :py:class:`re.Pattern`)
The origin(s) to allow requests from.
An origin configured here that matches the value of the :http:header:`Origin` header in a preflight OPTIONS request is returned as the value of the :http:header:`Access-Control-Allow-Origin` response header.

CORS_RESOURCES (:py:class:`~typing.Dict`, :py:class:`~typing.List` or :py:class:`str`)
The series of regular expression and (optionally) associated CORS options to be applied to the given resource path.

If the value is a dictionary, it's keys must be regular expressions matching resources, and the values must be another dictionary of configuration options, as described in this section.

If the argument is a list, it is expected to be a list of regular expressions matching resources for which the app-wide configured options are applied.

If the argument is a string, it is expected to be a regular expression matching resources for which the app-wide configured options are applied.

CORS_SEND_WILDCARD (:py:class:`bool`)
If :ref:`CORS_ORIGINS <cors_origins_setting>` is ``"*"`` and this is true, then the :http:header:`Access-Control-Allow-Origin` response header's value with be ``"*"`` as well, instead of the value of the :http:header:`Origin` request header.

CORS_SUPPORTS_CREDENTIALS (:py:class:`bool`)
Allows users to make authenticated requests.
If true, injects the :http:header:`Access-Control-Allow-Credentials` header in responses.
This allows cookies and credentials to be submitted across domains.

:note: This option cannot be used in conjunction with a "*" origin

CORS_VARY_HEADER: (:py:class:`bool`)
Enables or disables the injection of the :http:header:`Vary` response header is set to ``Origin``.
This informs clients that our CORS headers are dynamic and cannot be cached.

.. _cors_default_values:

Default values
~~~~~~~~~~~~~~

* CORS_ALLOW_HEADERS: "*"
* CORS_ALWAYS_SEND: True
* CORS_AUTOMATIC_OPTIONS: True
* CORS_EXPOSE_HEADERS: None
* CORS_INTERCEPT_EXCEPTIONS: True
* CORS_MAX_AGE: None
* CORS_METHODS: [":http:method:`get`", ":http:method:`head`", ":http:method:`post`", ":http:method:`options`", ":http:method:`put`", ":http:method:`patch`", ":http:method:`delete`"]
* CORS_ORIGINS: "*"
* CORS_RESOURCES: r"/\*"
* CORS_SEND_WILDCARD: False
* CORS_SUPPORTS_CREDENTIALS: False
* CORS_VARY_HEADER: True

.. _locations:

Locations
~~~~~~~~~

Resource level settings
^^^^^^^^^^^^^^^^^^^^^^^

You can specify CORS options on a resource level of granularity by passing a dictionary as the *resources* keyword argument when instantiating the :py:class:`flask_cors.CORS` object (or when calling ``init_app`` on it), mapping paths to a set of options.

Keyword argument settings
^^^^^^^^^^^^^^^^^^^^^^^^^

For options matching all resources, it's also possible to simply set the configuration options using keyword arguments when instantiating the :py:class:`flask_cors.CORS` object (or when calling ``init_app`` on it).

App level configuration settings
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

It's good practice to keep your application configuration settings in one place.
This is also possible with Flask-CORS using the same configuration options in the Flas application's config object.

Default settings
^^^^^^^^^^^^^^^^

Finally, every setting has a :ref:`default value <cors_default_values>` as well.
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
:name: mastertoc

self
configuration
api

2 changes: 1 addition & 1 deletion flask_cors/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class CORS(object):
`Access-Control-Allow-Credentials` header in responses. This allows
cookies and credentials to be submitted across domains.
:note: This option cannot be used in conjuction with a '*' origin
:note: This option cannot be used in conjunction with a '*' origin
Default : False
:type supports_credentials: bool
Expand Down

0 comments on commit aa822c3

Please sign in to comment.