README.rst 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. django-cors-headers
  2. ===================
  3. A Django App that adds CORS (Cross-Origin Resource Sharing) headers to
  4. responses.
  5. Although JSON-P is useful, it is strictly limited to GET requests. CORS
  6. builds on top of ``XmlHttpRequest`` to allow developers to make cross-domain
  7. requests, similar to same-domain requests. Read more about it here:
  8. http://www.html5rocks.com/en/tutorials/cors/
  9. .. image:: https://travis-ci.org/ottoyiu/django-cors-headers.svg?branch=master
  10. :target: https://travis-ci.org/ottoyiu/django-cors-headers
  11. Requirements
  12. ------------
  13. Tested with all combinations of:
  14. * Python: 2.7, 3.5, 3.6, 3.7
  15. * Django: 1.11, 2.0, 2.1, 2.2
  16. Setup
  17. -----
  18. Install from **pip**:
  19. .. code-block:: sh
  20. pip install django-cors-headers
  21. and then add it to your installed apps:
  22. .. code-block:: python
  23. INSTALLED_APPS = (
  24. ...
  25. 'corsheaders',
  26. ...
  27. )
  28. You will also need to add a middleware class to listen in on responses:
  29. .. code-block:: python
  30. MIDDLEWARE = [ # Or MIDDLEWARE_CLASSES on Django < 1.10
  31. ...
  32. 'corsheaders.middleware.CorsMiddleware',
  33. 'django.middleware.common.CommonMiddleware',
  34. ...
  35. ]
  36. ``CorsMiddleware`` should be placed as high as possible, especially before any
  37. middleware that can generate responses such as Django's ``CommonMiddleware`` or
  38. Whitenoise's ``WhiteNoiseMiddleware``. If it is not before, it will not be able
  39. to add the CORS headers to these responses.
  40. Also if you are using ``CORS_REPLACE_HTTPS_REFERER`` it should be placed before
  41. Django's ``CsrfViewMiddleware`` (see more below).
  42. About
  43. -----
  44. **django-cors-headers** was created in January 2013 by Otto Yiu. It went
  45. unmaintained from August 2015 and was forked in January 2016 to the package
  46. `django-cors-middleware <https://github.com/zestedesavoir/django-cors-middleware>`_
  47. by Laville Augustin at Zeste de Savoir.
  48. In September 2016, Adam Johnson, Ed Morley, and others gained maintenance
  49. responsibility for **django-cors-headers**
  50. (`Issue 110 <https://github.com/ottoyiu/django-cors-headers/issues/110>`_) from
  51. Otto Yiu.
  52. Basically all of the changes in the forked **django-cors-middleware** were
  53. merged back, or re-implemented in a different way, so it should be possible to
  54. switch back. If there's a feature that hasn't been merged, please open an issue
  55. about it.
  56. **django-cors-headers** has had `40+
  57. contributors <https://github.com/ottoyiu/django-cors-headers/graphs/contributors>`_
  58. in its time; thanks to every one of them.
  59. Configuration
  60. -------------
  61. Configure the middleware's behaviour in your Django settings. You must add the
  62. hosts that are allowed to do cross-site requests to
  63. ``CORS_ORIGIN_WHITELIST``, or set ``CORS_ORIGIN_ALLOW_ALL`` to ``True``
  64. to allow all hosts.
  65. ``CORS_ORIGIN_ALLOW_ALL``
  66. ~~~~~~~~~~~~~~~~~~~~~~~~~
  67. If ``True``, the whitelist will not be used and all origins will be accepted.
  68. Defaults to ``False``.
  69. ``CORS_ORIGIN_WHITELIST``
  70. ~~~~~~~~~~~~~~~~~~~~~~~~~
  71. A list of origin hostnames that are authorized to make cross-site HTTP
  72. requests. The value ``'null'`` can also appear in this list, and will match the
  73. ``Origin: null`` header that is used in `"privacy-sensitive contexts"
  74. <https://tools.ietf.org/html/rfc6454#section-6>`_, such as when the client is
  75. running from a ``file://`` domain. Defaults to ``[]``.
  76. Example:
  77. .. code-block:: python
  78. CORS_ORIGIN_WHITELIST = (
  79. 'google.com',
  80. 'hostname.example.com',
  81. 'localhost:8000',
  82. '127.0.0.1:9000'
  83. )
  84. ``CORS_ORIGIN_REGEX_WHITELIST``
  85. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  86. A list of regexes that match origin regex list of origin hostnames that are
  87. authorized to make cross-site HTTP requests. Defaults to ``[]``. Useful when
  88. ``CORS_ORIGIN_WHITELIST`` is impractical, such as when you have a large
  89. number of subdomains.
  90. Example:
  91. .. code-block:: python
  92. CORS_ORIGIN_REGEX_WHITELIST = (r'^(https?://)?(\w+\.)?google\.com$', )
  93. --------------
  94. The following are optional settings, for which the defaults probably suffice.
  95. ``CORS_URLS_REGEX``
  96. ~~~~~~~~~~~~~~~~~~~
  97. A regex which restricts the URL's for which the CORS headers will be sent.
  98. Defaults to ``r'^.*$'``, i.e. match all URL's. Useful when you only need CORS
  99. on a part of your site, e.g. an API at ``/api/``.
  100. Example:
  101. .. code-block:: python
  102. CORS_URLS_REGEX = r'^/api/.*$'
  103. ``CORS_ALLOW_METHODS``
  104. ~~~~~~~~~~~~~~~~~~~~~~
  105. A list of HTTP verbs that are allowed for the actual request. Defaults to:
  106. .. code-block:: python
  107. CORS_ALLOW_METHODS = (
  108. 'DELETE',
  109. 'GET',
  110. 'OPTIONS',
  111. 'PATCH',
  112. 'POST',
  113. 'PUT',
  114. )
  115. The default can be imported as ``corsheaders.defaults.default_methods`` so you
  116. can just extend it with your custom methods. This allows you to keep up to date
  117. with any future changes. For example:
  118. .. code-block:: python
  119. from corsheaders.defaults import default_methods
  120. CORS_ALLOW_METHODS = default_methods + (
  121. 'POKE',
  122. )
  123. ``CORS_ALLOW_HEADERS``
  124. ~~~~~~~~~~~~~~~~~~~~~~
  125. The list of non-standard HTTP headers that can be used when making the actual
  126. request. Defaults to:
  127. .. code-block:: python
  128. CORS_ALLOW_HEADERS = (
  129. 'accept',
  130. 'accept-encoding',
  131. 'authorization',
  132. 'content-type',
  133. 'dnt',
  134. 'origin',
  135. 'user-agent',
  136. 'x-csrftoken',
  137. 'x-requested-with',
  138. )
  139. The default can be imported as ``corsheaders.defaults.default_headers`` so you
  140. can extend it with your custom headers. This allows you to keep up to date with
  141. any future changes. For example:
  142. .. code-block:: python
  143. from corsheaders.defaults import default_headers
  144. CORS_ALLOW_HEADERS = default_headers + (
  145. 'my-custom-header',
  146. )
  147. ``CORS_EXPOSE_HEADERS``
  148. ~~~~~~~~~~~~~~~~~~~~~~~
  149. The list of HTTP headers that are to be exposed to the browser. Defaults to
  150. ``[]``.
  151. ``CORS_PREFLIGHT_MAX_AGE``
  152. ~~~~~~~~~~~~~~~~~~~~~~~~~~
  153. The number of seconds a client/browser can cache the preflight response. If
  154. this is 0 (or any falsey value), no max age header will be sent. Defaults to
  155. ``86400`` (one day).
  156. **Note:** A preflight request is an extra request that is made when making a
  157. "not-so-simple" request (e.g. ``Content-Type`` is not
  158. ``application/x-www-form-urlencoded``) to determine what requests the server
  159. actually accepts. Read more about it in the `HTML 5 Rocks CORS tutorial
  160. <https://www.html5rocks.com/en/tutorials/cors/>`_.
  161. ``CORS_ALLOW_CREDENTIALS``
  162. ~~~~~~~~~~~~~~~~~~~~~~~~~~
  163. If ``True``, cookies will be allowed to be included in cross-site HTTP
  164. requests. Defaults to ``False``.
  165. Note: in Django 2.1 the `SESSION_COOKIE_SAMESITE`_ setting was added, set to
  166. ``'Lax'`` by default, which will prevent Django's session cookie being sent
  167. cross-domain. Change it to ``None`` to bypass this security restriction.
  168. .. _SESSION_COOKIE_SAMESITE: https://docs.djangoproject.com/en/2.1/ref/settings/#std:setting-SESSION_COOKIE_SAMESITE
  169. ``CORS_MODEL``
  170. ~~~~~~~~~~~~~~
  171. If set, this should be the path to a model to look up allowed origins, in the
  172. form ``app.modelname``. Defaults to ``None``.
  173. The model should inherit from ``corsheaders.models.AbstractCorsModel`` and specify
  174. the allowed origin in the ``CharField`` called ``cors``.
  175. CSRF Integration
  176. ----------------
  177. Most sites will need to take advantage of the `Cross-Site Request Forgery
  178. protection <https://docs.djangoproject.com/en/dev/ref/csrf/>`_ that Django
  179. offers. CORS and CSRF are separate, and Django has no way of using your CORS
  180. configuration to exempt sites from the ``Referer`` checking that it does on
  181. secure requests. The way to do that is with its `CSRF_TRUSTED_ORIGINS setting
  182. <https://docs.djangoproject.com/en/dev/ref/settings/#csrf-trusted-origins>`_.
  183. For example:
  184. .. code-block:: python
  185. CORS_ORIGIN_WHITELIST = (
  186. 'read.only.com',
  187. 'change.allowed.com',
  188. )
  189. CSRF_TRUSTED_ORIGINS = (
  190. 'change.allowed.com',
  191. )
  192. ``CORS_REPLACE_HTTPS_REFERER``
  193. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  194. ``CSRF_TRUSTED_ORIGINS`` was introduced in Django 1.9, so users of earlier
  195. versions will need an alternate solution. If ``CORS_REPLACE_HTTPS_REFERER`` is
  196. ``True``, ``CorsMiddleware`` will change the ``Referer`` header to something
  197. that will pass Django's CSRF checks whenever the CORS checks pass. Defaults to
  198. ``False``.
  199. Note that unlike ``CSRF_TRUSTED_ORIGINS``, this setting does not allow you to
  200. distinguish between domains that are trusted to *read* resources by CORS and
  201. domains that are trusted to *change* resources by avoiding CSRF protection.
  202. With this feature enabled you should also add
  203. ``corsheaders.middleware.CorsPostCsrfMiddleware`` after
  204. ``django.middleware.csrf.CsrfViewMiddleware`` in your ``MIDDLEWARE_CLASSES`` to
  205. undo the ``Referer`` replacement:
  206. .. code-block:: python
  207. MIDDLEWARE_CLASSES = [
  208. ...
  209. 'corsheaders.middleware.CorsMiddleware',
  210. ...
  211. 'django.middleware.csrf.CsrfViewMiddleware',
  212. 'corsheaders.middleware.CorsPostCsrfMiddleware',
  213. ...
  214. ]
  215. Signals
  216. -------
  217. If you have a use case that requires more than just the above configuration,
  218. you can attach code to check if a given request should be allowed. For example,
  219. this can be used to read the list of origins you allow from a model. Attach any
  220. number of handlers to the ``check_request_enabled``
  221. `Django signal <https://docs.djangoproject.com/en/1.10/ref/signals/>`_, which
  222. provides the ``request`` argument (use ``**kwargs`` in your handler to protect
  223. against any future arguments being added). If any handler attached to the
  224. signal returns a truthy value, the request will be allowed.
  225. For example you might define a handler like this:
  226. .. code-block:: python
  227. # myapp/handlers.py
  228. from corsheaders.signals import check_request_enabled
  229. from .models import MySite
  230. def cors_allow_mysites(sender, request, **kwargs):
  231. return MySite.objects.filter(host=request.host).exists()
  232. check_request_enabled.connect(cors_allow_mysites)
  233. Then connect it at app ready time using a `Django AppConfig
  234. <https://docs.djangoproject.com/en/1.10/ref/applications/>`_:
  235. .. code-block:: python
  236. # myapp/__init__.py
  237. default_app_config = 'myapp.apps.MyAppConfig'
  238. .. code-block:: python
  239. # myapp/apps.py
  240. from django.apps import AppConfig
  241. class MyAppConfig(AppConfig):
  242. name = 'myapp'
  243. def ready(self):
  244. # Makes sure all signal handlers are connected
  245. from . import handlers # noqa
  246. A common use case for the signal is to allow *all* origins to access a subset
  247. of URL's, whilst allowing a normal set of origins to access *all* URL's. This
  248. isn't possible using just the normal configuration, but it can be achieved with
  249. a signal handler.
  250. First set ``CORS_ORIGIN_WHITELIST`` to the list of trusted origins that are
  251. allowed to access every URL, and then add a handler to
  252. ``check_request_enabled`` to allow CORS regardless of the origin for the
  253. unrestricted URL's. For example:
  254. .. code-block:: python
  255. # myapp/handlers.py
  256. from corsheaders.signals import check_request_enabled
  257. def cors_allow_api_to_everyone(sender, request, **kwargs):
  258. return request.path.startswith('/api/')
  259. check_request_enabled.connect(cors_allow_api_to_everyone)