在不打开的情况下检查 url 状态
Check url status without opening it
现在当 url 打开时(没有斜线 - example.com/blog
),斜线会自动添加到末尾(有 301
重定向)。问题是,我能否以某种方式执行此操作,以便首先检查该页面是否存在(没有斜杠 - example.com/blog
)。如果是这样,请打开它。如果没有,则检查页面是否存在带斜杠的(只有不带301
- example.com/blog/
)。如果是,则重定向 301
,如果不是,则抛出 404
.
现在如果没有页面(example.com/blog
),那么先在末尾添加一个斜线(example.com/blog/
),301
重定向去然后才一个404
抛出错误。在这种情况下,必须立即抛出 404
错误,而无需 301
重定向。
将dispatch
改写如下。
def is_normal_slash_count(url):
temp_url = url
slash_count = 0
while temp_url.endswith('/'):
slash_count += 1
temp_url = temp_url[:-1]
return (slash_count == 1, slash_count)
def replace_bad_slash(url, slash_count):
if slash_count == 2:
return url.replace('//', '/')
return url.replace('/'*(slash_count-1), '')
def normalize_url(url):
if len(url) > 1:
if not url.endswith('/'):
return url + '/'
# replace the url like /contacts//// to /contacts/
good_slash, slash_count = is_normal_slash_count(url)
if not good_slash:
url = replace_bad_slash(url, slash_count)
return url
def is_bad_url(url):
if len(url) > 1:
good_slash, slash_count = is_normal_slash_count(url)
if not good_slash:
return True
return False
class RedirectMixinView:
def dispatch(self, *args, **kwargs):
url = self.request.path
redirect_setting = RedirectSettings.objects.filter(url_from=url).first()
if redirect_setting:
return redirect(redirect_setting.url_to, permanent=True)
if is_bad_url(url):
return redirect(normalize_url(url), permanent=True)
return super(RedirectMixinView, self).dispatch(*args, **kwargs)
这现实吗?
我想写middleware
的方向。
已更新
projects.urls
url(r'^page/', include('pages.urls')),
pages.urls
url(r'^$', PageView.as_view(), name='page'),
测试
try:
resolve('/page/')
except:
raise Http404
return redirect('/page/')
我试过了/page/, /page, page/, page, http://127.0.0.1:8000/page/, http://127.0.0.1:8000/page
首先确保在 settings.py 中将 APPEND_SLASH
设置为 False
。这将禁用自动 301 重定向到带有斜杠的 URLs。
然后在重定向前用resolve()
检查带斜线的URL是否存在。在处理 response
状态码为 404 的情况的中间件 class 中执行此操作。
from django.urls import resolve
try:
resolve(url_with_slash)
except Resolver404:
raise Http404
return redirect(url_with_slash)
请注意,当存在与 url
匹配的路径时,resolve(url)
不会引发异常,即使该视图之后可能仍会引发 404。例如,如果您有a DetailView
表示对象的 pk 在 URL 中。假设您将 /objects/<pk>
/ 作为显示对象的路径,那么 url /objects/4/ 将始终匹配,即使 pk=4 的对象不存在。重定向后视图仍会引发 404。
所以如果你真的想同时捕获那些 404,你实际上可以自己调用视图函数来检查响应:
try:
r = resolve(url_with_slash)
response = r.func(request, args=r.args, kwargs=r.kwargs)
if response.status_code == 200:
return redirect(url_with_slash)
except Resolver404:
pass
- 您需要从
LandingView
中删除 RedirectMixinView
。
- 注释掉中间件
CommonMiddleware
.
- 将
RedirectMiddleware
添加到 中间件列表 (最好在顶部)。
- 创建
RedirectMiddleware
代码是与@dirkgroten共同编写的(他的大部分贡献)。
import re
from django.http import HttpResponsePermanentRedirect
class RedirectMiddleware(object):
response_redirect_class = HttpResponsePermanentRedirect
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
path = re.sub("/+", "/", request.path)
if response.status_code == 404:
if not path.endswith('/'):
request.path = path # to force using the cleaned path
else:
request.path = path[:-1] # to force using the cleaned path
try:
full_path = request.get_full_path(force_append_slash=True) # add the slash, keeping query parameters
r = resolve(full_path)
new_response = r.func(request, args=r.args, kwargs=r.kwargs)
if new_response.status_code == 200:
return redirect(full_path)
except Resolver404:
pass # this will fall through to `return response`
# Add the Content-Length header to non-streaming responses if not
# already set.
if not response.streaming and not response.has_header('Content-Length'):
response['Content-Length'] = str(len(response.content))
return response
- 添加到项目的 ngnx 配置
if ($request_uri ~* "\/\/") {
rewrite ^/(.*) $scheme://$host/ permanent;
}
# merge_slashes off;
它可以满足您的需要,而且 如果此页面存在,还会删除重复的斜杠。
现在当 url 打开时(没有斜线 - example.com/blog
),斜线会自动添加到末尾(有 301
重定向)。问题是,我能否以某种方式执行此操作,以便首先检查该页面是否存在(没有斜杠 - example.com/blog
)。如果是这样,请打开它。如果没有,则检查页面是否存在带斜杠的(只有不带301
- example.com/blog/
)。如果是,则重定向 301
,如果不是,则抛出 404
.
现在如果没有页面(example.com/blog
),那么先在末尾添加一个斜线(example.com/blog/
),301
重定向去然后才一个404
抛出错误。在这种情况下,必须立即抛出 404
错误,而无需 301
重定向。
将dispatch
改写如下。
def is_normal_slash_count(url):
temp_url = url
slash_count = 0
while temp_url.endswith('/'):
slash_count += 1
temp_url = temp_url[:-1]
return (slash_count == 1, slash_count)
def replace_bad_slash(url, slash_count):
if slash_count == 2:
return url.replace('//', '/')
return url.replace('/'*(slash_count-1), '')
def normalize_url(url):
if len(url) > 1:
if not url.endswith('/'):
return url + '/'
# replace the url like /contacts//// to /contacts/
good_slash, slash_count = is_normal_slash_count(url)
if not good_slash:
url = replace_bad_slash(url, slash_count)
return url
def is_bad_url(url):
if len(url) > 1:
good_slash, slash_count = is_normal_slash_count(url)
if not good_slash:
return True
return False
class RedirectMixinView:
def dispatch(self, *args, **kwargs):
url = self.request.path
redirect_setting = RedirectSettings.objects.filter(url_from=url).first()
if redirect_setting:
return redirect(redirect_setting.url_to, permanent=True)
if is_bad_url(url):
return redirect(normalize_url(url), permanent=True)
return super(RedirectMixinView, self).dispatch(*args, **kwargs)
这现实吗?
我想写middleware
的方向。
已更新
projects.urls
url(r'^page/', include('pages.urls')),
pages.urls
url(r'^$', PageView.as_view(), name='page'),
测试
try:
resolve('/page/')
except:
raise Http404
return redirect('/page/')
我试过了/page/, /page, page/, page, http://127.0.0.1:8000/page/, http://127.0.0.1:8000/page
首先确保在 settings.py 中将 APPEND_SLASH
设置为 False
。这将禁用自动 301 重定向到带有斜杠的 URLs。
然后在重定向前用resolve()
检查带斜线的URL是否存在。在处理 response
状态码为 404 的情况的中间件 class 中执行此操作。
from django.urls import resolve
try:
resolve(url_with_slash)
except Resolver404:
raise Http404
return redirect(url_with_slash)
请注意,当存在与 url
匹配的路径时,resolve(url)
不会引发异常,即使该视图之后可能仍会引发 404。例如,如果您有a DetailView
表示对象的 pk 在 URL 中。假设您将 /objects/<pk>
/ 作为显示对象的路径,那么 url /objects/4/ 将始终匹配,即使 pk=4 的对象不存在。重定向后视图仍会引发 404。
所以如果你真的想同时捕获那些 404,你实际上可以自己调用视图函数来检查响应:
try:
r = resolve(url_with_slash)
response = r.func(request, args=r.args, kwargs=r.kwargs)
if response.status_code == 200:
return redirect(url_with_slash)
except Resolver404:
pass
- 您需要从
LandingView
中删除RedirectMixinView
。 - 注释掉中间件
CommonMiddleware
. - 将
RedirectMiddleware
添加到 中间件列表 (最好在顶部)。 - 创建
RedirectMiddleware
代码是与@dirkgroten共同编写的(他的大部分贡献)。
import re
from django.http import HttpResponsePermanentRedirect
class RedirectMiddleware(object):
response_redirect_class = HttpResponsePermanentRedirect
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
path = re.sub("/+", "/", request.path)
if response.status_code == 404:
if not path.endswith('/'):
request.path = path # to force using the cleaned path
else:
request.path = path[:-1] # to force using the cleaned path
try:
full_path = request.get_full_path(force_append_slash=True) # add the slash, keeping query parameters
r = resolve(full_path)
new_response = r.func(request, args=r.args, kwargs=r.kwargs)
if new_response.status_code == 200:
return redirect(full_path)
except Resolver404:
pass # this will fall through to `return response`
# Add the Content-Length header to non-streaming responses if not
# already set.
if not response.streaming and not response.has_header('Content-Length'):
response['Content-Length'] = str(len(response.content))
return response
- 添加到项目的 ngnx 配置
if ($request_uri ~* "\/\/") {
rewrite ^/(.*) $scheme://$host/ permanent;
}
# merge_slashes off;
它可以满足您的需要,而且 如果此页面存在,还会删除重复的斜杠。