Lagom — Добавить заголовок к ответу в состав служебного вызова

#scala #cookies #header #composition #lagom

Вопрос:

я хочу написать код, который обновит файл cookie (через http-заголовок set-cookie) в Lagom.
Для уточнения файл cookie представляет собой закодированную строку (например, AES).
Давайте возьмем состав вызова службы lagom для аутентификации из служб реализации и отредактируем его

 def authenticated[Request, Response](
    serviceCall: User => ServerServiceCall[Request, Response]
) = ServerServiceCall.composeAsync { requestHeader =>
  
  //Get cookie from header and decode it
  val cookie = decodeCookie(requestHeader) 
 
  //Get user based on cookie decode function  
  val userLookup = getUser(cookie)

  userLookup.map {
    case Some(user) =>
        serviceCall(user)

    case None => throw Forbidden("User must be authenticated")
  }
}
 

Можно ли манипулировать заголовками ответов serviceCall(пользователя)?

Я попробовал что-то вроде этого:

 serviceCall( employee ).handleResponseHeader { case (responseHeader, response) =>
    responseHeader.withHeader("Set-Cookie",encodeCookie("NewCookieStringExample")) // Add header
    response
}
 

Но функция handleResponseHeader требует только ответа[T], так как результат и заголовок не будут изменены, потому что неизменяемы.

Я знаю, что могу передать файл cookie serviceCall(пользователю) и в каждой реализации вызова службы возвращать кортеж с заголовком ответа и ответом, но это повлияет на все конечные точки и добавит гораздо больше кода.

Использование HeaderFilter также возможно, но это позволило бы декодировать и кодировать cookie дважды в одном запросе (в фильтре заголовка и в составе проверенного вызова службы )

Какие-нибудь советы?

Ответ №1:

Вы можете вернуть измененный заголовок и ответ в виде кортежа:

 serviceCall( employee ).handleResponseHeader((responseHeader, response) => {
     val modifiedHeader =  responseHeader.withHeader("Set-Cookie",encodeCookie("NewCookieStringExample")) // Add header
    (modifiedHeader, response)
})
 

Кстати, приведенный пример не компилируется для меня. composeAsync хочет Future[ServerServiceCall[...]] .

Комментарии:

1. Хорошая идея. Сочинять асинхронно-это моя ошибка из-за копирования вставки (мой код будет использоваться в будущем). Я попробовал это сначала,но аутентифицированная функция жаловалась на неправильный тип (требуется ответ, но (ResponseHeader, ответ)). Я думал, что это ошибка в этой функции, но это была ошибка в функции выше (для аутентификации требуется ответ для возврата). Спасибо за помощь.