Scala Play 2.0 web services on Heroku

I noticed two issues with Scala Play web services on Heroku.

Firstly, for some reason my initial implementation worked when running Play locally, but did not work in production on the Heroku server. The approach was using java.net.URL as an input stream and blocking while the content was downloaded. So, don’t do that (the approach that worked is detailed below).

Secondly Heroku uses a reverse proxy between the user and the web server, so getting the user IP isn’t going to work as it will be the IP of the proxy instead. So what you need to do is look for the “X-Forwarded-For” attribute that the proxy adds to the header information for you.

Here’s what worked for me:

def index = Action { implicit request =>

   val ipAddress = request.headers.get("X-Forwarded-For") match {
      case Some(ip: String) => ip
      case None => request.remoteAddress
   }
   val ip = if( ipAddress.equals("127.0.0.1"))
      "10.0.0.1" // insert your IP here for development mode testing
      else ipAddress

   val promise: Future[play.api.libs.ws.Response] = WS.url("http://freegeoip.net/json/"+ip).get()
   Async {
      promise map { res =>
         val locationJSON:JsValue = Json.parse(res.ahcResponse.getResponseBody())
         val lat = ( locationJSON \ "latitude" ).asOpt[Double].getOrElse(0)
         val long = ( locationJSON \ "longitude" ).asOpt[Double].getOrElse(0)
         val city = ( locationJSON \ "city" ).asOpt[String].getOrElse("")
         println("City: "+city)

         Ok(views.html.location(city,ip))
      }
   }
}

Comments are closed.