Django 'WSGIRequest' object has no attribute 'set_cookie' - django

I keep on getting this exception when I do request.set_cookie() in the process_view of a custom middleware class. Here is the order of middleware classes in my settings.py:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'website.middleware.UserLastActiveMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
)

To start off with, set_cookie() is a method of HttpResponse, not HttpRequest, as you set cookies in your response to a requests.
Secondly, your middleware should come after AuthenticationMiddleware, since presumably it has to do with users.

You should set_cookie() call from response object.
Example:
def process_response(self, request, response):
...
response.set_cookie('user_agreement', user_agreement, domain='.mysite.com')
return response

You can take a look at this question: Django: WSGIRequest' object has no attribute 'user' on some pages?
This problem usually occurs when you do not add the trailing slash because then a redirect is done to the url containing a trailing slash

Related

Django csrf token not refreshed after first login

I have hosted a website at http://cognezic-dev.ap-south-1.elasticbeanstalk.com/login/. On closer inspection, the form has the same csrf token across page refreshes and browsers, which I suspect to be the cause of the issue,this works fine on the local django server.Dont know where this is being cached. I have added CSRF Middleware in the settings.py too.
You can use the test credentials as username bismeet and password bis12345 for testing.
I have also tried creating a custom middleware as follows:
from django.middleware.csrf import rotate_token, CsrfViewMiddleware
from django.utils.deprecation import MiddlewareMixin
class CSRFRefresh(CsrfViewMiddleware,MiddlewareMixin):
def process_response(self, request, response):
print("Custom MiddleWare called")
rotate_token(request)
return response
But it still fails.
My settings.py with custom middleware contains:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'solvesto.middleware.csrf_refresh.CSRFRefresh'
]
If not using the custom middleware,I use:
'django.middleware.csrf.CsrfViewMiddleware'
instead of
'solvesto.middleware.csrf_refresh.CSRFRefresh'
The only last resort I see to make this work is to remove csrf altogether,which is of course,bad for security.
I removed the csrf security,no other solution,works now.

Delete header in django rest framework response

I'm trying to delete Server header from django rest framework response, but I didn't find an easy way, so I create a middleware to delete it.
This is my first try:
middleware.py
class RemoveHeaders(object):
def process_response(self, request, response):
response['Server'] = ''
return response
This middleware works ok, but the problem is that it fills server header with empty string and not delete it. so I tried the next:
class RemoveHeaders(object):
def process_response(self, request, response):
del response['Server']
return response
But It doesn't work. server header continues.
How can I delete server header?, or do you know another alternative?
thanks
Updated, these are my middlewares, maybe someone is override server header, case it doesn't exist?
MIDDLEWARE_CLASSES = (
'corsheaders.middleware.CorsMiddleware',
'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',
'django.middleware.security.SecurityMiddleware',
'my_api.middleware.RemoveHeaders'
)
I just had the exact same problem. Your approach with
del response['Server']
Is correct!
However, you need to move your middleware to be the first. As other middlewares will add headers after the response is constructed, so the order of application is bottom-up. Your middleware has to be the first one to have the "last word".

middleware does an infinite redirect

I've already read this but the answer doesnt fit my needs.
I've made this very simple middleware:
class RedirectIfUserIsNotActiveMiddleware(object):
"""
Middleware to redirect if account is disabled
"""
#staticmethod
def process_request(request):
if not request.user.is_active:
try:
# test to see if not already on the right url:
a = resolve(request.path)
if a.url_name != settings.URL_REDIRECT_USER_NOT_ACTIVE:
return HttpResponseRedirect(
reverse_lazy(settings.URL_REDIRECT_USER_NOT_ACTIVE))
# request.path do a 404 if URL unknown -> do nothing :
except Resolver404:
pass
And I've added this here:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'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',
'django.middleware.security.SecurityMiddleware',
'third_party.hqf_middleware.RedirectIfUserIsNotActiveMiddleware',
)
But when the account is disabled I get an infinite loop with the message on the webbrowser: "mywebsite.com redirected you too many times.".
In my settings I have this:
URL_REDIRECT_USER_NOT_ACTIVE = 'my_home_profile_account_desactivated'
And the URL I'm trying to get is always (even each time step by step) /en/my-home/profile/edit
What am I missing?
It looks as if the my_home_profile_account_desactivated view is redirecting to your login page, and then the middleware redirects back to my_home_profile_account_desactivated, creating a redirect loop.
You should be able to break the authentication loop by changing the middleware so that you only redirect users that are authenticated and inactive.
#staticmethod
def process_request(request):
if request.user.is_authenticated() and not request.user.is_active:
...

Exclude middleware from caching

I have very simple middleware that track numbers of "hits" of an object.
class HitCount():
def process_view(self, request, view_func, view_args, view_kwargs):
if request.resolver_match.url_name == 'article_view':
try:
Article.objects.filter(slug=view_kwargs['slug']).update(hit_count=F('hit_count')+1)
except:
pass
The problem is, it doesn't work properly when "per-site" cache is enabled.
"hit_count" field (PositiveIntegerField) is updated only once per 5 minutes (cache timeout 300s), no matter how many times page was visited during that "5 minutes".
It doesnt have to be accurate, beacuse "hit_count" field isn't even displayed on front side. I need it only, to order articles via popularity. But "5 minutes measurement error" is too much.
How can I exclude that middleware from caching? Do I need to disable cache for whole view?
settings file, I tried to change middleware order, but no effect.
MIDDLEWARE_CLASSES = (
'django.middleware.cache.UpdateCacheMiddleware',
'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',
'django.middleware.security.SecurityMiddleware',
'blog.middleware.HitCount',
'django.middleware.cache.FetchFromCacheMiddleware',
)
view
class ArticleDetailView(DetailView):
queryset = Article.objects.published()
template_name = 'article.html'
The FetchFromCache middleware is fetching the page from the cache during process_request.
That means that the process_view middleware is never called.
You could try changing your middleware to override process_request instead. However, that might be tricky, because you won't have access to request.resolver_match.

WSGIRequest object has no attribute user on middleware function

I have the following middleware function:
class LastVisitMiddleware(object):
def process_response(self, request, response):
if request.user.is_authenticated():
customer = get_customer(request)
Customer.objects.filter(pk=customer.pk).update(last_visit=now())
return response
My middleware entries look like this:
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'my.middleware.LastVisitMiddleware',
)
My url looks like:
url(r'^dashboard/$', views.dashboard, name='dashboard'),
When I go to urls that have a forward slash the page loads normally. When I omit the forward slash I get the error:
WSGIRequest object has no attribute user
When I remove the middleware I have no issues whether I use the forward slash or not.
How can I prevent from throwing this error with or without a forward slash?
I know that Django redirects any urls without the trailing /, so /home to /home/, but I am not sure when Django does this redirection (apparently after it has run the middleware?). One way to get around this is to check if the user object has been set;
if hasattr(request, 'user') and request.user.is_authenticated():
This should fix your problem.
During the response phases (process_response() and process_exception() middleware), the classes are applied in reverse order, from the bottom up
similar question:
Django: WSGIRequest' object has no attribute 'user' on some pages?