2017-03-16 24 views
0

在akka-http中,除非路由依赖于一些动态的提取参数(客户端IP,请求头,任何内容),否则路由只会在构建时评估一次。akka-http'Directive0'强制内部路由对每个请求分别进行评估?

我的自定义指令之一取决于副作用(可能更改的系统文件),所以我希望每次单独执行它。我正在寻找可以包装的extractNothing

有没有这样的?

消耗参数的能力也可以,然后我可以(extract[Unit](_) & consume)

回答

1

路线静止型动态无

你是正确的路线只计算一次。然而,任何路线的身体本质上都可以是动态的。

作为一个例子,假设我们有一个返回的当前时间的函数:

val getTime =() => System.currentTimeMillis().toString 

此功能可被嵌入一个Route内:

val route = 
    get { 
    path("currentTime") { 
     complete(getTime()) 
    } 
    } 

更新文件路径

现在,每个HttpRequest都会得到不同的时间值,即使routeval

同样,你可以使用streaming file io在阿卡创建一个动态HttpResponse,实体这是你改变文件的内容:

val fileResponse =() => { 
    val file = Paths get "sourceFile.txt" 

    val chunkSource = FileIO fromPath file 

    val chunkEntity = 
    Chunked.fromData(ContentTypes.`text/plain(UTF-8)`, chunkSource) 


    HttpResponse(entity = chunkEntity) 
} 

val fileRoute = 
    get { 
    path("sourceFile") { 
     complete(fileResponse()) 
    } 
    } 

内&外部路由

扩展的例子进一步动态路由1步,您可以编写一个功能,每隔一段时间都会失败:

val halfBaked =() => { 
    var isGood = true 

() => { 
    if(isGood) { 
     isGood = false 
     complete(fileResponse()) 
    } 
    else { 
     isGood = true 
     complete(StatusCodes.InternalServerError) 
    } 
    } 
} 

并包裹在外部路线:

val innerRoute = halfBaked() 

val outerRoute = 
    get { 
    path("feelingLucky") { 
     innerRoute() 
    } 
    } 
+0

好的答案。但是,就我而言,这是指令本身需要重新评估。它从磁盘获取身份验证客户端ID,并且可能会旋转它们。所以你的方法不幸不起作用。 – akauppi

+0

@akauppi根据评论更新了我的答案。另外,你的问题有点暗示了一个设计缺陷。您应该将副作用和状态隔离到最底层,最小的空间。在我的示例中,isGood状态驻留在效用函数中。这听起来像你一直到Route层次都有副作用。 –

+0

你对设计缺陷是如此正确!由于你的回答,我重新思考了这个想法,并且能够将依赖于文件的行为移动到路由中,而不是在指令中。更干净,我很高兴! :) – akauppi