如何在龙卷风中删除请求?

How to drop request in tornado?

为了测试我的客户端,我想让我的客户端发送的一些HTTP请求没有得到任何响应。

例如,我希望每个请求都应该有 cookie topsession,如果没有,则没有响应。

class EchoHandler(tornado.web.RequestHandler):
    def get(self):
        if not self.get_cookie("topsession"):
            ###TODO
        else:
            self.write("0")

asynchronous 装饰你的方法,永远不要调用 finish:

class EchoHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get(self):
        if not self.get_cookie("topsession"):
            pass
        else:
            self.finish("0")

作为 docs for asynchronous say:

If this decorator is given, the response is not finished when the method returns. It is up to the request handler to call self.finish() to finish the HTTP request.

因此,如果您只是 return 而没有调用 finish,则客户端将永远等待(或直到其客户端套接字超时)没有收到响应的响应。但是,如果这样做,则必须在 if 语句的另一个分支中调用 finish

另一方面,如果 "no response" 你的意思是错误,你可以这样做:

class EchoHandler(tornado.web.RequestHandler):
    def get(self):
        if not self.get_cookie("topsession"):
            raise tornado.web.HTTPError(401)  # Unauthorized.
        else:
            self.write("0")

可以显式关闭请求的底层连接

import tornado.ioloop
import tornado.web
from tornado.gen import coroutine

class MainHandler(tornado.web.RequestHandler):

    @coroutine
    def get(self):
        self.request.connection.close()

if __name__ == "__main__":
    application = tornado.web.Application([
        (r"/", MainHandler),
    ])
    application.listen(8888)
    tornado.ioloop.IOLoop.current().start()

并使用 curl 进行测试:

curl http://localhost:8888/ -v
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8888 (#0)
> GET / HTTP/1.1
> Host: localhost:8888
> User-Agent: curl/7.47.0
> Accept: */*
> 
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server

上面的代码关闭了与 FIN-flow 的连接并将响应留空。如果您需要通过重置 - RST 断开连接,您可以强制执行。只需为连接的套接字设置 SO_LINGER 。您可以将 api 视为 public,因为没有 _,但是......它是 Tornado 的内部内容(依赖于实现)。

import socket
import struct
import tornado.ioloop
import tornado.web
from tornado.gen import coroutine

class MainHandler(tornado.web.RequestHandler):

    @coroutine
    def get(self):
        s = self.request.connection.stream.socket
        l_onoff = 1
        l_linger = 0
        s.setsockopt(
            socket.SOL_SOCKET, socket.SO_LINGER,
            struct.pack('ii', l_onoff, l_linger)
        )
        self.request.connection.close()

if __name__ == "__main__":
    application = tornado.web.Application([
        (r"/", MainHandler),
    ])
    application.listen(8888)
    tornado.ioloop.IOLoop.current().start()