Code Monkey home page Code Monkey logo

django-cors-headers's Introduction

django-cors-headers

https://img.shields.io/github/actions/workflow/status/adamchainz/django-cors-headers/main.yml.svg?branch=main&style=for-the-badge https://img.shields.io/badge/Coverage-100%25-success?style=for-the-badge https://img.shields.io/pypi/v/django-cors-headers.svg?style=for-the-badge https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge pre-commit

A Django App that adds Cross-Origin Resource Sharing (CORS) headers to responses. This allows in-browser requests to your Django application from other origins.


Improve your Django and Git skills with my books.


About CORS

Adding CORS headers allows your resources to be accessed on other domains. It's important you understand the implications before adding the headers, since you could be unintentionally opening up your site's private data to others.

Some good resources to read on the subject are:

Requirements

Python 3.8 to 3.12 supported.

Django 3.2 to 5.1 supported.

Setup

Install from pip:

python -m pip install django-cors-headers

and then add it to your installed apps:

INSTALLED_APPS = [
    ...,
    "corsheaders",
    ...,
]

Make sure you add the trailing comma or you might get a ModuleNotFoundError (see this blog post).

You will also need to add a middleware class to listen in on responses:

MIDDLEWARE = [
    ...,
    "corsheaders.middleware.CorsMiddleware",
    "django.middleware.common.CommonMiddleware",
    ...,
]

CorsMiddleware should be placed as high as possible, especially before any middleware that can generate responses such as Django's CommonMiddleware or Whitenoise's WhiteNoiseMiddleware. If it is not before, it will not be able to add the CORS headers to these responses.

About

django-cors-headers was created in January 2013 by Otto Yiu. It went unmaintained from August 2015 and was forked in January 2016 to the package django-cors-middleware by Laville Augustin at Zeste de Savoir. In September 2016, Adam Johnson, Ed Morley, and others gained maintenance responsibility for django-cors-headers (Issue 110) from Otto Yiu. Basically all of the changes in the forked django-cors-middleware were merged back, or re-implemented in a different way, so it should be possible to switch back. If there's a feature that hasn't been merged, please open an issue about it.

django-cors-headers has had 40+ contributors in its time; thanks to every one of them.

Configuration

Configure the middleware's behaviour in your Django settings. You must set at least one of three following settings:

  • CORS_ALLOWED_ORIGINS
  • CORS_ALLOWED_ORIGIN_REGEXES
  • CORS_ALLOW_ALL_ORIGINS

CORS_ALLOWED_ORIGINS: Sequence[str]

A list of origins that are authorized to make cross-site HTTP requests. The origins in this setting will be allowed, and the requesting origin will be echoed back to the client in the access-control-allow-origin header. Defaults to [].

An Origin is defined by the CORS RFC Section 3.2 as a URI scheme + hostname + port, or one of the special values 'null' or 'file://'. Default ports (HTTPS = 443, HTTP = 80) are optional.

The special value null is sent by the browser in "privacy-sensitive contexts", such as when the client is running from a file:// domain. The special value file:// is sent accidentally by some versions of Chrome on Android as per this bug.

Example:

CORS_ALLOWED_ORIGINS = [
    "https://example.com",
    "https://sub.example.com",
    "http://localhost:8080",
    "http://127.0.0.1:9000",
]

Previously this setting was called CORS_ORIGIN_WHITELIST, which still works as an alias, with the new name taking precedence.

CORS_ALLOWED_ORIGIN_REGEXES: Sequence[str | Pattern[str]]

A list of strings representing regexes that match Origins that are authorized to make cross-site HTTP requests. Defaults to []. Useful when CORS_ALLOWED_ORIGINS is impractical, such as when you have a large number of subdomains.

Example:

CORS_ALLOWED_ORIGIN_REGEXES = [
    r"^https://\w+\.example\.com$",
]

Previously this setting was called CORS_ORIGIN_REGEX_WHITELIST, which still works as an alias, with the new name taking precedence.

CORS_ALLOW_ALL_ORIGINS: bool

If True, all origins will be allowed. Other settings restricting allowed origins will be ignored. Defaults to False.

Setting this to True can be dangerous, as it allows any website to make cross-origin requests to yours. Generally you'll want to restrict the list of allowed origins with CORS_ALLOWED_ORIGINS or CORS_ALLOWED_ORIGIN_REGEXES.

Previously this setting was called CORS_ORIGIN_ALLOW_ALL, which still works as an alias, with the new name taking precedence.


The following are optional settings, for which the defaults probably suffice.

CORS_URLS_REGEX: str | Pattern[str]

A regex which restricts the URL's for which the CORS headers will be sent. Defaults to r'^.*$', i.e. match all URL's. Useful when you only need CORS on a part of your site, e.g. an API at /api/.

Example:

CORS_URLS_REGEX = r"^/api/.*$"

CORS_ALLOW_METHODS: Sequence[str]

A list of HTTP verbs that are allowed for the actual request. Defaults to:

CORS_ALLOW_METHODS = (
    "DELETE",
    "GET",
    "OPTIONS",
    "PATCH",
    "POST",
    "PUT",
)

The default can be imported as corsheaders.defaults.default_methods so you can just extend it with your custom methods. This allows you to keep up to date with any future changes. For example:

from corsheaders.defaults import default_methods

CORS_ALLOW_METHODS = (
    *default_methods,
    "POKE",
)

CORS_ALLOW_HEADERS: Sequence[str]

The list of non-standard HTTP headers that you permit in requests from the browser. Sets the Access-Control-Allow-Headers header in responses to preflight requests. Defaults to:

CORS_ALLOW_HEADERS = (
    "accept",
    "authorization",
    "content-type",
    "user-agent",
    "x-csrftoken",
    "x-requested-with",
)

The default can be imported as corsheaders.defaults.default_headers so you can extend it with your custom headers. This allows you to keep up to date with any future changes. For example:

from corsheaders.defaults import default_headers

CORS_ALLOW_HEADERS = (
    *default_headers,
    "my-custom-header",
)

CORS_EXPOSE_HEADERS: Sequence[str]

The list of extra HTTP headers to expose to the browser, in addition to the default safelisted headers. If non-empty, these are declared in the access-control-expose-headers header. Defaults to [].

CORS_PREFLIGHT_MAX_AGE: int

The number of seconds the browser can cache the preflight response. This sets the access-control-max-age header in preflight responses. If this is 0 (or any falsey value), no max age header will be sent. Defaults to 86400 (one day).

Note: Browsers send preflight requests before certain “non-simple” requests, to check they will be allowed. Read more about it in the CORS MDN article.

CORS_ALLOW_CREDENTIALS: bool

If True, cookies will be allowed to be included in cross-site HTTP requests. This sets the Access-Control-Allow-Credentials header in preflight and normal responses. Defaults to False.

Note: in Django 2.1 the SESSION_COOKIE_SAMESITE setting was added, set to 'Lax' by default, which will prevent Django's session cookie being sent cross-domain. Change the setting to 'None' if you need to bypass this security restriction.

CORS_ALLOW_PRIVATE_NETWORK: bool

If True, allow requests from sites on “public” IP to this server on a “private” IP. In such cases, browsers send an extra CORS header access-control-request-private-network, for which OPTIONS responses must contain access-control-allow-private-network: true.

Refer to:

CSRF Integration

Most sites will need to take advantage of the Cross-Site Request Forgery protection that Django offers. CORS and CSRF are separate, and Django has no way of using your CORS configuration to exempt sites from the Referer checking that it does on secure requests. The way to do that is with its CSRF_TRUSTED_ORIGINS setting. For example:

CORS_ALLOWED_ORIGINS = [
    "https://read-only.example.com",
    "https://read-and-write.example.com",
]

CSRF_TRUSTED_ORIGINS = [
    "https://read-and-write.example.com",
]

Signals

If you have a use case that requires more than just the above configuration, you can attach code to check if a given request should be allowed. For example, this can be used to read the list of origins you allow from a model. Attach any number of handlers to the check_request_enabled Django signal, which provides the request argument (use **kwargs in your handler to protect against any future arguments being added). If any handler attached to the signal returns a truthy value, the request will be allowed.

For example you might define a handler like this:

# myapp/handlers.py
from corsheaders.signals import check_request_enabled

from myapp.models import MySite


def cors_allow_mysites(sender, request, **kwargs):
    return MySite.objects.filter(host=request.headers["origin"]).exists()


check_request_enabled.connect(cors_allow_mysites)

Then connect it at app ready time using a Django AppConfig:

# myapp/__init__.py

default_app_config = "myapp.apps.MyAppConfig"
# myapp/apps.py

from django.apps import AppConfig


class MyAppConfig(AppConfig):
    name = "myapp"

    def ready(self):
        # Makes sure all signal handlers are connected
        from myapp import handlers  # noqa

A common use case for the signal is to allow all origins to access a subset of URL's, whilst allowing a normal set of origins to access all URL's. This isn't possible using just the normal configuration, but it can be achieved with a signal handler.

First set CORS_ALLOWED_ORIGINS to the list of trusted origins that are allowed to access every URL, and then add a handler to check_request_enabled to allow CORS regardless of the origin for the unrestricted URL's. For example:

# myapp/handlers.py
from corsheaders.signals import check_request_enabled


def cors_allow_api_to_everyone(sender, request, **kwargs):
    return request.path.startswith("/api/")


check_request_enabled.connect(cors_allow_api_to_everyone)

django-cors-headers's People

Contributors

aaron7 avatar adamchainz avatar darrinm avatar darylyu avatar dependabot[bot] avatar jayvdb avatar lukaszb avatar marfire avatar michael-k avatar minho42 avatar mkai avatar mlissner avatar mtomwing avatar nikolas avatar opozo avatar ottoyiu avatar pdufour avatar pennersr avatar pre-commit-ci[bot] avatar robustican avatar royalflamejlh avatar rsalmaso avatar sawan avatar sciyoshi avatar sobolevn avatar suligap avatar tanoabeleyra avatar thijstriemstra avatar timgates42 avatar unknownplatypus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-cors-headers's Issues

'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed

I am using django-cors-headers and I have deployed my application on server, but still I am getting this issue. My current setting for CORS are

INSTALLED_APPS = ['corsheaders']

MIDDLEWARE_CLASSES = ['corsheaders.middleware.CorsMiddleware', 'corsheaders.middleware.CorsPostCsrfMiddleware']

CORS_ORIGIN_ALLOW_ALL = True

CORS_REPLACE_HTTPS_REFERER = True


CORS_ALLOW_HEADERS = (
        'x-requested-with',
        'content-type',
        'accept',
        'origin',
        'authorization',
        'x-csrftoken',
        'accept-encoding'
    )

CORS_ALLOW_METHODS = (
        'GET',
        'POST',
        'PUT',
        'PATCH',
        'DELETE',
        'OPTIONS'
    )

is there anyone who has resolved the following issue

CSRF Failing

I'm having an issue with the CSRF failing inconsistently.

Here are the modules that I have installed:

  • Django == 1.7.4
  • Cors Headers == 1.0.0
  • Rest Framework == 3.0.2

I have this in my settings.py

INSTALLED_APPS = (
   ...,
   'corsheaders',
   ...
)

MIDDLEWARE_CLASSES = (
   ...,
   'corsheaders.middleware.CorsMiddleware',
   'django.middleware.common.CommonMiddleware',
   ...
)

CORS_ORIGIN_ALLOW_ALL = True
CORS_URLS_REGEX = r'^/api/.*$'

The issue that I'm getting is CSRF Failed: CSRF token missing or incorrect from the server, however; this is happening inconsistently. Sometimes, the CSRF will not file but after an hour or less, it starts to fail again.

Could this be because of Rest Framework 3 or Django 1.7?

Problem with CORS_ALLOW_HEADERS setting

I have added the following line to my Django settings using the plugin:

CORS_ALLOW_HEADERS = ('MY-auth-origin')

which causes my response header to be

Access-Control-Allow-Headers:M,Y, -, a, u, t, h, -, o, r, i, g, i, n

Solution
I tried adding two headers (as per example in docs)

CORS_ALLOW_HEADERS = ('MY-auth-origin','Dean-Is-Awesome')

which returns the proper first header as

Access-Control-Allow-Headers: MY-auth-origin, Dean-Is-Awesome

Using Django version 1.8.4 and Google Chrome Version 48.0.2564.97 m (64-bit)

IE8/9 setup

Hey guys!

Im using django-cors-headers with django-rest-framework and an angularjs client. All my server side is using a subdomain like api.myapp.com and my client app is www.myapp.com. All works fine except for IE8 and 9. Any ideas how to set that up? All I see on the IE8 debug window is the cross domain error.
Thank you for any clue!

Chromium won't accept CORS unless Access-Control-Allow-Origin is an allowed header

In our tests, Chromium was unable to communicate to a Django app using
this plugin unless we overrode CORS_ALLOW_HEADERS in settings.py to
include the access-control-allow-origin header itself.

Thus, if you can replicate, I think the default headers in the plugin
should include that, and be like:

CORS_ALLOW_HEADERS = (
    'x-requested-with',
    'content-type',
    'accept',
    'origin',
    'authorization',
    'x-csrftoken',
    'access-control-allow-origin',
)

CorsPostCsrfMiddleware

corsheaders.middleware.CorsPostCsrfMiddleware doesn't find.
1.0.0 doesn't have it. Did you forget to push it?

XMLHttpRequest cannot load ... The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed. Origin is therefore not allowed access.

I'm using CORS_ORIGIN_ALLOW_ALL = True. In Chrome I'm getting this error message.

XMLHttpRequest cannot load XXXXXX. The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed. Origin 'XXXXX' is therefore not allowed access.

FireFox says:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at XXXXX. This can be fixed by moving the resource to the same domain or enabling CORS.

Am I doing something wrong, or is it a bug?

Setting CORS_ORIGIN_WHITELIST to None causes an exception to be raised

Although the doc states that setting CORS_ORIGIN_WHITELIST to None will allow anyone access to the service, this causes the following error:

Internal Server Error: /
Traceback (most recent call last):
  File "/home/vagrant/.virtualenvs/WebsiteBackend/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 201, in get_response
    response = middleware_method(request, response)
  File "/home/vagrant/.virtualenvs/WebsiteBackend/local/lib/python2.7/site-packages/corsheaders/middleware.py", line 44, in process_response
    if not settings.CORS_ORIGIN_ALLOW_ALL and self.origin_not_found_in_white_lists(origin, url):
  File "/home/vagrant/.virtualenvs/WebsiteBackend/local/lib/python2.7/site-packages/corsheaders/middleware.py", line 64, in origin_not_found_in_white_lists
    return url.netloc not in settings.CORS_ORIGIN_WHITELIST and not self.regex_domain_match(origin)
TypeError: argument of type 'NoneType' is not iterable

If this behaviour is indeed unexpected, I'l be happy to send a PR.

Thanks,

Work with runserver, but failed run with uwsgi+nginx

It works when I run my website with runserver, but sometimes cors POST request failed when I run it with uwsgi + Nginx. Here's the output from chrome console when it failed:

1

Should I config uwsgi or Nginx as well?

Browser doesn't follow 302 redirect for preflighted CORS requests.

I'm not sure if this behaviour is triggered by any particular combination or lack of headers being set by django-cors-headers, or if it's a general limitation or CORS, or an implementation bug in both Firefox and Chrome (and possibly others?)

I have installed django-cors-headers and set CORS_ORIGIN_WHITELIST to actual host names (so it's not setting Access-Control-Allow-Origin: *, it's using the actual whitelisted origin.

If I submit a "safe" (non-preflighted) POST request to a URL that returns a 302 redirect, the browser will transparently follow that redirect.

If I trigger a preflighted POST request by changing the content type to something like text/css, or include an additional header like X-Requested-With: XMLHttpRequest, then the browser will not follow the redirect.

Here's my sample code. If you just change the domain names, update the CORS_ORIGIN_WHITELIST setting, and configure the target URL to return a 302 redirect on POST, you should be able to recreate this problem.

test.html:

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.js"></script>
        <script type="text/javascript">
            $(function() {
                $('#preflighted').submit(function(e) {
                    e.preventDefault();
                    $.ajax({
                        contentType: 'text/css',
                        type: 'POST',
                        url: 'http://xyz.com:8000/test/',
                        // headers: {
                        //  'X-Requested-With': 'XMLHttpRequest'
                        // },
                        success: function(data, textStatus, jqXHR) {
                            console.log('success');
                        }
                    })
                });
                $('#simple').submit(function(e) {
                    e.preventDefault();
                    $.ajax({
                        type: 'POST',
                        url: 'http://xyz.com:8000/test/',
                        success: function(data, textStatus, jqXHR) {
                            console.log('success');
                        }
                    })
                });
            });
        </script>
    </head>
    <body>
        <form id="preflighted" action="http://xyz.com:8000/test/" method="POST">
            <input type="submit" value="Submit preflighted CORS request">
        </form>
        <form id="simple" action="http://xyz.com:8000/test/" method="POST">
            <input type="submit" value="Submit simple CORS request">
        </form>
    </body>
</html>

views.py:

@csrf_exempt
def test(request):
    if request.method == 'POST':
        return HttpResponseRedirect('/test2/')
    return TemplateResponse(request, 'test.html')

Then view your site at localhost:8000, add that to CORS_ORIGIN_WHITELIST, and add a hosts entry for xyz.com to 127.0.0.1.

Firefox with Firebug does a better job than Chrome at reporting the response headers in both cases.

Simple request (browser DOES follow the redirect):

POST /test/ HTTP/1.1
Host: xyz.com:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Gecko/20100101 Firefox/23.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://localhost:8000/test/
Origin: http://localhost:8000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Content-Length: 0
HTTP/1.0 302 FOUND
Date: Tue, 01 Oct 2013 07:38:02 GMT
Server: WSGIServer/0.1 Python/2.7.5
Access-Control-Allow-Origin: http://localhost:8000
Etag: "d41d8cd98f00b204e9800998ecf8427e"
Content-Type: text/html; charset=utf-8
Location: http://xyz.com:8000/test2/

Preflighted request (browser does NOT follow redirect):

OPTIONS /test/ HTTP/1.1
Host: xyz.com:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Gecko/20100101 Firefox/23.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Origin: http://localhost:8000
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
HTTP/1.0 200 OK
Date: Tue, 01 Oct 2013 07:41:39 GMT
Server: WSGIServer/0.1 Python/2.7.5
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Max-Age: 86400
Etag: "d41d8cd98f00b204e9800998ecf8427e"
Access-Control-Allow-Origin: http://localhost:8000
Access-Control-Allow-Headers: x-requested-with, content-type, accept, origin, authorization, x-csrftoken
Content-Type: text/html; charset=utf-8
POST /test/ HTTP/1.1
Host: xyz.com:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Gecko/20100101 Firefox/23.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Content-Type: text/css
Referer: http://localhost:8000/test/
Origin: http://localhost:8000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Content-Length: 0
HTTP/1.0 302 FOUND
Date: Tue, 01 Oct 2013 07:41:39 GMT
Server: WSGIServer/0.1 Python/2.7.5
Access-Control-Allow-Origin: http://localhost:8000
Etag: "d41d8cd98f00b204e9800998ecf8427e"
Content-Type: text/html; charset=utf-8
Location: http://xyz.com:8000/test2/

Upload v0.6 to PyPI

Will v0.6 get uploaded to PyPI soon? Are there more changes that need to be added before the new release?

Django 1.7 support

I upgrade to Django 1.7 and this module is not working anymore.

In the first few requests to Django from my web app in another domain, it works just fine. But all of a sudden I get the "No 'Access-Control-Allow-Origin' header is present on the requested resource". And none of following requests are accepted. I could not pinpoint the exact type of request that made it stop working.

It was working fine in Django 1.6.6

Still getting the XMLHttpRequest not allowed by Access-Control-Allow-Origin?

I have 2 django web apps built with the django rest framework. I did the following in both apps

  1. pip install django-cors-headers
  2. added "corsheaders" to the end of my installed apps list
  3. added it to my middleware just under csrf (though my endpoints are exempt for now)

MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)

When I do an ajax http POST from localhost:9000 to localhost:8000 I can watch the terminal and see the endpoint I posted to does return a 201 (successful create on the 8000 web app) but in the chrome dev tools console (where I kicked the ajax request off from) I get the following (run from the 9000 web app).

XMLHttpRequest cannot load http://localhost:8000/object/. Origin http://localhost:9000 is not allowed by Access-Control-Allow-Origin.

When I look at both terminals to see if an OPTION verb was thrown at either web app - it's clear this isn't happening. In fact the only http request that shows up is the HTTP POST (again -returns a 201 and does actually insert the record with the data I sent in the ajax post)

Here is a sample of the ajax method I threw at it (within the chrome dev tools with the port 9000 web app open)

$.ajax({ url: "http://localhost:8000/object/", type: "POST", data: { foo: "bar" }, beforeSend: function ( xhr ) { console.log("x"); } }).done(function ( data ) { console.log("Sample of data:", data); });

I assumed this egg would technically solve this so I'm sure I missed a step :)

Thank you in advance

CORS Ec2 instance behind an ELB Load Balancer

I was wondering if you have any tips for getting this to work in an environment that has a potentially changing IP address or DNS name? Specifically operating behind a Load Balancer.

Add `X-CSRFToken` to default `CORS_ALLOW_HEADERS`

Wondering if Django's X-CSRFToken should be included in the defaults for CORS_ALLOW_HEADERS. As it stands CORS POST/PUT/DELETE requests that include a CSRF token in the form itself will be allowed, but AJAX style CORS requests that include the CSRF token as a header will not be allowed.

I don't really know enough about CORS to know if X-CSRFToken should be in by default, but if not it's probably worth documenting it either as something that users might need to add.

Not seen anyone else report this issue, so may be a misunderstanding on my part. Any thoughts?

This ticket is a result of the follow conv on IRC...

[09:52:06] <Noeble>          hi tomchristie
[09:52:27] <Noeble>          I solved the problem last nite with the csrfcookie
[09:52:51] <tomchristie>     ah good
[09:53:14] <Noeble>          2 simple things
[09:53:27] <Noeble>          @method_decorator(ensure_csrf_cookie)  on the post def in the class based view
[09:53:34] <Noeble>          to force the cookie creation
[09:54:03] <Noeble>          and to allow X-CSRFToken in the CORS settings for incoming headers
[10:10:34] <tomchristie>     Noeble: "and to allow X-CSRFToken in the CORS settings for incoming headers" <--- Is this mentioned in the Django docs someplace?
[10:15:04] <Noeble>          tomchristie: No, its specific for the django-cors-headers, even tho its following the cors standard so its probably similiar in other implementations of cors.
[10:16:22] <tomchristie>     Noeble: Confused - CSRF not mentioned in django-cosrs-headers, tho?
[10:16:40] <Noeble>          nope, its not but CORS_ALLOW_HEADERS is
[10:16:51] <Noeble>          and it tells you the headers that is allowed by default
[10:17:18] <Noeble>          if you wanna use other headers towards the cors api you need to add it to the tuple
[10:18:04] <tomchristie>     Noeble: So what have you got in your django-cors-headers settings then?
[10:18:28] <Noeble>          http://pastebin.com/tv5pTmYV
[10:18:39] <Noeble>          I added the 5 default ones + the custom header for django csrf
[10:19:33] <tomchristie>     Ahhhhhhhh
[10:20:09] <Noeble>          :)
[10:21:31] <tomchristie>     Looks to me that that ought to be in there by default
[10:21:47] <tomchristie>     `CORS_ALLOW_METHODS` includes POST etc by default, so….
[10:22:16] <Noeble>          yea if you put the csrftoken inside the form it will work
[10:23:40] <Noeble>          but I do a post using angularjs, and I dont do any template rendering
[10:24:03] <Noeble>          $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
[10:28:29] <Noeble>          Same thing applies if you do a normal ajax post with jquery, not rendering th csrf token inside the form
[10:28:52] <Noeble>          cross domain that it
[10:28:55] <Noeble>          is-

use new Django app loading system

importing cors-headers in Django 1.7+ results in

.../lib/python3.4/importlib/_bootstrap.py:321: RemovedInDjango19Warning: The utilities in django.db.models.loading are deprecated in favor of the new application loading system.
  return f(*args, **kwds)

It can be fixed by replacing "from django.db.models.loading import get_model"
in corsheaders/middleware.py with

try:
    from django.apps import apps
    get_model = apps.get_model
except:
    from django.db.models.loading import get_model

Default allow_headers breaks JSON in Safari

Not sure if this should be added to the defaults or simply mentioned in the relevant section of the README, but communicating in JSON on Safari causes the following error:

Failed to load resource: Request header field Accept-Encoding is not allowed by Access-Control-Allow-Headers.

[Error] XMLHttpRequest cannot load http://mydomain.com/mypath. Request header field Accept-Encoding is not allowed by Access-Control-Allow-Headers. (localhost, line 0)

The fix is to add 'accept-encoding' to CORS_ALLOW_HEADERS

Not working for me (I must be doing something wrong)

Total noob here, but let me describe what I did...

I cloned the repo and installed. Then I opened settings.py of my website and added 'corsheaders' to the INSTALLED_APPS.

I also didn't forget adding 'corsheaders.middleware.CorsMiddleware' to MIDDLEWARE_CLASSES, before the 'django.middleware.common.CommonMiddleware'.

CORS_ORIGIN_ALLOW_ALL = True

... this i added to the end of settings.py. Is that ok?

This is the firebug output of the ajax GET request:

Accept text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Encoding gzip, deflate
Accept-Language sl,en-GB;q=0.7,en;q=0.3
DNT 1
Host example.com:8933
Origin http://example.com
Referer http://example.com/myapp/
User-Agent Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0

Django AWS S3

Image from origin 'https://{{name}}.amazonaws.com' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://192.168.10.171:9090' is therefore not allowed access.

Is Django-cors-headers solved cross origin issues or not?

requests from different types of clients

I have been experimenting with different settings and don't think there's a solution a good solution for the following scenario (other than modifying headers in the view method):

I have a resource on /api that can be accessed from anywhere:

CORS_ORIGIN_ALLOW_ALL = True
CORS_URLS_REGEX = r'^/api/.*$'

All works fine w/ that. Now I want to access a resource on /priv-api. Using these settings it works:

CORS_ORIGIN_WHITELIST = (
    'sub.domain.com'
)
CORS_ALLOW_CREDENTIALS = True

My problem comes when I try to combine them. I don't want to ALLOW_ALL to /priv-api. Perhaps a CORS_URLS_WHITELIST would satisfy my requirement?

Echo Access-Control-Request-Headers value in Access-Control-Allow-Headers

I am investigating the Cross-Domains problems, I have with some REST service call. Chrome said this: Request header field x-requested-with is not allowed by Access-Control-Allow-Headers.

The solution that I have read, is to exactly echo back value of "Access-Control-Request-Headers" to "Access-Control-Allow-Headers".

Need a way (config) to get this done.

does it works with Djagno Server

Hi,

I was wondering whether it works with django server (a server bundled with Djagno). I have turned on settings

CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True

But I do't see any headers related cors on response

CORS_EXPOSE_HEADERS fails

I'm trying to add Access-Control-Allow-Origin: * to the response header, and can't seem to accomplish it. I've added installed django-cors-headers with pip, and I have the following in settings.py:

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp',
    'rest_framework',
    'corsheaders',
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
)

CORS_ORIGIN_ALLOW_ALL = False

CORS_ORIGIN_WHITELIST = (
    'localhost',
    'myhost.com'
)

CORS_ALLOW_HEADERS = (
    'x-requested-with',
    'content-type',
    'accept',
    'accept-encoding',
    'origin',
    'authorization',
    'x-csrftoken'
)
CORS_EXPOSE_HEADERS = (
    'Access-Control-Allow-Origin: *',
)

I'm using Django 1.7.1, DRF 3.0.2, Python 3.4. It's quite possible that I just don't understand what your library is supposed to do. I appreciate any help.

pip version missing code?

Hi,

I have ran pip install django-cors-headers and it reported that CorsPostCsrfMiddleware doesn't exist.

I opened files that pip installed and in deed CorsPostCsrfMiddleware class is missing. I have checked github repo, and normally there you have CorsPostCsrfMiddleware.

Then I went to
https://pypi.python.org/pypi/django-cors-headers
and saw that on last two versions available up there there is some missing code.

But when I do pip install git+git://github.com/ottoyiu/django-cors-headers.git all goes good

Can you help what is going on?

Unable to set cookie

Hello folks, not sure this is the right place to ask but, here we go:
I have a project composed of a ionic app and a django project with cors-headers configured. In my ionic app, I make a request to a special view in my django project decorated with ensure_csrf_cookie in order to get the csrftoken cookie. When I do this using my local development server, I manage to fetch the cookie. When I send the request to the remote django server (running behind nginx+uwsgi), the django project sets the cookie but it never reaches my ionic app.
I have

CORS_ALLOW_CREDENTIALS = True

in my django settings and also:

CORS_ORIGIN_REGEX_WHITELIST = (
    '^(https?://)?$',
    '^(https?://)?localhost:\d{4}',
    '^(https?://)?192\.168\.\d+\.\d+(:\d{4})?'
)

So, the server should be reachable to the ionic app from the emulator and also should support cookies. Am I missing something? Could there be a bug?

Middleware will not provide correct CORS response unless view returns 200 response.

If the view returns a non-200 status code (eg if it typically requires authentication, which a CORS OPTIONS request will not provide, then it might return a 403 or 401 response), then then response sent back from the middleware will also be non-200.

The CORS spec is explicit that 200 is the required response, so although the correct headers will have been sent, the response will be disregarded by the client.

As an example, I don't believe this middleware would work out of the box with REST framework views that require authentication.

An alternative would be to instead use process_request, and if the request is an OPTIONS request, and includes an Access-Control-Request-Method indicating that this is a CORS preflight request, then immediately return a 200 response with an empty body and the correct headers set as is currently the case.

It might also make sense to also continue to handle the response case as you currently do, for better consistency of response headers. (Eg. This gist https://gist.github.com/1369619 uses a similar implementation to what I've described here.)

It'd be nice to link to this middleware from the REST framework docs as a definitive solution to CORS, so be great if we could get it working together with authentication-protected APIs one way or another.

My CORS knowledge is a little sketchy so it's entirely possible that I'm being stupid here feel free to talk any of this through if that doesn't seem sensible to you.

Note related discussions:

AttributeError: type object 'CorsModel' has no attribute 'get_viewset'

Running on Django 1.9.x and Python 3.5, it returns the following error when trying to start server or run migrations:

Traceback (most recent call last):
File "manage.py", line 10, in
execute_from_command_line(sys.argv)
File "C:\Users\galeal\AppData\Local\Programs\Python\Python35-32\lib\site-packa
ges\django\core\management__init__.py", line 350, in execute_from_command_line
utility.execute()
File "C:\Users\galeal\AppData\Local\Programs\Python\Python35-32\lib\site-packa
ges\django\core\management__init__.py", line 342, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Users\galeal\AppData\Local\Programs\Python\Python35-32\lib\site-packa
ges\django\core\management\base.py", line 348, in run_from_argv
self.execute(_args, *_cmd_options)
File "C:\Users\galeal\AppData\Local\Programs\Python\Python35-32\lib\site-packa
ges\django\core\management\base.py", line 398, in execute
self.check()
File "C:\Users\galeal\AppData\Local\Programs\Python\Python35-32\lib\site-packa
ges\django\core\management\base.py", line 426, in check
include_deployment_checks=include_deployment_checks,
File "C:\Users\galeal\AppData\Local\Programs\Python\Python35-32\lib\site-packa
ges\django\core\checks\registry.py", line 75, in run_checks
new_errors = check(app_configs=app_configs)
File "C:\Users\galeal\AppData\Local\Programs\Python\Python35-32\lib\site-packa
ges\django\core\checks\urls.py", line 10, in check_url_config
return check_resolver(resolver)
File "C:\Users\galeal\AppData\Local\Programs\Python\Python35-32\lib\site-packa
ges\django\core\checks\urls.py", line 19, in check_resolver
for pattern in resolver.url_patterns:
File "C:\Users\galeal\AppData\Local\Programs\Python\Python35-32\lib\site-packa
ges\django\utils\functional.py", line 33, in get
res = instance.dict[self.name] = self.func(instance)
File "C:\Users\galeal\AppData\Local\Programs\Python\Python35-32\lib\site-packa
ges\django\core\urlresolvers.py", line 417, in url_patterns
patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
File "C:\Users\galeal\AppData\Local\Programs\Python\Python35-32\lib\site-packa
ges\django\utils\functional.py", line 33, in get
res = instance.dict[self.name] = self.func(instance)
File "C:\Users\galeal\AppData\Local\Programs\Python\Python35-32\lib\site-packa
ges\django\core\urlresolvers.py", line 410, in urlconf_module
return import_module(self.urlconf_name)
File "C:\Users\galeal\AppData\Local\Programs\Python\Python35-32\lib\importlib
init.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "", line 986, in _gcd_import
File "", line 969, in _find_and_load
File "", line 958, in _find_and_load_unlocked
File "", line 673, in _load_unlocked
File "", line 662, in exec_module
File "", line 222, in _call_with_frames_removed
File "D:\Guilherme\proj\bitbucket\uengine\union_engine\urls.py", line 4, in
from union_engine.generics import urls as generics_urls
File "D:\Guilherme\proj\bitbucket\uengine\union_engine\generics\urls.py", line
30, in
route_name, mdl.get_viewset(), base_name=route_name)
AttributeError: type object 'CorsModel' has no attribute 'get_viewset'

Internal Server Error

Hello,

I tried to install via pip, then added the necessary code, and deploy it to Heroku. However, the page shows internal server error. How can I debug this?

how to install django-cors-headers on server host computer

I developed a server using Django Python framework which will receive a Json from a client writing using ruby rail framework. The server cannot see the Json and so i want use django-cors-headers but I have already host the app (i.e. the server) using Digital Ocean hosting. My question is Is it possible to install django-cors-headers using the pip install django-cors-headers on the server host computer at Digital Ocean using may be PUTTY or Winscp? If yes, pls how do i do it?

Cors Not Working: Apache and DRF

I installed django-cors-headers==1.0.0
I'm hosting just djangorestframework at localhost:8000

The webcode is hosted in localhost

My settings.py is

THIRD_PARTY_APPS = (
'corsheaders',
'bootstrap_admin',
'adminactions',
'rest_framework',
'rest_framework_swagger',
'taggit',
)

Also installed

MIDDLEWARE_CLASSES = (
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'ccDjango.middleware.SetLastVisitMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

Error in Console

CORS_ORIGIN_ALLOW_ALL = True

Anyone else having the same issue?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.