2014-03-03 25 views
1

爲了確保人們不追加隨機查詢參數(例如追加&r=234522.123或類似的)來避免碰到我們的緩存,我想有一種方法來拒絕任何沒有明確處理的查詢。我當然可以創建一個包含白名單的項目,但這必須單獨維護,而我討厭維護需要保持同步的兩件事。 (雖然它會幫助更快地失敗。)這是可能的噴霧佈線嗎?是否可以編寫指令來匹配「任何其他查詢參數」?

回答

1

我結束了與此:

// This contains a white-list of allowed query parameters. This is useful to 
// ensure people don't try to use &r=234234 to bust your caches. 
def allowedParameters(params: String*): Directive0 = parameterSeq.flatMap { 
    case xs => 
    val illegal = xs.collect { 
     case (k, _) if !params.contains(k) => k 
    } 
    if (illegal.nonEmpty) 
     reject(ValidationRejection("Illegal query parameters: " + illegal.mkString("", ", ", "\nAllowed ones are: ") + params.mkString(", "))) 
    else 
     pass 
} 

有關用法,看看單元測試:

val allowedRoute = { 
    allowedParameters("foo", "bar") { 
    complete("OK") 
    } 
} 

"Allowed Parameter Directive" should "reject parameters not in its whitelist" in { 
    Get("/?foo&bar&quux") ~> allowedRoute ~> check { 
    handled should equal(false) 
    rejection should be(ValidationRejection("Illegal query parameters: quux\nAllowed ones are: foo, bar")) 
    } 
} 

it should "allow properly sorted parameters through" in { 
    Get("/?bar&foo") ~> allowedRoute ~> check { 
    handled should equal(true) 
    responseAs[String] should equal("OK") 
    } 
} 
+0

如果有人提出更好的解決方案,請保留此問題... –

-2

有了這樣的路線:

val myRoute = { 
    ... 
    pathPrefix("test") { 
    parameter("good") { 
     good => 
     complete("GOOD") 
    } 
    } ~ 
... 
} 

噴霧將需要第一個參數是good並具有值,即?good=value。沒有其他具有值的參數被允許。

+0

我不明白你如何得出這個結論。你的意思是其他參數*忽略*?這不是我想要的。我希望路由被拒絕並顯示錯誤消息。 –

+0

我的意思是說,如果有任何其他查詢參數具有值,即'param = value'除'good = value'外,那麼路由將被拒絕並顯示錯誤消息。 'url/test?good = true' - 接受,'url/test?bad = true?good = true' - 拒絕,'url/test?good = true?bad = true' - 拒絕。然而,由於某些原因,沒有值的參數不會被拒絕:接受「url/test?good = true?bad」或「url/test?bad?good = true」。 –

+0

我認爲當我們說「被拒絕」時我們會談論兩件不同的事情。你的'/ test?good = ...'路由只會被*接受*,如果你在請求中有一個名爲good的參數和一個值。但是它不拒絕我想要的其他參數;我不想讓多餘的論據被忽略,我希望他們成爲一個錯誤。 –

1

其實,你有一個很好的解決辦法,我只能建議小重構:

def only(params: String*): Directive0 = { 
    def check: Map[String, String] => Boolean = _.keySet diff params.toSet isEmpty 
    parameterMap.require(check, rejection) 
} 

你可以把它寫成一行代碼,但它是剛剛長

+0

這是一個很好的重構。謝謝! –

相關問題