akka-http, response with "application/json" media type

2,231 views
Skip to first unread message

dmitry....@iohk.io

unread,
Apr 22, 2016, 10:19:31 AM4/22/16
to Akka User List
Hi!

I have a simple route, that should respond (as I expect) with `application/json` media type. 

 def height: Route = {
   path
("height") {
     
// respondWithHeaders(`Content-Type`(MediaTypes.`application/json`))(complete("???")) // also don't work
     respondWithHeaders
(RawHeader("Content-Type", "application/json"))(complete("???"))
   
}
 
}

But when I do requests to this route, I see Content-Type: text/plain :

 $ curl -X GET -v 'http://localhost:9085/blocks/height'
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 9085 (#0)
> GET /blocks/height HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:9085
> Accept: */*
>
< HTTP/1.1 200 OK
* Server akka-http/2.4.4 is not blacklisted
< Server: akka-http/2.4.4
< Date: Fri, 22 Apr 2016 14:04:18 GMT
< Content-Type: text/plain; charset=UTF-8
< Content-Length: 3
<
* Connection #0 to host localhost left intact
???



What should I change to get `application/json` media typ&



Konrad Malawski

unread,
Apr 22, 2016, 10:25:06 AM4/22/16
to akka...@googlegroups.com, dmitry....@iohk.io
Content-Type is special – it should come with/from the data you're completing with – please don't hardcode it like that (it won't work, and that's on purpose).

Here's how you'd use JSON in a real world app:

object TestServer extends App
with SprayJsonSupport with DefaultJsonProtocol {

implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
import system.dispatcher

import Directives._

final case class Thingy(value: String)
implicit val thingyFormat = jsonFormat1(Thingy)

val routes =
complete(Thingy(""))

val bindingFuture = Http().bindAndHandle(routes, interface = "localhost", port = 8080)

println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
Console.readLine()

bindingFuture.flatMap(_.unbind()).onComplete(_ ⇒ system.terminate())

}

If you really want to do raw hardcoding of content type header, you can by returning HttpEntity:

val routes =
complete(HttpEntity(ContentTypes.`application/json`, "{}"))

$ http localhost:8080  Accept:*/*
HTTP/1.1 200 OK
Content-Length: 2
Content-Type: application/json
Date: Fri, 22 Apr 2016 14:24:19 GMT
Server: akka-http/2.4-SNAPSHOT

{}

Happy hakking!

-- 
Konrad `ktoso` Malawski
Akka @ Lightbend

On 22 April 2016 at 16:19:27, dmitry....@iohk.io (dmitry....@iohk.io) wrote:

Hi!

I have a simple route, that should respond (as I expect) with `application/json` media type. 

 def height: Route = {
   path
("height") {
     
// respondWithHeaders(`Content-Type`(MediaTypes.`application/json`))(complete("???")) // also don't work
     respondWithHeaders
(RawHeader("Content-Type", "application/json"))(complete("???"))
   
}
 
}

But when I do requests to this route, I see Content-Type: text/plain :

What should I change to get `application/json` media typ&



 $ curl -X GET -v 'http://localhost:9085/blocks/height'
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 9085 (#0)
> GET /blocks/height HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:9085
> Accept: */*
>
< HTTP/1.1 200 OK
* Server akka-http/2.4.4 is not blacklisted
< Server: akka-http/2.4.4
< Date: Fri, 22 Apr 2016 14:04:18 GMT
< Content-Type: text/plain; charset=UTF-8
< Content-Length: 3
<
* Connection #0 to host localhost left intact
???



--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at https://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

dmitry....@iohk.io

unread,
Apr 25, 2016, 4:34:24 AM4/25/16
to Akka User List, dmitry....@iohk.io
Thanks for your response!

Is it possible to combine it with play-json?
My spray function I'm trying to rewrite looks like 

 def jsonRoute(fn: => ToResponseMarshallable, method: Directive0 = get): Route = method {
    val jsonResponse = respondWithMediaType(`application/json`) {
      complete(fn)
    }
    if (corsAllowed) respondWithHeader(RawHeader("Access-Control-Allow-Origin", "*"))(jsonResponse)
    else jsonResponse
  }

I still can't see how to combine your response (even the `hacking` one) with ToResponseMarshallable..
Reply all
Reply to author
Forward
0 new messages