在 Scotty / WAI 中完全发送响应后如何 运行 执行操作

How to run an action after response has been fully sent in Scotty / WAI

根据 GET 请求,我的 Scotty 网络应用程序将 运行 进行一些计算并将其结果存储在一个临时文件中,它使用 file.

作为响应发送

现在我想运行一些清理工作(即删除临时文件)文件发送后。 Scotty 似乎没有提供这样做的方法。

WAI 中是否有任何功能可以实现这一点?

wai 给了我们一个函数 responseStream

responseStream :: Status -> ResponseHeaders -> StreamingBody -> Response

即构造了一个Response out of a StreamingBody,其实就是一个函数

type StreamingBody = (Builder -> IO ()) -> IO () -> IO ()

给定“写入”操作和“刷新”操作,在某处找到一些字节并执行所有写入和刷新操作。

wai还为我们提供了一个ready-maderesponseFile功能:

responseFile :: Status -> ResponseHeaders -> FilePath -> Maybe FilePart -> Response

但最后并没有删除文件。我们能以某种方式修改它吗?貌似可以,借助responseToStream辅助函数

responseToStream :: Response -> (Status, ResponseHeaders, (StreamingBody -> IO a) -> IO a)

“打开”已经构建好的 Response,允许我们进行调整。

像这样:

import Network.Wai
import Network.HTTP.Types.Status (status200)
import System.Directory (removeFile)

responseFileDeleting' :: FilePath -> Response
responseFileDeleting' filepath = 
    let (status,header,streamer) = 
            responseToStream $ responseFile status200 [] filepath Nothing
     in responseStream status header (\write flush ->
             -- this would be a good place to put a bracket, if needed
             do streamer (\body -> body write flush)
                removeFile filepath)

(注:streamer的类型有点mind-twisting,因为全部都是higher-orderness。)

此解决方案的缺点是请求必须等到文件被删除才能完成。另一种选择是将文件路径发送到某种 concurrent queue 在另一个线程中执行删除操作。