apache does not pass request to Django (404 not found) - django

I have a custom 404 page setup for the site, which works fine, like this:
when I hit mysite.com/fdsafsadfdsa which doesn't exist, the custom 404 page shows up.
However if I add a urlencoded '/' which is '%2f' at the end of url, mysite.com/fdsafsadfdsa%2f, and this gives me the apache 404 not found.
it looks like apache decided to handle this 404 itself instead of passing down to Django
Anybody has idea why this is happening?

Turns out it's a issue in Apache/Nginx. And somebody submit this issue to Django project before, see here: https://code.djangoproject.com/ticket/15718
and quote from the ticket, there's a workaround:
After investigation I've found that the 2nd issue (404 error directly from apache) is not related to django and can be avoided by adding "AllowEncodedSlashes On" into apache config. Unfortunately apache replaces %2f with / itself, so the behavior is exactly the same as in simple http server provided by django. In Apache 2.2.18 (which is not released yet, i guess), AllowEncodedSlashes allows value NoDecode. With the value NoDecode, such URLs are accepted, but encoded slashes are not decoded but left in their encoded state. Meanwhile I'm using the workaround
request_uri = force_unicode(environ.get('REQUEST_URI', u'/'))
if u'?' in request_uri:
path_info,query = request_uri.split('?',1)
else:
path_info,query = request_uri,''
instead of original
path_info = force_unicode(environ.get('PATH_INFO', u'/'))
in core/handlers/wsgi.py

Related

Access django url without apache http basic authentication

I'm working on a Django 3.2 project which is hosted using Apache 2.4 server. The user authentication in this project is handled using HTTP Basic Authentication configured using LDAP.
I have implemented a sign up feature for new users. For that I have created the necessary form, view, template and url pattern in the Django project. The urlpattern to visit the sign up form is /signup.
My goal is to make the sign up urlpattern accessible to anyone i.e. prevent the Basic Authentication from showing when the sign up urlpattern is requested by user in the browser.
JFI, the complete Apache configuration is already complete and works already.
To achieve this, I have used the "LocationMatch" directive in the Apache configuration within the VirtualHost directive:
...
<LocationMatch "^/signup$">
Require all granted
</LocationMatch>
...
With this the Basic Authentication is removed when /signup URI is requested, but the server always redirects to another url which ultimately requires authentication hence giving the basic auth pop-up.
$ curl -I https://*****.com/signup
HTTP/1.1 302 Found
...
I have tried to redirect the request explicitly to /signup whenever the is /signup. This ends up in an endless loop of redirections.
RewriteEngine on
...
RewriteRule ^/signup$ /signup [R=301,L]
I have also tried other ways by setting environment variables within Apache configuration, I have restarted Apache whenever a change was done in config, I have cleared browser cache etc., but nothing seems be working.
FYI, I can access the /signup url successfully after logging into the application which is not useful for me.
I'm afraid I cannot share the complete source (apache config, django source etc.) here as the project is not completely open source yet. But I'm sure your suggestions would surely help me in some way.
I want to fix the redirection. I have no clue what I'm missing out here.

website be opened with redirection from stranger domaine

my problem is:
I own a website developed with django framework and uploaded in heroku.
my domain is "OnlyMyDomain.com", but "StrangeDomaine.com" calls my website with a redirect. in other words when you go to StrangeDomaine.com, my website is opened even if the address change to OnlyMyDomain.com.
I tried in my settings.py:
DEBUG = False
ALLOWED_HOSTS = ['OnlyMyDomain.com']
Please can someone explain to me where the problem is coming from? and how can I avoid it?
There is no problem. It seems that you define a permanent redirection (301) from StrangeDomain.com to OnlyMyDomain.com. Then request url will be updated, then StrangeDomain.com becomes OnlyMyDomain.com. If you want to avoid that, just remove this redirection.
The HTTP response status code 301 Moved Permanently is used for
permanent URL redirection, meaning current links or records using the
URL that the response is received for should be updated. The new URL
should be provided in the Location field included with the response.
Wiki : HTTP 301

Django weird url call error

I have my Django app. I have a redirect URL(say a 404 page) to be redirected when no other URL matches. Now if any url is called as
mysite.com/something
I am redirected to the 404 page. But
mysite/something/
works fine.
The redirection url added to the end of all:
url(r'^.*/',theview),
When I remove the redirect url from the urls.py, the problem is cleared and the above URL works (without / at the end). Why is the error?
First of all, it would be a good idea to link to your previous post and mention you are using a hack that I gave you, because (A) it's not normal setup and (B) Someone might come up with a better idea than mine
Secondly, you're seeing this behaviour because of normal url processing. See, the urls mysite.com/something and mysite.com/something/ are not the same. To match it with django's urls, the difference would be:
url(r'^something/$')
url(r'^something$')
Since the difference is so minor, when using a normal setup, after failing to find the a url without a forward slash django's common middlewere* will automatically try to add one and test it. It's only then that it would give up and forward you to a 404 page.
However, in your setup, the catch-all url prevents the second round because it does apply to the url without the forward slash. My solution? Don't worry about it. The only reason you're using this hack is because Debug=True means a debug page instead of your custom 404 page, a problem you won't be facing when moving to a production environment
*and a big thanks to #Alasdair who pointed this out in the comments

Microsoft Azure appending extra query string to urls with query strings

In deploying a version of the Django website I'm working on to Microsoft's Azure service, I added a page which takes a query string like
http://<my_site_name>.azurewebsites.net/security/user/?username=<some_username>&password=<some_password>
However, I was getting 404 responses to this URL. So I turned on Django's Debug flag and the page I get returned said:
Page not found (404)
Request Method: GET
Request URL: http://<my_site_name>.azurewebsites.net/security/user/?username=<some_username>&password=<some_password>?username=<some_username>&password=<some_password>
Using the `URLconf` defined in `<my_project_name>.urls`, Django tried these URL patterns, in this order:
^$
^security/ ^user/$
^account/
^admin/
^api/
The current URL, `security/user/?username=<some_username>&password=<some_password>`, didn't match any of these.
So it seems to be appending the query string onto the end of the url that already has the same query string. I have the site running on my local machine and on an iis server on my internal network which I'm using for staging before pushing to Azure. Neither of these site deployments do this, so this seems to be something specific to Azure.
Is there something I need to set in the Azure website management interface to prevent it from modifying URLs with query strings? Is there something I'm doing wrong with regards to using query strings with Azure?
In speaking to the providers of wfastcgi.py they told me it may be an issue with wfastcgi.py that is causing this problem. While they look into it they gave me a work around that fixes the issue.
Download the latest copy of wfastcgi.py from http://pytools.codeplex.com/releases
In that file find this part of the code:
if 'HTTP_X_ORIGINAL_URL' in record.params:
# We've been re-written for shared FastCGI hosting, send the original URL as the PATH_INFO.
record.params['PATH_INFO'] = record.params['HTTP_X_ORIGINAL_URL']
And add right below it (still part of the if block):
# PATH_INFO is not supposed to include the query parameters, so remove them
record.params['PATH_INFO'] = record.params['PATH_INFO'].split('?')[0]
Then, upload/deploy this modified file to the Azure site (either use the ftp to put it somewhere or add it to your site deployment. I'm deploying it so that if I need to modify it further its versioned and backed up.
In the Azure management page for the site, go to the site's configure page and change the handler mapping to point to the modified wfastcgi.py file and save the configuration.
i.e. my handler used to be the default D:\python27\scripts\wfastcgi.py. Since I deployed my modified file, the handler path is now: D:\home\site\wwwroot\wfastcgi.py
I also restarted the site, but you may not have to.
This modified script should now strip the query string from PATH_INFO, and urls with query strings should work. I'll be using this until I hear from the wfastcgi.py devs that the default wfastcgi.py file in the Python27 install has been fixed/replaced.

Correct escaping of % in the URL with Apache

I have a Django project where I have a search page which takes input through a POST and redirect to /search/<search string>/ and this page renders the result. The percentage sign (%) is used as a wildcard in the search (tes%er returns testuser, tester, etc and the url looks like this then: example.com/search/tes%25er/) and everything works fine with the Django development server. If I manually write tes%er in the url it changes to tes%25er automatically.
Now I'm deploying on an Apache server with mod_wsgi and when my search page redirects to example.com/search/tes%er/ I get the server error: Bad Request. Your browser sent a request that this server could not understand.. If I manually add '25' to the url, like the encoded % sign so it looks like the development server it works fine.
Is there a way for Apache to automatically escape the %-sign and create a url that works, understand % unescaped or do I need to do ugly hacks in my search page that builds the url? (I'd rather not do ugly hacks like this cause then the users can't manually add % to the url and get it to work).
Edit: The code that sends the query from the search page to the search url.
if form.is_valid():
if 'search_user' in request.POST:
q = request.POST['search_user']
return redirect('/search/'+q)
As Ignacio already suggested, you should not redirect to an invalid url. So to answer your question:
you can (or perhaps its better to say 'should') not ask your Apache server to escape your url. The reason you escape your URL is because some characters have another meaning. For example, take a querystring:
somedomain.com/?key=value
If we would want to use a ? or a = in your value you would have a problem because your server would think that you are using operators of your querystring.
The same for the %-symbol. When your apache server sees a %-symbol he thinks he will find an enconded and will try to decode it. If your querystring is %20, apache will translate this to a space, while you meant "wildcard20".
In summary: apache decodes your string, so you dont want him to encode it.
But this does not solve your problem. You can solve your problem by changing your code into the following:
from urllib import urlencode
if form.is_valid():
if 'search_user' in request.POST:
q = request.POST['search_user']
return redirect('/search/?q='+urlencode(q))
In case you wonder: what if my user would type /search/?q=%; in that case he'ld have a problem for he has typed an invalid address.
Hope this helps :-).
Wout