一个处理程序能否处理龙卷风中的帖子并获得不同的URL

时间:2019-11-06 14:20:14

标签: python tornado

一个处理程序可以在龙卷风中处理发布和获取请求(URL稍有不同)吗?

例如,我想要拥有:

  • undefined使用请求中的数据创建新用户 身体
  • /app/user (POST)返回具有给定ID的用户

目前,我有两个处理程序/app/user/<user_id> (GET)GetUser和两条路由。

2 个答案:

答案 0 :(得分:1)

是的,您可以执行此操作,但是到目前为止,我所见过的所有快速解决方案在处理位置参数时总是会有一些不便之处。看一下这个例子:

import tornado.ioloop
import tornado.web

class UserHandler(tornado.web.RequestHandler):
    def get(self, __):
        self.write("Get request")

    def post(self, user_id):
        self.write(f"Post request for user id {user_id}")

app = tornado.web.Application([
    (r"/app/user/?(\d+)?", UserHandler),
])

app.listen(8000)
tornado.ioloop.IOLoop.current().start()

这将建立一个匹配两个URL模式并分配UserHandler的路由规则。 URL中的捕获组是可选的,因此当POST请求发送到None时,user_id可能作为/app/user传递。使用这种方法,龙卷风将始终使用正则表达式中第二组的参数调用get方法。根据您的项目,您可能需要进行更广泛的错误检查(检查给定的参数,如果不是None,则发送405 Method Not Allowed或适合您情况的任何方法-也许您想要允许一个用户使用GET?)


也可以通过使用同一处理程序添加两个规则来做到这一点:

import tornado.ioloop
import tornado.web

class UserHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Get request")

    def post(self, user_id):
        self.write(f"Post request for user id {user_id}")

app = tornado.web.Application([
    (r"/app/user", UserHandler),
    (r"/app/user/(\d+)", UserHandler),
])
app.listen(8000)
tornado.ioloop.IOLoop.current().start()

请记住,龙卷风的POST和GET请求都将匹配这两个路线,这带来了不便:

  • 如果有人向/app/user发送POST请求,则会抛出TypeError: post() missing 1 required positional argument: 'user_id'
  • 如果有人向/app/user/123发送GET请求,则会抛出TypeError: get() takes 1 positional argument but 2 were given

您可以解决这些问题,但是我认为第一种解决方案可以更简洁地解决此问题。


编辑:当然,您还可以实现自己的Matcher类,该类不仅可以通过子类化tornado.routing.PathMatches来区分URL,而且可以区分请求方法-尽管这是一些代码。这里的主要缺点是对于有效的路由,服务器将在应为405s的位置返回404响应(因为路由/“资源”本身是有效的,所以方法错误)

import tornado.ioloop
import tornado.web
import tornado.routing

class MethodAndPathMatch(tornado.routing.PathMatches):
    def __init__(self, method, path_pattern):
        super().__init__(path_pattern)
        self.method = method

    def match(self, request):
        if request.method != self.method:
            return None

        return super().match(request)

class UserHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Get request")

    def post(self, user_id):
        self.write(f"Post request for user id {user_id}")

app = tornado.web.Application([
    (MethodAndPathMatch("GET", r"/app/user"), UserHandler),
    (MethodAndPathMatch("POST", r"/app/user/(\d+)"), UserHandler),
])

app.listen(8000)
tornado.ioloop.IOLoop.current().start()

cURL进行测试:

$ curl -w '\n' -X POST localhost:8000/app/user
$ curl -w '\n' -X POST localhost:8000/app/user/123
$ curl -w '\n' -X GET localhost:8000/app/user
$ curl -w '\n' -X GET localhost:8000/app/user/123

答案 1 :(得分:-1)

简单

def options(self):
    return
get=head=post=delete=patch=put=options