2016-07-20 2 views
2

Я новичок в спрее, и я пытаюсь написать специальную директиву. Я хотел бы, чтобы директива отклонила запрос, если значение заголовка недействительно, иначе оставить запрос в одиночку.Пользовательская директива spray.io для проверки значения заголовка запроса

Я пытался поглотить эту страницу: http://spray.io/documentation/1.1.2/spray-routing/key-concepts/directives/

В частности, часть о респондеров цепи. Я пытаюсь создать что-то на уровне барной директивы на иллюстрации. Я просто не понимаю, как передать контекст без изменений на внутренний маршрут.

Неверный блок ниже, но выражает то, что я пытаюсь сделать. Я просто не могу понять, как его реализовать.

Любая помощь была бы принята с благодарностью.

trait ApiKeyDirective { 
    import spray.routing.directives.HeaderDirectives._ 
    import spray.routing.directives.BasicDirectives._ 

    def validateApiKey(): Directive1 = { 

     headerValueByName("api-key") {key => 
      val valid = key == "123" 
      if (!valid) reject() else pass 
     } 
    } 
} 

object ApiKeyDirective extends ApiKeyDirective 

ответ

0

Я просто не получаю, как передать контекст без изменений к внутреннему маршруту.

Спрей делает это за вас!

Ваш код в основном верный, есть только 2 простых проблемы, чтобы исправить! Во-первых, вам необходимо установить flatMapheaderValueByName("api-key"). Во-вторых, тип возврата будет Directive0, потому что директива не даст никакого значения.

Так окончательный код будет выглядеть следующим образом:

object ApiKeyDirective { 
    import spray.routing.Directives._ 

    val validateApiKey: Directive0 = 
    headerValueByName("api-key").flatMap { key => 
     val valid = key == "123" 
     if (!valid) reject() else pass 
    } 

} 

Кроме того, я рекомендую вам добавить пользовательский отказ в reject() блока, так что пользователи API будут проинформированы, когда их ключ API недействителен.

+1

Спасибо! Я намерен отклонить с помощью AuthorizationFailedRejection, но оставил его для краткости. –

2

Вы можете комбинировать

headerValueByName:

def headerValueByName(headerName: String): Directive1[String] 

с validate:

def validate(check: ⇒ Boolean, errorMsg: String): Directive0 

Например:

def validateApiKey(route: Route) = 
    headerValueByName("api-key") { key => 
     validate(key == "123", "Invalid API key") { 
     route 
     } 
    } 

или без validate:

def validateApiKey(route: Route) = 
    headerValueByName("api-key") { key => 
     if (key == "123") 
     route 
     else 
     reject(ValidationRejection("Invalid API key")) 
    } 

Использование:

lazy val route = ... 
    ... ~ 
    pathPrefix("test_directive") { 
     get { 
     validateApiKey { 
      complete("ok") 
     } 
     } 
    } ~ 
    ... 

Испытание из CMD/оболочки:

# curl http://localhost:8080/test_directive 
Request is missing required HTTP header 'api-key' 

# curl http://localhost:8080/test_directive -H 'api-key: bad' 
Invalid API key 

# curl http://localhost:8080/test_directive -H 'api-key: 123' 
"ok" 
+0

Спасибо. Очень полезно видеть возможные варианты. –

Смежные вопросы