检查URL状态而不打开它

时间:2019-08-22 10:17:06

标签: django redirect middleware dispatch

现在,当打开url时(不带斜杠-example.com/blog),将在末尾自动添加一个斜杠(存在301重定向)。问题是,我能以某种方式做到这一点,以便首先检查该页面是否存在(不带斜杠-example.com/blog)。如果是这样,请打开它。如果不是,则检查页面是否存在斜线(仅不包含301-example.com/blog/)。如果是这样,则重定向301,否则,则重定向404

现在,即使没有页面(example.com/blog),也将在第一个末尾添加斜杠(example.com/blog/),301重定向go,然后只有{{1}引发错误。在这种情况下,必须立即抛出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) 的方向。

enter image description here

已更新

projects.urls

middleware

pages.urls

url(r'^page/', include('pages.urls')),

测试

url(r'^$', PageView.as_view(), name='page'),

我尝试过try: resolve('/page/') except: raise Http404 return redirect('/page/')

2 个答案:

答案 0 :(得分:2)

首先请确保在settings.py中将APPEND_SLASH设置为False。这将禁用自动301重定向到带有斜杠的URL。

然后使用resolve()来检查重定向前是否存在带有斜杠的URL。在处理response状态码为404的情况的Middleware类中执行此操作。

from django.urls import resolve

try:
    resolve(url_with_slash)
except Resolver404:
    raise Http404
return redirect(url_with_slash)

请注意,如果路径与resolve(url)相匹配,则url不会引发异常,即使视图之后可能仍会引发404。例如,如果您有一个{ {1}}用于对象的pk在URL中的对象。假设您有 / objects / DetailView / 作为显示对象的路径,然后是URL / objects / 4 / 也将始终匹配。重定向后,视图仍会显示404。

因此,如果您确实还想捕获那些404,则可以实际调用视图函数来检查响应:

<pk>

答案 1 :(得分:2)

  1. 您需要从RedirectMixinView中删除LandingView
  2. 注释中间件 CommonMiddleware
  3. RedirectMiddleware添加到中间件的列表(最好在顶部)。
  4. 创建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

  1. 添加到项目的 ngnx配置
    if ($request_uri ~* "\/\/") {
        rewrite ^/(.*)      $scheme://$host/$1    permanent;
    }
    # merge_slashes off;

它可以满足您的需要,并且如果存在此页面,也可以删除重复的斜杠。