Как я могу установить тайм-аут в Python HTTPServer

У меня есть HTTP-сервер Python (2.7.13), работающий в Debian, я хочу остановить любой запрос GET, который занимает больше 10 секунд, но нигде не могу найти решение.

Я уже пробовал все фрагменты, опубликованные в следующем вопросе: Как реализовать Timeout в BaseHTTPServer.BaseHTTPRequestHandler Python

#!/usr/bin/env python
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import os

class handlr(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type','text-html')
        self.end_headers()
        self.wfile.write(os.popen('sleep 20 & echo "this took 20 seconds"').read())

def run():
    server_address = ('127.0.0.1', 8080)
    httpd = HTTPServer(server_address, handlr)
    httpd.serve_forever()

if __name__ == '__main__':
    run()

В качестве теста я запускаю команду оболочки, выполнение которой занимает 20 секунд, поэтому мне нужно, чтобы сервер остановился перед этим.


person Urias BT    schedule 24.01.2019    source источник


Ответы (1)


Поместите свою операцию в фоновый поток, а затем дождитесь завершения фонового потока. Не существует универсального безопасного способа прерывания потоков, поэтому эта реализация, к сожалению, оставляет функцию работающей в фоновом режиме, хотя она уже отказалась.

Если вы можете, вы можете рассмотреть возможность размещения прокси-сервера (например, nginx) перед вашим сервером и позволить ему обрабатывать тайм-ауты для вас, или, возможно, использовать более надежную реализацию HTTP-сервера, которая допускает это в качестве параметра конфигурации. Но ответ ниже должен в основном охватывать это.

#!/usr/bin/env python
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import os
import threading

class handlr(BaseHTTPRequestHandler):
    def do_GET(self):
        result, succeeded = run_with_timeout(lambda: os.popen('sleep 20 & echo "this took 20 seconds"').read(), timeout=3)
        if succeeded:
            self.send_response(200)
            self.send_header('Content-type','text-html')
            self.end_headers()
            self.wfile.write(os.popen('sleep 20 & echo "this took 20 seconds"').read())
        else:
            self.send_response(500)
            self.send_header('Content-type','text-html')
            self.end_headers()
            self.wfile.write('<html><head></head><body>Sad panda</body></html>')
        self.wfile.close()

def run():
    server_address = ('127.0.0.1', 8080)
    httpd = HTTPServer(server_address, handlr)
    httpd.serve_forever()

def run_with_timeout(fn, timeout):
    lock = threading.Lock()
    result = [None, False]
    def run_callback():
        r = fn()
        with lock:
            result[0] = r
            result[1] = True

    t = threading.Thread(target=run_callback)
    t.daemon = True
    t.start()
    t.join(timeout)
    with lock:
        return tuple(result)

if __name__ == '__main__':
    run()
person dtanabe    schedule 25.01.2019