Search code examples
scalaakka-http

Set Content-Type header


I have a problem with akka-http.
The Content-Type headers default value is text/plain. I am trying to set application/json value like this:

val routes = 
  respondWithHeader(headers.`Content-Type`(ContentType(MediaTypes.`application/json`))) {
    // ...
    // all api routes
    // ...
  }

But this doesn't work. Content-Type is still text/plain.


UPD
I am NOT reading clients Content-Type header. I am trying to send another from default Content-Type header from server.


UPD2
For instance:

import JsonProtocol.entityFormat
//...
(get & path("api" / "entities")) {
  complete(getAllEntities)
}

getAllEntities returns a list of entities from DB as Future[Entity]. Entity is just a model:

case class Entity(foo: Int, bar: String)

EntityFormat looks like:

object JsonProtocol extends spray.json.DefaultJsonProtocol {
  implicit val entityFormat = jsonFormat2(Entity)
}

Finally cast Future to ResponseMarshallable:

implicit def entity2ResponseMarshallable(entityF: Future[Entity]): ToResponseMarshallable =
  entityF map (_.toJson.toString())

Solution

  • Pulling together the discussion in comments with an actual solution:

    If you remove .toString from your entity2ResponseMarshallable method, so simply have

    implicit def entity2ResponseMarshallable(
          entityF: Future[Entity]): ToResponseMarshallable =
        entityF map (_.toJson)
    

    you should get the correct content type headers in your server response.

    This is how akka-http wants to handle the Content-Type header - it sets it automatically depending on what marshaller it ends up using. String, which you had before, translates to text/plain.

    As for your original question, I don't believe changing the Content-Type header manually is possible at that point. As per the Akka documentation,

    The Content-Type of an HTTP message is modeled as the contentType field of the HttpEntity. The Content-Type header therefore doesn’t appear in the headers sequence of a message. Also, a Content-Type header instance that is explicitly added to the headers of a request or response will not be rendered onto the wire and trigger a warning being logged instead!

    So in order to set the content-type manually, you have to override it in the HttpEntity instance as per the other question I originally linked - in order to do it on a route level you'd have to redefine the HttpEntity contained in your HttpResponse after the fact which I'm not sure is possible, and which doesn't sound like a good idea in any case.