I am using python Klein http://klein.readthedocs.io/en/latest/ for setting up a web service. I had checked the documentation but I still don't know how to set the timeout of the service. Can anyone who is more familiar with tool shows how to set the timeout to 15 seconds? Thanks!
You could call
Request.loseConnection() to drop the request connection to the client after an set timeout interval. Here is a quick example:
from twisted.internet import reactor, task, defer from klein import Klein app = Klein() request_timeout = 10 # seconds @app.route('/delayed/<int:n>') @defer.inlineCallbacks def timeoutRequest(request, n): work = serverTask(n) # work that might take too long drop = reactor.callLater( request_timeout, # drop request connection after n seconds dropRequest, # function to drop request connection request, # pass request obj into dropRequest() work) # pass worker deferred obj to dropRequest() try: result = yield work # work has completed, get result drop.cancel() # cancel the task to drop the request connection except: result = 'Request dropped' defer.returnValue(result) def serverTask(n): """ A simulation of a task that takes n number of seconds to complete. """ d = task.deferLater(reactor, n, lambda: 'delayed for %d seconds' % (n)) return d def dropRequest(request, deferred): """ Drop the request connection and cancel any deferreds """ request.loseConnection() deferred.cancel() app.run('localhost', 9000)
To try this out, go to
http://localhost:9000/delayed/20 to test a scenario when the task doesn't complete in time. Don't forget to cancel all tasks, deferreds, threads, etc related to this request or you could potentially waste lots of memory.
Server Side Task: Client goes to
/delayed/<n> endpoint with a specified delay value. A server side task (
serverTask()) starts and for the sake of simplicity and to simulate a busy task,
deferLater was used to return a string after
Request Timeout: Using
callLater function, after the
request_timeout interval, call the
dropRequest function and pass
request and all work deferreds that need to be canceled (in this case there's only
work). When the
request_timeout has passed then the request connection will be closed (
request.loseConnection()) and deferreds will be cancelled (
Yield Server Task Result: In a try/except block, the result will be yielded when the value is available or, if the timeout has passed and connection is dropped, an error will occur and the
Request dropped message will be returned.
This really doesn't seem like a desirable scenario and should be avoided if possible, but I could see a need for this kind of functionality. Also, though rare, keep in mind that
loseConnection doesn't always fully close a connection (this is due to TCP implementation not so much Twisted). A better solution would be to cancel a server side task when the client disconnects (which may be a bit easier to catch). This can be done by attaching an
Request.notifyFinish(). Here is an example using just Twisted (http://twistedmatrix.com/documents/current/web/howto/web-in-60/interrupted.html).