Hi Matthew,

I don't know what is wrong with this code, so you should probably file a
bug. I would first recommend though to simplify the reproducer as much as
you can (i.e. remove generalization/abstraction).

-Endre

On Fri, Sep 4, 2015 at 6:43 PM, Matthew Adams <[email protected]>
wrote:

> I'm trying to finish a little demo where my purpose is to respond to a GET
> to /ping with data whose format is dictated by the caller.
>
> The idea is that the caller sends an HTTP GET to /ping with an Accept
> header that can be of their choosing, provided it includes what the
> endpoint I'm writing currently supports, which are application/json,
> text/xml, text/html, and text/plain.  My code looks at the Accept header
> and picks the first media type in the Accept header that is supported, then
> I return the data with that Content-Type and in the appropriate format.
> The source code for the demo is at the bottom of this message.
>
> For example, this works great (color & emphasis added):
>
> $ curl -i -H '*Accept: application/json, text/xml*'
> http://localhost:8080/ping
> HTTP/1.1 200 OK
> Server: akka-http/2.3.12
> Date: Fri, 04 Sep 2015 16:33:12 GMT
> *Content-Type: application/json*
> Content-Length: 42
>
> {
>   "s": "MediaType is application/json"
> }
>
> However, when I change the Accept header to only request text/xml, I get
> an error:
>
> $ curl -i -H '*Accept: text/xml*' http://localhost:8080/ping
> HTTP/1.1 406 Not Acceptable
> Server: akka-http/2.3.12
> Date: Fri, 04 Sep 2015 16:34:01 GMT
> Content-Type: text/plain; charset=UTF-8
> Content-Length: 84
>
> Resource representation is only available with these Content-Types:
> application/json
>
> It's as though akka-http's routing directives are forcing me to use *only*
> application/json, when I'd like to demonstrate that the client can get the
> media type they want through the Accept header.  How do I tell akka-http
> that I want to use an explicit Content-Type of my own choosing?
>
> Here's the code.  Thanks in advance.
>
> import akka.actor.ActorSystem
> import akka.http.scaladsl.Http
> import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
> import akka.http.scaladsl.model.headers.Accept
> import akka.stream.ActorMaterializer
> import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
> import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._
> import akka.http.scaladsl.server.Directives._
> import akka.http.scaladsl.model._
> import akka.http.scaladsl.marshalling._
> import scala.concurrent.Future
> import scala.concurrent.ExecutionContext.Implicits.global
> import spray.json.DefaultJsonProtocol._
> import spray.json.DefaultJsonProtocol
> import akka.http.scaladsl.server.{Rejection, Directive1, Directive}
>
> object Main extends App {
>
>   // start infrastructure
>   implicit val system = ActorSystem("akka-http-routing")
>   implicit val materializer = ActorMaterializer()
>
>   val json = MediaTypes.`application/json`
>   val xml = MediaTypes.`text/xml`
>   val html = MediaTypes.`text/html`
>   val text = MediaTypes.`text/plain`
>
>   case class MissingAcceptHeaderMediaType(requiredMediaType:
> Seq[MediaType]) extends Rejection
>
>   case class Pong(s: String = "")
>   implicit val pjf = jsonFormat1(Pong)
>
>   def firstIn[In, Among](in: Seq[In], among: Seq[Among], predicate: (In,
> Among) => Boolean): Option[In] =
>     in collectFirst { case i if among exists { a => predicate(i, a) } => i
> }
>
>   def firstAmong[In, Among](in: Seq[In], among: Seq[Among], predicate:
> (In, Among) => Boolean): Option[Among] =
>     firstIn(in, among, predicate) match {
>       case Some(i) => among collectFirst { case a if predicate(i, a) => a }
>       case _ => None
>     }
>
>   def firstMediaType(in: Accept, among: Seq[MediaType]): Option[MediaType]
> = {
>     firstAmong(in.mediaRanges, among, (r: MediaRange, t: MediaType) => r
> matches t)
>   }
>
>   def accept(requiredTypes: Seq[MediaType]): Directive1[MediaType] =
> headerValueByType[Accept]().flatMap {
>     case v => firstMediaType(v, requiredTypes) match {
>       case Some(mt) => extract { f => mt }
>     }
>     case _ => reject(MissingAcceptHeaderMediaType(requiredTypes))
>   }
>
>   val route =
>     get {
>       path("ping") {
>         accept(List(json, xml, html, text)) { t =>
>           val s = s"""MediaType is ${t}"""
>           t match {
>             case json => complete {
>               Pong(s)
>             }
>             case xml => complete {
>               <pong>
>                 {s}
>               </pong>
>             }
>             case html => complete {
>               <html>
>                 <body>
>                   <pre>
>                     {s}
>                   </pre>
>                 </body>
>               </html>
>             }
>             case _ => complete {
>               Pong(s).toString
>             }
>           }
>         }
>       }
>     }
>
>   // start a new HTTP server on port 8080 with our route
>   Http().bindAndHandle(route, "localhost", 8080)
> }
>
> --
> >>>>>>>>>> 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 [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/akka-user.
> For more options, visit https://groups.google.com/d/optout.
>



-- 
Akka Team
Typesafe - Reactive apps on the JVM
Blog: letitcrash.com
Twitter: @akkateam

-- 
>>>>>>>>>>      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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Reply via email to