2013-01-31 37 views
1

有時,其他網站使用錯誤地編碼百分比URL來鏈接到我們的Django站點。 Disqus.com和Twitter.com也有同樣的問題,所以對我們的用例來說沒什麼特別的:http://disqus.com/%C3A4。在這個網址中,缺少了第二個%。有效的URL如下所示:http://disqus.com/%C3%A4在Django中錯誤地捕捉%編碼的URL以返回自定義的「錯誤400」頁面

Django返回一個空錯誤400(錯誤請求)頁面。但是,我們希望發現錯誤,而不是返回一個簡單的非信息頁面,我們希望向用戶顯示至少我們的自定義404頁面。甚至更好,我們希望檢查輸入URL上缺少的%字符或類似的東西來驗證其格式。 MiddleWare/process_request被我們目前的400錯誤調用,所以我們確實有一個鉤子來捕捉錯誤。

我們想在我們的網站上解決這個問題。有沒有最佳做法...? handler400會很棒 - 是否可以自己創建一個?

+0

爲什麼不通過攔截錯誤簡單地從前端代理重定向用戶? –

+0

您如何通過使用不需要編碼的乾淨URL來解決問題? –

+0

我不明白關於代理的想法。你能解釋一下嗎? ... Pixbay有20種語言可供選擇,並且(例如)中文和日文全部字符需要適當的UR編碼。我們最終的編碼工作非常順利。無論如何,術語「乾淨」並不完全正確,因爲%-encoding確實是處理URL內國際字符的正確方式。 –

回答

0

如在凱蒂的aswer那纔是真的好評論的形式已經發布,但在這種特殊情況下不工作,我在這裏發佈我們的電流,稍hackish的解決方案,另一種答案:

顯然,這個錯誤不能在Django的MiddleWares中重寫。這是一個UNICODE解碼錯誤,它在\ django \ core \ handlers \ wsgi.py中的WSGIHandler內部觸發。確切地說,這是導致問題的內部WSGIRequest,它是

path_info = force_unicode(environ.get('PATH_INFO', u'/')) 

。這基本上是Django的正確行爲,但正如我的問題所述,我們只是想向用戶展示一些比空的錯誤頁面更有用的東西。因此,我們在將有效的UNICODE字符傳遞給我們的WSGIHandler之前,檢查傳入的URL請求。本博客文章指出我們到正確的方向:http://codeinthehole.com/writing/django-nginx-wsgi-and-encoded-slashes/

因此,我們重新路由無效的網址,我們wsgi.py裏面,像這樣:

os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' 

import django.core.handlers.wsgi 
_application = django.core.handlers.wsgi.WSGIHandler() 

# for Django 1.7+ 
# from django.core.wsgi import get_wsgi_application 
# _application = get_wsgi_application() 

from django.utils.encoding import force_unicode 
def application(environ, start_response): 
    try: 
     path_info = force_unicode(environ.get('PATH_INFO', u'/')) 
    except: 
     environ['PATH_INFO'] = u'/' 
    return _application(environ, start_response) 

子類WSGHandler相反,還應該工作。在這個例子中,我們只是將無效的URL重定向到我們的網站根目錄「/」。但你也可以重定向到任何自定義的錯誤頁面URL,或者你可以嘗試清理你的URL ......它適用於我們,但也許有更好的解決方案。

1

在你的模板創建404.html那麼把它放進你的urls.py

#handle the errors  
from django.utils.functional import curry 
from django.views.defaults import * 

handler404 = curry(page_not_found, template_name='404.html') 

You can also handle other errors like this: 
handler500 = curry(server_error, template_name='500.html') 
handler403 = curry(permission_denied, template_name='403.html') 

處理任何類型的錯誤。你會在這裏得到一個想法。

https://github.com/Roejames12/django-error-pages 
+1

問題是:我們需要一個handler400,它在Django中不存在。 handler403,404和500確實存在,可以適當地使用...奇怪的是,我甚至無法看到,Django如何處理現有的處理程序,否則我會嘗試將它們複製並修改爲新的自定義處理程序......任何想法? –

+1

使用它可以處理任何類型的錯誤,https://github.com/Roejames12/django-error-pages – catherine

+1

謝謝cathy! +1爲偉大的提示。但是,Django的錯誤頁面不會收到此錯誤。與此同時,我們提出了一個有點難看的解決方案。這個錯誤在Django的WSGIHandler中引發。似乎沒有解決這個硬編碼行爲的鉤子。中間件被重寫,這就是爲什麼django-error-pages在這裏不起作用。基於以下腳本,我們現在通過繼承Django的WSGIHandler解決了這個問題:我們在無效URL到達處理程序之前修改了這些問題。 http://codeinthehole.com/writing/django-nginx-wsgi-and-encoded-slashes/ –