如何使 webapp2 的尾部斜杠成为可选?

发布于 2024-12-26 13:10:59 字数 255 浏览 5 评论 0原文

我正在使用新的 webapp2(现在是 1.6 中的默认 webapp),并且我无法弄清楚如何在这样的代码中使尾随斜杠可选:

webapp.Route('/feed', handler = feed)

我尝试过 /feed/?< /code>、/feed/*/feed\/*/feed\/?,都无济于事。

I'm using the new webapp2 (now the default webapp in 1.6), and I haven't been able to figure out how to make the trailing slash optional in code like this:

webapp.Route('/feed', handler = feed)

I've tried /feed/?, /feed/*, /feed\/* and /feed\/?, all to no avail.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

甜中书 2025-01-02 13:10:59

为了避免在同一页面创建重复的 URL:,您应该使用将 strict_slash 设置为 True 的 RedirectRoute 自动将 /feed/ 重定向到 /feed,如下所示:

from webapp2_extras.routes import RedirectRoute

route = RedirectRoute('/feed', handler=feed, strict_slash=True)

阅读更多信息 http://webapp2.readthedocs.io/en/latest/api/webapp2_extras/routes.html

To avoid creating duplicate URL:s to the same page, you should use a RedirectRoute with strict_slash set to True to automatically redirect /feed/ to /feed, like this:

from webapp2_extras.routes import RedirectRoute

route = RedirectRoute('/feed', handler=feed, strict_slash=True)

Read more at http://webapp2.readthedocs.io/en/latest/api/webapp2_extras/routes.html

罗罗贝儿 2025-01-02 13:10:59

我不喜欢 RedirectRoute 类,因为它会导致不必要的 HTTP 重定向
根据 webapp2 Route 类 的文档,这里是在此 webapp2.Route with optionalleading part 线程中有更详细的答案。

简短回答

我的路由模式适用于以下 URL。

  1. //
  2. feed
  3. /feed/
  4. /feed/create
  5. /feed/create/
  6. /feed/edit/{entity_id}
SITE_URLS = [
    webapp2.Route(r'/', handler=HomePageHandler, name='route-home'),

    webapp2.Route(r'/feed/<:(create/?)|edit/><entity_id:(\d*)>',
        handler=MyFeedHandler,
        name='route-entity-create-or-edit'),

    webapp2.SimpleRoute(r'/feed/?',
        handler=MyFeedListHandler,
        name='route-entity-list'),
]

希望有帮助:-)

I don't like the RedirectRoute class because it causes an unnecessary HTTP Redirect.
Based on the documentation for webapp2 Route class, here is a more detailed answer in this webapp2.Route with optional leading part thread.

Short Answer

My route patterns works for the following URLs.

  1. /
  2. /feed
  3. /feed/
  4. /feed/create
  5. /feed/create/
  6. /feed/edit/{entity_id}
SITE_URLS = [
    webapp2.Route(r'/', handler=HomePageHandler, name='route-home'),

    webapp2.Route(r'/feed/<:(create/?)|edit/><entity_id:(\d*)>',
        handler=MyFeedHandler,
        name='route-entity-create-or-edit'),

    webapp2.SimpleRoute(r'/feed/?',
        handler=MyFeedListHandler,
        name='route-entity-list'),
]

Hope it helps :-)

南风起 2025-01-02 13:10:59

这是我处理这些路线的方法。

from webapp2 import Route
from webapp2_extras.routes import PathPrefixRoute
import handlers

urls = [
  Route('/foo<:/?>', handlers.Foo),
  Route('/bars', handlers.BarList),
  PathPrefixRoute('/bar', [
    Route('/', handlers.BarList),
    Route('/<bar_id:\w+><:/?>', handlers.Bar),
  ]),
]
...

需要注意的是,您的处理程序需要定义 *args**kwargs 来处理潜在的尾部斜杠,使用此方法将其作为参数发送给它们。

class Bar(webapp2.RequestHandler):

  def get(bar_id, *args, **kwargs):
    # Lookup and render this Bar using bar_id.
    ...

Here's how I handle these routes.

from webapp2 import Route
from webapp2_extras.routes import PathPrefixRoute
import handlers

urls = [
  Route('/foo<:/?>', handlers.Foo),
  Route('/bars', handlers.BarList),
  PathPrefixRoute('/bar', [
    Route('/', handlers.BarList),
    Route('/<bar_id:\w+><:/?>', handlers.Bar),
  ]),
]
...

It's important to note that your handlers will need to define *args and **kwargs to deal with the potential trailing slash, which gets sent to them as an argument using this method.

class Bar(webapp2.RequestHandler):

  def get(bar_id, *args, **kwargs):
    # Lookup and render this Bar using bar_id.
    ...
む无字情书 2025-01-02 13:10:59

webapp2.Route 模板不是正则表达式,您的值正在使用 re.escape 进行转义。您可以使用提供正则表达式模板的旧样式规则:

 webapp2.SimpleRoute('^/feed/?
, handler = feed)

webapp2.Route template is not a regular expressions and your value is being escaped with re.escape. You can use old style rules which provides regular expression templates:

 webapp2.SimpleRoute('^/feed/?
, handler = feed)
野鹿林 2025-01-02 13:10:59

这对我有用并且非常简单。它使用 webapp2 Route class。此示例中的尾部斜杠是可选的,没有重定向:

webapp2.Route('/your_url<:/?>', PageHandler)

V 形之间的冒号之后的所有内容都被视为正则表达式:<:regex>

This works for me and is very simple. It uses the template format for URI routing in the webapp2 Route class. Trailing slash in this example is optional with no redirection:

webapp2.Route('/your_url<:/?>', PageHandler)

Everything after the colon between the chevrons is considered to be a regex: <:regex>

谁的新欢旧爱 2025-01-02 13:10:59

如果您不想使用重定向(而且您可能不想),您可以重写 Route.match()

from webapp2 import Route, _get_route_variables
import urllib
from webob import exc


class SloppyRoute(Route):
    """
    A route with optional trailing slash.
    """
    def __init__(self, *args, **kwargs):
        super(SloppyRoute, self).__init__(*args, **kwargs)

    def match(self, request):
        path = urllib.unquote(request.path)
        match = self.regex.match(path)
        try:
            if not match and not path.endswith('/'):
                match = self.regex.match(path + '/')
        except:
            pass
        if not match or self.schemes and request.scheme not in self.schemes:
            return None

        if self.methods and request.method not in self.methods:
            # This will be caught by the router, so routes with different
            # methods can be tried.
            raise exc.HTTPMethodNotAllowed()

        args, kwargs = _get_route_variables(match, self.defaults.copy())
        return self, args, kwargs

If you don't want to use redirects (and you probably don't), you can override Route.match():

from webapp2 import Route, _get_route_variables
import urllib
from webob import exc


class SloppyRoute(Route):
    """
    A route with optional trailing slash.
    """
    def __init__(self, *args, **kwargs):
        super(SloppyRoute, self).__init__(*args, **kwargs)

    def match(self, request):
        path = urllib.unquote(request.path)
        match = self.regex.match(path)
        try:
            if not match and not path.endswith('/'):
                match = self.regex.match(path + '/')
        except:
            pass
        if not match or self.schemes and request.scheme not in self.schemes:
            return None

        if self.methods and request.method not in self.methods:
            # This will be caught by the router, so routes with different
            # methods can be tried.
            raise exc.HTTPMethodNotAllowed()

        args, kwargs = _get_route_variables(match, self.defaults.copy())
        return self, args, kwargs
故人如初 2025-01-02 13:10:59

我正在寻找一种方法,使 PathPrefixRoute 块根部的尾部斜杠可选。

如果有,请说:

from webapp2_extras.routes import RedirectRoute, PathPrefixRoute

from webapp2 import Route

app = webapp2.WSGIApplication([
  PathPrefixRoute('admin', [
      RedirectRoute('/', handler='DashboardHandler', name='admin-dashboard', strict_slash=True),
      RedirectRoute('/sample-page/', handler='SamplePageHandler', name='sample-page', strict_slash=True),
  ]),
])

您将能够访问 /admin/,但不能访问 /admin

由于我找不到更好的解决方案,因此我将 redirect_to_name 添加到了额外的路由中,例如:

from webapp2_extras.routes import RedirectRoute, PathPrefixRoute

from webapp2 import Route

app = webapp2.WSGIApplication([
  Route('admin', handler='DashboardHandler', name='admin-dashboard'),
  PathPrefixRoute('admin', [
      RedirectRoute('/', redirect_to_name='admin-dashboard'),
      RedirectRoute('/sample-page/', handler='SamplePageHandler', name='sample-page', strict_slash=True),
  ]),
])

我对解决此问题的更好解决方案感兴趣。

我应该采用 Stun 的解决方案而不使用 RedirectRoute 吗?

I was looking for a way to make the trailling slash on the root of a PathPrefixRoute block optional.

If you have, say:

from webapp2_extras.routes import RedirectRoute, PathPrefixRoute

from webapp2 import Route

app = webapp2.WSGIApplication([
  PathPrefixRoute('admin', [
      RedirectRoute('/', handler='DashboardHandler', name='admin-dashboard', strict_slash=True),
      RedirectRoute('/sample-page/', handler='SamplePageHandler', name='sample-page', strict_slash=True),
  ]),
])

You will be able to access /admin/, but not /admin.

Since I couldn't find any better solution, I've added a redirect_to_name to an extra route, like:

from webapp2_extras.routes import RedirectRoute, PathPrefixRoute

from webapp2 import Route

app = webapp2.WSGIApplication([
  Route('admin', handler='DashboardHandler', name='admin-dashboard'),
  PathPrefixRoute('admin', [
      RedirectRoute('/', redirect_to_name='admin-dashboard'),
      RedirectRoute('/sample-page/', handler='SamplePageHandler', name='sample-page', strict_slash=True),
  ]),
])

I'm interested in better solutions to this problem.

Should I go for Stun's solution and simply not use RedirectRoute?

拔了角的鹿 2025-01-02 13:10:59

我想出了一种古怪的方法。我定义了以下类:

class UrlConf(object):

    def __init__(self, *args, **kwargs):
        self.confs = []
        for arg in args:
            if isinstance(arg, webapp2.Route):
                slash_route = webapp2.Route(arg.template + '/', arg.handler)
                self.confs += [arg, slash_route]

    def __iter__(self):
        for route in self.confs:
            yield route

然后我设置了如下所示的路线:

MIRROR_URLS = list(UrlConf(
    Route('/path/to/stuff', handler=StuffHandler, name='stuff.page'),
    Route('/path/to/more/stuff', handler= MoreStuffHandler, name='more.stuff.page')
))

如果您确实选择走这条路线,那么显然您可以对其进行改进,使其与其他类型的 BaseRoute 对象更加灵活。

I came up with a sort of hacky way. I define the following class:

class UrlConf(object):

    def __init__(self, *args, **kwargs):
        self.confs = []
        for arg in args:
            if isinstance(arg, webapp2.Route):
                slash_route = webapp2.Route(arg.template + '/', arg.handler)
                self.confs += [arg, slash_route]

    def __iter__(self):
        for route in self.confs:
            yield route

Then I set up my routes like the following:

MIRROR_URLS = list(UrlConf(
    Route('/path/to/stuff', handler=StuffHandler, name='stuff.page'),
    Route('/path/to/more/stuff', handler= MoreStuffHandler, name='more.stuff.page')
))

If you do choose to go this route, you can obviously improve upon it to be more flexible with other types of BaseRoute objects.

左秋 2025-01-02 13:10:59

我对 webapp2 不熟悉,但如果第一个参数是正则表达式,请尝试:

/feed(/)?

I am not familiar with webapp2, but if the first parameter is a regular expression, try:

/feed(/)?
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文