2

I am looking into the akka-http documentation, and find there how to serve html content with the low-level server api using HttpResponses. However, I can not find any good examples on how to serve html-content, which should be correctly represented in the browser. The only things that I find and can get working is when it serve String content as below. I found an example that:

imports akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._

but I can not see that scaladsl contains marshallers (it contains marshalling)

import akka.http.scaladsl.Http
import akka.stream.ActorMaterializer
import akka.http.scaladsl.server.Directives._
import akka.actor.ActorSystem

object HttpAkka extends App{

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

   val route = get {
       pathEndOrSingleSlash {
           complete("<h1>Hello</h1>")
       }
   }

  Http().bindAndHandle(route, "localhost", 8080)

}

found a relevant question here Akka-http: Accept and Content-type handling

I did not fully understand the answer in that link, but tried the following (i eventually got this to work..):

complete {
    HttpResponse(entity=HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say Hello</h1>"))
}

as well as:

complete {
    respondWithHeader (RawHeader("Content-Type", "text/html(UFT-8"))
      "<h1> Say hello</h1>"
    } 
Community
  • 1
  • 1
stian
  • 1,947
  • 5
  • 25
  • 47
  • both doesn't work as is it is now. For mustafas suggestion there needs to be an xml library added, and for kostya`s suggestion I get a not found value error (if I use ContentTypes.`text/html(UTF8)` I get a type mismatch. – stian Mar 23 '16 at 08:41

1 Answers1

2

The best way to handle this probably is to use ScalaXmlSupport to build a NodeSeq marshaller that will properly set the content type as text/html. To do that, you first need to add a new dependency as ScalaXmlSupport is not included by default. Assuming you are using sbt, then the dependency to add is as follows:

"com.typesafe.akka" %% "akka-http-xml-experimental" % "2.4.2"

Then, you can setup a route like so to return a Scala NodeSeq that will be flagged as text/html when akka sets the content type:

implicit val system = ActorSystem()
import system.dispatcher
implicit val mater = ActorMaterializer()
implicit val htmlMarshaller = ScalaXmlSupport.nodeSeqMarshaller(MediaTypes.`text/html` )

val route = {
  (get & path("foo")){
    val resp = 
      <html>
        <body>
          <h1>This is a test</h1>
        </body>
      </html>

    complete(resp)
  }
}

Http().bindAndHandle(route, "localhost", 8080

The trick to getting text/html vs text/xml is to use the nodeSeqMarshaller method on ScalaXmlSupport, passing in MediaTypes.text/html as the media type. If you just import ScalaXmlSupport._ then the default marshaller that will be in scope will set the content type to text/xml.

cmbaxter
  • 35,283
  • 4
  • 86
  • 95
  • would this also work if the html was read from a file as a string? for instance val resp = Source.fromFile("filePath").mkString? – stian Mar 23 '16 at 21:21
  • @stian, it would work if you took the additional step of converting that string read from the file into a `NodeSeq` first. – cmbaxter Mar 24 '16 at 10:45