0

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())
Oleg
  • 899
  • 1
  • 8
  • 22
  • Can you try this: respondWithHeader(RawHeader("Content-Type", "application/json")) – earlymorningtea Jul 17 '18 at 11:11
  • Possible duplicate of [Akka-http: Accept and Content-type handling](https://stackoverflow.com/questions/32187858/akka-http-accept-and-content-type-handling) – Astrid Jul 17 '18 at 11:14
  • @tea-addict the same result – Oleg Jul 17 '18 at 11:21
  • @Astrid I dont think so. I have tons routes and tons of tons `complete` methods. I dont want to modify each of them. I want to set header once. – Oleg Jul 17 '18 at 11:24
  • It'd be good to see an example of one of those methods - usually akka-http auto-detects the content type and sets it to application/json if you're returning a JSON object. Content-Type generally gets special handling and, it looks like, can't be set as a header - see https://doc.akka.io/docs/akka-http/current/common/http-model.html#http-headers – Astrid Jul 17 '18 at 12:06
  • @Astrid Typical complete method sends message to the `akka-actor` via `ask` or `?` wich runs DB request via `slick` and serialize result via `spray-json`. – Oleg Jul 17 '18 at 12:50
  • The bit I'd like to see is "serialize result via `spray-json`" and the construction of the `HttpEntity` object used in the response. Basically, if you're returning JSON objects then `Content-Type application/json` should be set automatically, and you're probably going to have more luck figuring out why it's not than trying to override your `Content-Type` header globally - which, according to the docs, is likely not possible. – Astrid Jul 17 '18 at 13:58
  • @Astrid added UPD2 – Oleg Jul 17 '18 at 14:16

1 Answers1

3

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.

Astrid
  • 1,808
  • 12
  • 24