Сериализация Lagom для активов Stati c - PullRequest
0 голосов
/ 18 февраля 2020

Я занимаюсь разработкой микросервиса Lagom. В дополнение к его мясу у него есть несколько файлов stati c (index. html, *. css, *. js и favicon.ico). Я знаю, как установить заголовок Content-Type ответа, используя Lagom's ServerServiceCall[Req, Res]. Однако, если в качестве типа параметра ответа указать String, Content-Type будет перезаписан как «text / plain» независимо от того, что я установил в теле вызова службы. Если я использую akka.util.ByteString, то Content-Type становится «application / octet-stream».

Я полагаю, что это должно быть потому, что этого требуют сериализаторы String и ByteString. Итак, мой вопрос: какие типы ответов я должен сделать, чтобы получить «text / html», «text / css», «application / javascript» и «image / vnd.microsoft.icon»? Или есть более общий c способ обслуживания активов c в Лагоме? Документация на это удивительно редка.

Хотелось бы что-то вроде этой работы:

import akka.util.ByteString
import com.lightbend.lagom.scaladsl.api.transport.MessageProtocol
import com.lightbend.lagom.scaladsl.api.deser.MessageSerializer.NegotiatedSerializer

class ContentTypeSerializer(contentType: String, charset: String) extends NegotiatedSerializer[String, ByteString] {
  override val protocol = MessageProtocol(Some(contentType), Some(charset))
  def serialize(body: String) = ByteString.fromString(body, charset)
}

1 Ответ

0 голосов
/ 18 февраля 2020

Да, это позаботится об этом:

import akka.util.ByteString
import play.api.libs.json.Json
import scala.collection.immutable
import scala.util.control.NonFatal
import com.lightbend.lagom.scaladsl.api.transport._
import com.lightbend.lagom.scaladsl.api.deser.StrictMessageSerializer
import com.lightbend.lagom.scaladsl.api.deser.MessageSerializer.{NegotiatedDeserializer, NegotiatedSerializer}

class ContentTypeSerializer(contentType: String, charset: String) extends NegotiatedSerializer[String, ByteString] {
  override val protocol = MessageProtocol(Some(contentType), Some(charset))
  def serialize(body: String) = ByteString.fromString(body, charset)
}

object ContentTypeSerializer {
  val Json = "application/json"
  val Js = "application/javascript"
  val Icon = "image/vnd.microsoft.icon"
  val Html = "text/html"
  val Css = "text/css"

  val JsonSerializer = new ContentTypeSerializer(ContentTypeSerializer.Json, "utf-8")
}

class JsonTextDeserializer extends NegotiatedDeserializer[String, ByteString] {
  def deserialize(bytes: ByteString) =
    try {
      Json.parse(bytes.iterator.asInputStream).as[String]
    } catch {
      case NonFatal(e) => throw DeserializationException(e)
    }
}

object ResponseSerializer extends StrictMessageSerializer[String] {
  override val acceptResponseProtocols = List(
    MessageProtocol(Some(ContentTypeSerializer.Json)),
    MessageProtocol(Some(ContentTypeSerializer.Html)),
    MessageProtocol(Some(ContentTypeSerializer.Icon)),
    MessageProtocol(Some(ContentTypeSerializer.Css)),
    MessageProtocol(Some(ContentTypeSerializer.Js))
  )

  val serializerForRequest = ContentTypeSerializer.JsonSerializer

  def deserializer(protocol: MessageProtocol) = protocol.contentType match {
    case Some(ContentTypeSerializer.Json) | None =>
      new JsonTextDeserializer
    case _ =>
      throw UnsupportedMediaType(protocol, MessageProtocol(Some("text/plain")))
  }

  def serializerForResponse(accepted: immutable.Seq[MessageProtocol]) = accepted match {
    case Nil => ContentTypeSerializer.JsonSerializer
    case protocols => protocols.collectFirst {
      case MessageProtocol(Some(ContentTypeSerializer.Json), charset, _) =>
        new ContentTypeSerializer(ContentTypeSerializer.Json, charset.getOrElse("utf-8"))
      case MessageProtocol(Some(ContentTypeSerializer.Html), charset, _) =>
        new ContentTypeSerializer(ContentTypeSerializer.Html, charset.getOrElse("utf-8"))
      case MessageProtocol(Some(ContentTypeSerializer.Icon), charset, _) =>
        new ContentTypeSerializer(ContentTypeSerializer.Icon, charset.getOrElse("utf-8"))
      case MessageProtocol(Some(ContentTypeSerializer.Css), charset, _) =>
        new ContentTypeSerializer(ContentTypeSerializer.Css, charset.getOrElse("utf-8"))
      case MessageProtocol(Some(ContentTypeSerializer.Js), charset, _) =>
        new ContentTypeSerializer(ContentTypeSerializer.Js, charset.getOrElse("utf-8"))
    }.getOrElse {
      throw NotAcceptable(accepted, MessageProtocol(Some("text/plain")))
    }
  }
}
...