Getting the flask's connection socket object from flask app itself is not possible as of now.
From what I've found on other questions on SO about flask's sockets, it seems we can set file descriptor of the socket for werkzeug.serving.BaseWSGIServer
.
Another problem is sending a socket reset in a pythonic way.
So, I was able to combine the answers of the linked questions into something like this, I went with the default werkzeug's wsgi server (the one used when app.run
is called).
import logging
import os
import socket
import socketserver
import struct
from flask import Flask, abort, request, session
from werkzeug.serving import BaseWSGIServer
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
app = Flask(__name__)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.set_inheritable(True)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
@app.route('/hello')
def hello():
return "Hello"
@app.route('/bye')
def bye():
return ""
if __name__ == "__main__":
try:
bind_to = ('127.0.0.1', 5000)
sock.bind(bind_to)
sock.listen()
sock_fd = sock.fileno()
logging.info("Sock FD is {}".format(sock_fd))
# calls Socket.dup on the sock_fd
# and passes the context into init of inherited
# HTTPServer, rendering the server and sock
# unpatchable afterwards
base_wsgi = BaseWSGIServer(
*bind_to, app, fd=sock_fd)
base_wsgi.serve_forever()
finally:
if not sock._closed:
msg = "Socket not closed, closing."
sock.close()
else:
msg = "Socket already closed."
logger.info(msg)
It might (or might not) be easier and completely possible to control the socket
& connection
with different wsgi backends like Gevent, Twisted web, ...
The result
Checking from wireshark, it now additionally sends RSTs after each request. So after the connection is naturally closed - FIN.
One issue is that the RST can't be controlled - this basically extends the socket with the SO_LINGER
options causing RSTs to be always sent when connections are closed. To allow selective RST sending, one would have to propagate the underlying connection
(created from the sock
) into the endpoint, then set the sockoptions on that connection and close it - which might also cause the underlying webserver to fail.