Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to put favicon for a scala Spray application (i.e. what is the root of the site?)?

Internet says I should put my favicon.ico in the root of the site to stop Spray from clogging my logs with huge stacktraces. I don't know what the root of the site means, particularly in the context of a RESTful spray application.

Suppose my project is in ~/src/my-project - I build it (sbt assembly), and run it from this location, where should I put the favicon.ico?? I tried putting in ~/src/my-project but I still get the stacktrace.

NB: it only throws the exception if I directly access the API from my browser (rather than via the actual front end of our website).

like image 334
samthebest Avatar asked Jan 10 '23 01:01

samthebest


1 Answers

Most current browsers are automatically looking for favicon.ico inside your site's root. So, you have to process their GET /favicon.ico http-requests. The easiest way to do that is to use spray-routing's getFromResource:

import spray.routing.SimpleRoutingApp
import spray.http._
import MediaTypes._

object Main extends App with SimpleRoutingApp {
  implicit val system = ActorSystem("my-system")

  startServer(interface = "localhost", port = 8080) {
    path("favicon.ico") {
      getFromResource("favicon.ico", `image/x-icon`) // will look for the file inside your `resources` folder
    }
  }
}

If you already have some processing actor (and don't use spray-routing), you will need to process GET /favicon.ico directly inside your actor, returning something like:

def receive = {
   case HttpRequest(GET, Uri.Path("/favicon.ico"), _, _, _) => 
      sender ! HttpResponse(entity = HttpEntity(`image/x-icon`, 
         HttpData(new File("favicon.ico")))) //will take it from a file in application folder, you may also pass any array of byte instead of File
   ...
}

See another answer for more info about second option.

P.S. If you don't want to bother with favicon.ico file - you may return just StatusCodes.NotFound in both cases:

  • complete(NotFound) for routing
  • sender ! HttpResponse(NotFound) for your own actor

As it's done inside SiteServiceActor.

Also, using W3C's preferred method (putting the link inside your web pages) won't guarantee cross-browser compatibility as it depends on the browser's search order and there is no W3C standard about that (see siteData-36). Most browsers seems to look inside the site's root first, even if you don't have any html pages.

like image 54
dk14 Avatar answered Jan 16 '23 19:01

dk14