play.api.Play Scala Examples

The following examples show how to use play.api.Play. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: ErrorHandler.scala    From Aton   with GNU General Public License v3.0 5 votes vote down vote up
import com.google.inject.Inject
import play.api.{Application, Play}
import play.api.http.{DefaultHttpErrorHandler, HttpErrorHandler, Status}
import play.api.mvc.{RequestHeader, Result, Results}
import views.html.index

import scala.concurrent.Future


class ErrorHandler @Inject()(errorHandler: DefaultHttpErrorHandler) extends HttpErrorHandler {
  override def onClientError(request: RequestHeader, statusCode: Int, message: String): Future[Result] = {
    statusCode match {
      case clientError if statusCode > 400 && statusCode < 500 => Future.successful(Results.NotFound(index("Aton")))
      case _ => Future.successful(Results.ServiceUnavailable("Unexpected error happened"))
    }
  }

  override def onServerError(request: RequestHeader, exception: Throwable): Future[Result] = {
    errorHandler.onServerError(request,exception)
  }
} 
Example 2
Source File: Init.scala    From cave   with MIT License 5 votes vote down vote up
package init

import akka.actor._
import com.cave.metrics.data.AwsConfig
import com.cave.metrics.data.influxdb.{InfluxClientFactory, InfluxConfiguration}
import com.typesafe.config.ConfigFactory
import org.apache.commons.logging.LogFactory
import play.api.Play
import worker.Coordinator
import worker.converter.ConverterFactory
import worker.web.AsyncNotificationSender

object Init {

  private[this] val configuration = Play.current.configuration
  private val log = LogFactory.getLog("Init")

  val serviceConfFile = configuration.getString("serviceConf").getOrElse("worker.conf")

  val appConfig = ConfigFactory.load(serviceConfFile).getConfig("worker")

  // prepare AWS config
  val awsConfig = new AwsConfig(appConfig)

  // a wrapper for required AWS
  val awsWrapper = new AwsWrapper(awsConfig)

  // a connection to the InfluxDB backend
  val influxConfig = appConfig.getConfig("influx")
  val influxClientFactory = new InfluxClientFactory(InfluxConfiguration(influxConfig))

  val converterFactory = new ConverterFactory(appConfig.getConfig("converters"))
  val sender = new AsyncNotificationSender(converterFactory)

  val system = ActorSystem("CaveWorker")
  val coordinator = system.actorOf(Props(new Coordinator(awsWrapper)), "coordinator")

  def init() {
    log.info("Init started...")
    awsWrapper.init()
    log.info("Init completed.")
  }

  def shutdown() {
    log.info("Shutdown started...")
    awsWrapper.shutdown()
    influxClientFactory.close()
    system.shutdown()
    log.info("Shutdown completed.")
  }
} 
Example 3
Source File: Init.scala    From cave   with MIT License 5 votes vote down vote up
package init

import java.util.concurrent.TimeUnit

import com.cave.metrics.data.influxdb.{InfluxClientFactory, InfluxConfiguration}
import com.cave.metrics.data.metrics.InternalReporter
import com.cave.metrics.data.{AlertManager, AwsConfig, Metric, PasswordHelper}
import com.codahale.metrics.MetricRegistry
import com.codahale.metrics.jvm.{GarbageCollectorMetricSet, MemoryUsageGaugeSet, ThreadStatesGaugeSet}
import com.typesafe.config.ConfigFactory
import org.apache.commons.logging.LogFactory
import play.api.Play

object Init {


  val metricRegistry = new MetricRegistry

  private val log = LogFactory.getLog("Init")
  private val InternalTags = Map(Metric.Organization -> Metric.Internal)

  private[this] val configuration = Play.current.configuration
  val baseUrl = configuration.getString("baseUrl").getOrElse("https://api.cavellc.io")
  val maxTokens = configuration.getInt("maxTokens").getOrElse(3)
  val serviceConfFile = configuration.getString("serviceConf").getOrElse("api-service.conf")

  val appConfig = ConfigFactory.load(serviceConfFile).getConfig("api-service")

  // prepare AWS config and Kinesis data sink
  val awsConfig = new AwsConfig(appConfig)

  // a wrapper for required AWS
  val awsWrapper = new AwsWrapper(awsConfig)

  // a connection to the InfluxDB backend
  val influxConfig = appConfig.getConfig("influx")

  val influxClientFactory = new InfluxClientFactory(InfluxConfiguration(influxConfig))

  val alertManager = new AlertManager(awsWrapper.dataManager, influxClientFactory)

  val mailService = new MailService
  val passwordHelper = new PasswordHelper

  def init() {
    awsWrapper.init()
    log.warn("Init.init()")

    val reporter = InternalReporter(registry = metricRegistry) { metrics =>
      metrics foreach(metric => awsWrapper.dataSink.sendMetric(Metric(metric.name, metric.timestamp, metric.value, InternalTags ++ metric.tags)))
    }

    reporter.start(1, TimeUnit.MINUTES)

    metricRegistry.register(MetricRegistry.name("jvm", "gc"), new GarbageCollectorMetricSet())
    metricRegistry.register(MetricRegistry.name("jvm", "memory"), new MemoryUsageGaugeSet())
    metricRegistry.register(MetricRegistry.name("jvm", "thread-states"), new ThreadStatesGaugeSet())
  }

  def shutdown() {
    awsWrapper.shutdown()
    influxClientFactory.close()
    log.warn("Init.shutdown()")
  }
} 
Example 4
Source File: HttpsAndWwwRedirectForElbFilter.scala    From cave   with MIT License 5 votes vote down vote up
package filters


import play.api.Play
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import play.api.mvc._
import play.api.Play.current

import scala.concurrent.Future

object HttpsAndWwwRedirectForElbFilter extends Filter {

  def apply(nextFilter: (RequestHeader) => Future[Result])(requestHeader: RequestHeader): Future[Result] = {
    //play uses lower case headers.
    requestHeader.headers.get("x-forwarded-proto") match {
      case Some(header) => {
        if ("https" == header) {
          if (doWwwRedirect(requestHeader))
            Future.successful(Results.Redirect("https://www." + requestHeader.host + requestHeader.uri, 301))
          else
            nextFilter(requestHeader).map { result =>
              result.withHeaders(("Strict-Transport-Security", "max-age=31536000"))
            }
        } else {
          Future.successful(Results.Redirect("https://" + requestHeader.host + requestHeader.uri, 301))
        }
      }
      case None => nextFilter(requestHeader)
    }
  }

  def doWwwRedirect(requestHeader: RequestHeader): Boolean = {
    val redirectsEnabled = Play.configuration.getBoolean("cave.enableWwwRedirect").getOrElse(false)
    val wwwRedirectEnabledDomain = Play.configuration.getString("cave.wwwRedirectEnabledDomain").getOrElse("cavellc.io")

    redirectsEnabled && requestHeader.host.startsWith(wwwRedirectEnabledDomain) && !requestHeader.host.startsWith("www.")
  }
} 
Example 5
Source File: Init.scala    From cave   with MIT License 5 votes vote down vote up
package init

import java.net.InetAddress
import java.util.UUID

import com.amazonaws.services.kinesis.clientlibrary.lib.worker.{InitialPositionInStream, KinesisClientLibConfiguration, Worker}
import com.amazonaws.services.kinesis.metrics.impl.NullMetricsFactory
import com.cave.metrics.data.AwsConfig
import com.cave.metrics.data.influxdb.{InfluxConfiguration, InfluxDataSink}
import com.cave.metrics.data.kinesis.RecordProcessorFactory
import com.typesafe.config.ConfigFactory
import org.apache.commons.logging.LogFactory
import play.api.Play

import scala.util.Try

object Init {

  // Docker should place the stream name in this environment variable
  final val EnvStreamName = "STREAM_NAME"

  // The name of this application for Kinesis Client Library
  final val ApplicationName = "cave-db-worker"

  // CloudWatch Reporter parameters
  final val MetricsNamespace = s"metrics-$ApplicationName"
  final val MetricsBufferTime = 1000L
  final val MetricsBufferSize = 200

  final val ThreadWaitTimeout = 10000L

  private val Log = LogFactory.getLog("db-writer-app")

  val worker = createWorker()
  val workerThread = new Thread(worker)

  def start(): Unit = {
    workerThread.start()
  }

  def shutdown(): Unit = {
    worker.shutdown()
    Try (workerThread.join(ThreadWaitTimeout)) recover {
      case e: Exception =>
        Log.info(s"Caught exception while joining worker thread: $e")
    }
  }

  
  private[this] def createWorker(): Worker = {
    val configuration = Play.current.configuration
    val serviceConfFile = configuration.getString("serviceConf").getOrElse("db-writer-service.conf")
    val kinesisAppName = configuration.getString("appName").getOrElse(ApplicationName)
    val appConfig = ConfigFactory.load(serviceConfFile).getConfig("db-writer")
    val awsConfig = new AwsConfig(appConfig)

    val streamName = System.getenv(EnvStreamName) match {
      case "processed" => awsConfig.processedStreamName
      case _ => awsConfig.rawStreamName
    }

    val workerId = s"${InetAddress.getLocalHost.getCanonicalHostName}:${UUID.randomUUID()}"

    Log.info(s"Running $ApplicationName for stream $streamName as worker $workerId")

    // a connection to the InfluxDB backend
    val influxConfig = appConfig.getConfig("influx")

    new Worker(
      // a factory for record processors
      new RecordProcessorFactory(
        awsConfig,
        new InfluxDataSink(InfluxConfiguration(influxConfig))),

      // a client library instance
      new KinesisClientLibConfiguration(kinesisAppName, streamName, awsConfig.awsCredentialsProvider, workerId)
        .withInitialPositionInStream(InitialPositionInStream.TRIM_HORIZON),

      new NullMetricsFactory)
      // TODO: check out the possibility to use CloudWatch Metrics
      // new CWMetricsFactory(awsConfig.awsCredentialsProvider, MetricsNamespace, MetricsBufferTime, MetricsBufferSize))
  }
} 
Example 6
Source File: KubeServiceLocatorServer.scala    From lagom-on-kube   with Apache License 2.0 5 votes vote down vote up
package me.alexray.lagom.kube.discovery

import java.io.Closeable
import java.net.URI
import java.util.{Map => JMap}

import com.lightbend.lagom.gateway.{ServiceGateway, ServiceGatewayConfig, ServiceGatewayFactory}
import me.alexray.lagom.kube.discovery.impl.KubeServiceRegistryModule
import me.alexray.lagom.kube.gateway.{KubeServiceGateway, KubeServiceGatewayConfig, KubeServiceGatewayFactory}
import play.api.Application
import play.api.Logger
import play.api.Mode
import play.api.Play
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.inject.guice.GuiceableModule.fromGuiceModule
import play.core.server.ServerConfig
import play.core.server.ServerProvider
import play.core.server.ServerWithStop

import scala.util.control.NonFatal

class KubeServiceLocatorServer extends Closeable {
  private val logger: Logger = Logger(this.getClass)

  @volatile private var server: ServerWithStop = _
  @volatile private var gateway: KubeServiceGateway = _

  def start(serviceLocatorPort: Int, serviceGatewayPort: Int, unmanagedServices: JMap[String, String]): Unit = synchronized {
    require(server == null, "Service locator is already running on " + server.mainAddress)

    val application = createApplication(KubeServiceGatewayConfig(serviceGatewayPort), unmanagedServices)
    Play.start(application)
    try {
      server = createServer(application, serviceLocatorPort)
    } catch {
      case NonFatal(e) =>
        throw new RuntimeException(s"Unable to start service locator on port $serviceLocatorPort", e)
    }
    try {
      gateway = application.injector.instanceOf[KubeServiceGatewayFactory].start()
    } catch {
      case NonFatal(e) =>
        throw new RuntimeException(s"Unable to start service gateway on port $serviceGatewayPort", e)
    }
    logger.info("Service locator can be reached at " + serviceLocatorAddress)
    logger.info("Service gateway can be reached at " + serviceGatewayAddress)
  }

  private def createApplication(serviceGatewayConfig: KubeServiceGatewayConfig, unmanagedServices: JMap[String, String]): Application = {
    new GuiceApplicationBuilder()
      .overrides(KubeServiceRegistryModule(serviceGatewayConfig, unmanagedServices))
      .build()
  }

  private def createServer(application: Application, port: Int): ServerWithStop = {
    val config = ServerConfig(port = Some(port), mode = Mode.Test)
    val provider = implicitly[ServerProvider]
    provider.createServer(config, application)
  }

  override def close(): Unit = synchronized {
    if (server == null) Logger.logger.debug("Service locator was already stopped")
    else {
      logger.debug("Stopping service locator...")
      server.stop()
      server = null
      logger.info("Service locator stopped")
    }
  }

  def serviceLocatorAddress: URI = {
    // Converting InetSocketAddress into URL is not that simple.
    // Because we know the service locator is running locally, I'm hardcoding the hostname and protocol.
    new URI(s"http://localhost:${server.mainAddress.getPort}")
  }

  def serviceGatewayAddress: URI = {
    new URI(s"http://localhost:${gateway.address.getPort}")
  }
} 
Example 7
Source File: HttpTimeoutSpec.scala    From http-verbs   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.play.http

import java.net.{ServerSocket, URI}
import java.util.concurrent.TimeoutException

import org.scalatest.concurrent.ScalaFutures
import org.scalatest.BeforeAndAfterAll
import org.scalatest.wordspec.AnyWordSpecLike
import org.scalatest.matchers.should.Matchers
import org.webbitserver.handler.{DelayedHttpHandler, StringHttpHandler}
import org.webbitserver.netty.NettyWebServer
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.libs.ws.WSClient
import play.api.test.WsTestClient
import play.api.{Configuration, Play}
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.http.ws.WSHttp
import uk.gov.hmrc.play.test.TestHttpCore

import scala.concurrent.{Await, ExecutionContext}
import scala.concurrent.duration.DurationInt

class HttpTimeoutSpec extends AnyWordSpecLike with Matchers with ScalaFutures with BeforeAndAfterAll {

  import ExecutionContext.Implicits.global

  lazy val fakeApplication =
    GuiceApplicationBuilder(configuration = Configuration("play.ws.timeout.request" -> "1000ms")).build()

  override def beforeAll() {
    super.beforeAll()
    Play.start(fakeApplication)
  }

  override def afterAll() {
    super.afterAll()
    Play.stop(fakeApplication)
  }

  WsTestClient.withClient{ client =>

    "HttpCalls" should {

      "be gracefully timeout when no response is received within the 'timeout' frame" in {
        val http = new WSHttp with TestHttpCore {
          override val wsClient = fakeApplication.injector.instanceOf[WSClient]
        }

        // get an unused port
        val ss = new ServerSocket(0)
        ss.close()
        val executor = ExecutionContext.global // fromExecutorService(ExecutionContext.global)
        val publicUri = URI.create(s"http://localhost:${ss.getLocalPort}")
        val ws        = new NettyWebServer(executor, ss.getLocalSocketAddress, publicUri)
        try {
          //starts web server
          ws.add(
            "/test",
            new DelayedHttpHandler(executor, 2000, new StringHttpHandler("application/json", "{name:'pong'}")))
          ws.start().get()

          implicit val hc = HeaderCarrier()

          val start = System.currentTimeMillis()
          intercept[TimeoutException] {
            //make request to web server
            Await.result(http.doPost(s"$publicUri/test", "{name:'ping'}", Seq()), 5.seconds)
          }
          val diff = (System.currentTimeMillis() - start).toInt
          // there is test execution delay around 700ms
          diff should be >= 1000
          diff should be < 2500
        } finally {
          ws.stop()
        }
      }
    }
  }
} 
Example 8
Source File: HttpTimeoutSpec.scala    From http-verbs   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.play.http

import java.net.{ServerSocket, URI}
import java.util.concurrent.TimeoutException

import org.scalatest.concurrent.ScalaFutures
import org.scalatest.BeforeAndAfterAll
import org.scalatest.wordspec.AnyWordSpecLike
import org.scalatest.matchers.should.Matchers
import org.webbitserver.handler.{DelayedHttpHandler, StringHttpHandler}
import org.webbitserver.netty.NettyWebServer
import play.api.Play
import play.api.test.FakeApplication
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.http.ws.WSHttp
import uk.gov.hmrc.play.test.TestHttpCore

import scala.concurrent.Await
import scala.concurrent.duration.DurationInt
import scala.concurrent.ExecutionContext.Implicits.global

class HttpTimeoutSpec extends AnyWordSpecLike with Matchers with ScalaFutures with BeforeAndAfterAll {

  lazy val fakeApplication = FakeApplication(additionalConfiguration = Map("ws.timeout.request" -> "1000"))

  override def beforeAll() {
    super.beforeAll()
    Play.start(fakeApplication)
  }

  override def afterAll() {
    super.afterAll()
    Play.stop(fakeApplication)
  }

  "HttpCalls" should {

    "be gracefully timeout when no response is received within the 'timeout' frame" in {
      val http = new WSHttp with TestHttpCore

      // get an unused port
      val ss = new ServerSocket(0)
      ss.close()
      val publicUri = URI.create(s"http://localhost:${ss.getLocalPort}")
      val ws        = new NettyWebServer(global, ss.getLocalSocketAddress, publicUri)
      try {
        //starts web server
        ws.add(
          "/test",
          new DelayedHttpHandler(global, 2000, new StringHttpHandler("application/json", "{name:'pong'}")))
        ws.start().get()

        implicit val hc = HeaderCarrier()

        val start = System.currentTimeMillis()
        intercept[TimeoutException] {
          //make request to web server
          Await.result(http.doPost(s"$publicUri/test", "{name:'ping'}", Seq()), 5.seconds)
        }
        val diff = (System.currentTimeMillis() - start).toInt
        // there is test execution delay around 700ms
        diff should be >= 1000
        diff should be < 2500
      } finally {
        ws.stop()
      }
    }
  }
} 
Example 9
Source File: WsProxySpec.scala    From http-verbs   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.play.http.ws

import com.github.tomakehurst.wiremock.client.VerificationException
import com.github.tomakehurst.wiremock.client.WireMock._
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike
import org.scalatest.{BeforeAndAfterAll, OptionValues}
import org.scalatestplus.mockito.MockitoSugar
import play.api.Play
import play.api.libs.ws.WSProxyServer
import play.api.test.FakeApplication
import uk.gov.hmrc.http.HeaderCarrier

class WsProxySpec extends AnyWordSpecLike with Matchers with MockitoSugar with OptionValues with BeforeAndAfterAll {
  implicit val hc = HeaderCarrier()

  lazy val fakeApplication = FakeApplication()

  "A proxied get request" should {
    "correctly make a request via the specified proxy server" in new Setup {

      val wSProxyServer = mock[WSProxyServer]

      object ProxiedGet extends WSProxy {

        override def applicableHeaders(url: String)(implicit hc: HeaderCarrier): Seq[(String, String)] = Nil

        def wsProxyServer = Some(wSProxyServer)
      }

      val request = ProxiedGet.buildRequest("http://example.com", headers = Seq.empty)

      request.proxyServer.value shouldBe (wSProxyServer)
    }
  }

  "A proxied get request, without a defined proxy configuration, i.e. for use in environments where a proxy does not exist" should {
    "still work by making the request without using a proxy server" in new Setup {

      object ProxiedGet extends WSProxy {

        override def applicableHeaders(url: String)(implicit hc: HeaderCarrier): Seq[(String, String)] = Nil

        def wsProxyServer = None
      }

      val request = ProxiedGet.buildRequest("http://example.com", headers = Seq.empty)

      request.proxyServer shouldBe (None)
    }
  }

  class Setup extends WireMockEndpoints {

    val responseData = "ResourceABC"
    val resourcePath = s"/resource/abc"

    def endpointBaseUrl = s"http://localhost:$endpointPort"

    def fullResourceUrl = s"$endpointBaseUrl$resourcePath"

    def setupEndpointExpectations() {
      endpointMock.register(
        get(urlEqualTo(resourcePath))
          .willReturn(
            aResponse()
              .withHeader("Content-Type", "text/plain")
              .withBody(responseData)))

      proxyMock.register(
        get(urlMatching(resourcePath))
          .willReturn(aResponse().proxiedFrom(endpointBaseUrl)))
    }

    def assertEndpointWasCalled() {
      endpointMock.verifyThat(getRequestedFor(urlEqualTo(resourcePath)))
    }

    def assertCallViaProxy() {
      endpointMock.verifyThat(getRequestedFor(urlEqualTo(resourcePath)))
    }

    def assertProxyNotUsed() {
      a[VerificationException] should be thrownBy proxyMock.verifyThat(getRequestedFor(urlEqualTo(resourcePath)))
    }
  }

  override def beforeAll() {
    super.beforeAll()
    Play.start(fakeApplication)
  }

  override def afterAll() {
    super.afterAll()
    Play.stop(fakeApplication)
  }

} 
Example 10
Source File: WSRequest.scala    From http-verbs   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.play.http.ws

import com.github.ghik.silencer.silent
import play.api.libs.ws.{DefaultWSProxyServer, WSClient, WSProxyServer, WSRequest => PlayWSRequest }
import play.api.{Configuration, Play}
import uk.gov.hmrc.http.HeaderCarrier

trait WSRequest extends WSRequestBuilder {

  import play.api.libs.ws.WS

  @silent("deprecated")
  def wsClient: WSClient =
    WS.client(play.api.Play.current)

  def buildRequest[A](url: String, headers: Seq[(String, String)] = Seq.empty)(implicit hc: HeaderCarrier): PlayWSRequest =
    wsClient.url(url)
      .withHeaders(applicableHeaders(url)(hc): _*)
      .withHeaders(headers: _*)
}

trait WSProxy extends WSRequest {

  def wsProxyServer: Option[WSProxyServer]

  override def buildRequest[A](url: String, headers: Seq[(String, String)])(implicit hc: HeaderCarrier): PlayWSRequest =
    wsProxyServer match {
      case Some(proxy) => super.buildRequest(url, headers).withProxyServer(proxy)
      case None        => super.buildRequest(url, headers)
    }
}

object WSProxyConfiguration {

  def apply(configPrefix: String, configuration: Configuration): Option[WSProxyServer] = {
    val proxyRequired = configuration.getBoolean(s"$configPrefix.proxyRequiredForThisEnvironment").getOrElse(true)

    if (proxyRequired) Some(parseProxyConfiguration(configPrefix, configuration)) else None
  }

  @silent("deprecated")
  def apply(configPrefix: String): Option[WSProxyServer] =
    apply(configPrefix, play.api.Play.current.configuration)

  private def parseProxyConfiguration(configPrefix: String, configuration: Configuration) =
    DefaultWSProxyServer(
      protocol =
        configuration.getString(s"$configPrefix.protocol").orElse(throw ProxyConfigurationException("protocol")),
      host      = configuration.getString(s"$configPrefix.host").getOrElse(throw ProxyConfigurationException("host")),
      port      = configuration.getInt(s"$configPrefix.port").getOrElse(throw ProxyConfigurationException("port")),
      principal = configuration.getString(s"$configPrefix.username"),
      password  = configuration.getString(s"$configPrefix.password")
    )

  case class ProxyConfigurationException(key: String)
      extends RuntimeException(s"Missing proxy configuration - key '$key' not found")
} 
Example 11
Source File: layouts.scala    From play-ui   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.play.views.html

import play.api.Play
import uk.gov.hmrc.play.config.{AssetsConfig, GTMConfig, OptimizelyConfig}

package object layouts {

  

  private lazy val assetsConfig = Play.current.injector.instanceOf[AssetsConfig]

  private lazy val optimizelyConfig = Play.current.injector.instanceOf[OptimizelyConfig]

  private lazy val gtmConfig = Play.current.injector.instanceOf[GTMConfig]

  lazy val article             = new Article()
  lazy val attorney_banner     = new AttorneyBanner()
  lazy val betaBanner          = new BetaBanner()
  lazy val footer              = new Footer(assetsConfig)
  lazy val eu_exit_links       = new EuExitLinks()
  lazy val footer_links        = new FooterLinks()
  lazy val head                = new Head(optimizely_snippet, assetsConfig, gtmSnippet)
  lazy val header_nav          = new HeaderNav()
  lazy val loginStatus         = new LoginStatus()
  lazy val main_content        = new MainContent()
  lazy val main_content_header = new MainContentHeader()
  lazy val optimizely_snippet  = new OptimizelySnippet(optimizelyConfig)
  lazy val gtmSnippet          = new GTMSnippet(gtmConfig)
  lazy val serviceInfo         = new ServiceInfo()
  lazy val sidebar             = new Sidebar()

} 
Example 12
Source File: GenericErrors.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package error

import config.ConfigDecorator
import controllers.auth.requests.UserRequest
import play.api.Play
import play.api.i18n.Messages
import play.api.mvc.Result
import play.api.mvc.Results.{BadRequest, InternalServerError}
import uk.gov.hmrc.renderer.TemplateRenderer
import util.LocalPartialRetriever

object GenericErrors {

  implicit val templateRenderer: TemplateRenderer = Play.current.injector.instanceOf[TemplateRenderer]

  def badRequest(
    implicit request: UserRequest[_],
    configDecorator: ConfigDecorator,
    partialRetriever: LocalPartialRetriever,
    messages: Messages): Result =
    BadRequest(
      views.html.error(
        "global.error.BadRequest.title",
        Some("global.error.BadRequest.title"),
        List("global.error.BadRequest.message1", "global.error.BadRequest.message2")))

  def internalServerError(
    implicit request: UserRequest[_],
    configDecorator: ConfigDecorator,
    partialRetriever: LocalPartialRetriever,
    messages: Messages): Result =
    InternalServerError(
      views.html.error(
        "global.error.InternalServerError500.title",
        Some("global.error.InternalServerError500.title"),
        List("global.error.InternalServerError500.message")))
} 
Example 13
Source File: MockTemplateRenderer.scala    From nisp-frontend   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.nisp.utils

import org.scalatest.mock.MockitoSugar
import play.api.Mode.Mode
import play.api.i18n.Messages
import play.api.{Configuration, Play}
import play.twirl.api.Html
import uk.gov.hmrc.nisp.config.{LocalTemplateRenderer, WsAllMethods}

import scala.concurrent.duration._

object MockTemplateRenderer extends LocalTemplateRenderer {
  override lazy val templateServiceBaseUrl = "http://example.com/template/mustache"
  override val refreshAfter = 10 minutes
  override val wsHttp = MockitoSugar.mock[WsAllMethods]

  override def renderDefaultTemplate(path:String, content: Html, extraArgs: Map[String, Any])(implicit messages: Messages) = {
    Html(
      "<title>" + extraArgs("pageTitle") + "</title>"
        + "<sidebar>"+extraArgs("sidebar")+"</sidebar>"
        + "<navLinks>"+extraArgs("navLinks")+"</navLinks>"
        + displayUrBanner(extraArgs) +
        "<mainContentHeader>" +extraArgs("mainContentHeader")+ "</mainContentHeader>"
        + content)
  }

    def displayUrBanner(extraArgs: Map[String, Any]): String ={
      if(extraArgs.contains("fullWidthBannerTitle")){
        "<div id=full-width-banner>" + "<div class = \"full-width-banner__title\">" + extraArgs("fullWidthBannerTitle") + "</div>" + "<div id = fullWidthBannerLink>" + extraArgs("fullWidthBannerLink") +  "</div>"+ "<div>" + extraArgs("fullWidthBannerText")+ "</div>"+ "<div id = fullWidthBannerDismissText>"+extraArgs("fullWidthBannerDismissText")+"</div>"
      }
      else ""
    }

  override protected def mode: Mode = Play.current.mode
  override protected def runModeConfiguration: Configuration = Play.current.configuration
} 
Example 14
Source File: ApplicationConfig.scala    From nisp-frontend   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.nisp.config

import play.api.{Configuration, Play}
import play.api.Mode.Mode
import play.api.Play._
import uk.gov.hmrc.nisp.utils.Constants
import uk.gov.hmrc.play.config.ServicesConfig

trait ApplicationConfig {
  val assetsPrefix: String
  val betaFeedbackUrl: String
  val betaFeedbackUnauthenticatedUrl: String
  val analyticsToken: Option[String]
  val analyticsHost: String
  val ssoUrl: Option[String]
  val contactFormServiceIdentifier: String
  val contactFrontendPartialBaseUrl: String
  val reportAProblemPartialUrl: String
  val reportAProblemNonJSUrl: String
  val showGovUkDonePage: Boolean
  val govUkFinishedPageUrl: String
  val identityVerification: Boolean
  val postSignInRedirectUrl: String
  val notAuthorisedRedirectUrl: String
  val verifySignIn: String
  val verifySignInContinue: Boolean
  val ivUpliftUrl: String
  val ggSignInUrl: String
  val pertaxFrontendUrl: String
  val breadcrumbPartialUrl: String
  val showFullNI: Boolean
  val futureProofPersonalMax: Boolean
  val isWelshEnabled: Boolean
  val feedbackFrontendUrl: String
  val frontendTemplatePath: String
}

object ApplicationConfig extends ApplicationConfig with ServicesConfig {

  private def loadConfig(key: String) = configuration.getString(key).getOrElse(throw new Exception(s"Missing key: $key"))

  private val contactFrontendService = baseUrl("contact-frontend")
  private val contactHost = configuration.getString(s"contact-frontend.host").getOrElse("")

  override lazy val assetsPrefix: String = loadConfig(s"assets.url") + loadConfig(s"assets.version") + "/"
  override lazy val betaFeedbackUrl = s"${Constants.baseUrl}/feedback"
  override lazy val betaFeedbackUnauthenticatedUrl = betaFeedbackUrl
  override lazy val analyticsToken: Option[String] = configuration.getString(s"google-analytics.token")
  override lazy val analyticsHost: String = configuration.getString(s"google-analytics.host").getOrElse("auto")
  override lazy val ssoUrl: Option[String] = configuration.getString(s"portal.ssoUrl")
  lazy val frontendTemplatePath: String = configuration.getString("microservice.services.frontend-template-provider.path").getOrElse("/template/mustache")

  override val contactFormServiceIdentifier = "NISP"
  override lazy val contactFrontendPartialBaseUrl = s"$contactFrontendService"
  override lazy val reportAProblemPartialUrl = s"$contactHost/contact/problem_reports_ajax?service=$contactFormServiceIdentifier"
  override lazy val reportAProblemNonJSUrl = s"$contactHost/contact/problem_reports_nonjs?service=$contactFormServiceIdentifier"
  override val showGovUkDonePage: Boolean = configuration.getBoolean("govuk-done-page.enabled").getOrElse(true)
  override val govUkFinishedPageUrl: String = loadConfig("govuk-done-page.url")
  override val identityVerification: Boolean = configuration.getBoolean("microservice.services.features.identityVerification").getOrElse(false)

  override lazy val verifySignIn: String = configuration.getString("verify-sign-in.url").getOrElse("")
  override lazy val verifySignInContinue: Boolean = configuration.getBoolean("verify-sign-in.submit-continue-url").getOrElse(false)
  override lazy val postSignInRedirectUrl = configuration.getString("login-callback.url").getOrElse("")
  override lazy val notAuthorisedRedirectUrl = configuration.getString("not-authorised-callback.url").getOrElse("")
  override val ivUpliftUrl: String = configuration.getString(s"identity-verification-uplift.host").getOrElse("")
  override val ggSignInUrl: String = configuration.getString(s"government-gateway-sign-in.host").getOrElse("")

  val showUrBanner:Boolean = configuration.getBoolean("urBannerToggle").getOrElse(false)
  val GaEventAction: String = "home page UR"
  val isleManLink = runModeConfiguration.getString("isle-man-link.url")
  val citizenAdviceLinkEn = runModeConfiguration.getString("citizens-advice-link-en.url")
  val citizenAdviceLinkCy = runModeConfiguration.getString("citizens-advice-link-cy.url")
  val moneyAdviceLinkEn = runModeConfiguration.getString("money-advice-link-en.url")
  val moneyAdviceLinkCy = runModeConfiguration.getString("money-advice-link-cy.url")
  val pensionWiseLink = runModeConfiguration.getString("pension-wise-link.url")

  private val pertaxFrontendService: String = baseUrl("pertax-frontend")
  override lazy val pertaxFrontendUrl: String = configuration.getString(s"breadcrumb-service.url").getOrElse("")
  override lazy val breadcrumbPartialUrl: String = s"$pertaxFrontendService/personal-account/integration/main-content-header"
  override lazy val showFullNI: Boolean = configuration.getBoolean("microservice.services.features.fullNIrecord").getOrElse(false)
  override lazy val futureProofPersonalMax: Boolean = configuration.getBoolean("microservice.services.features.future-proof.personalMax").getOrElse(false)
  override val isWelshEnabled = configuration.getBoolean("microservice.services.features.welsh-translation").getOrElse(false)
  override val feedbackFrontendUrl: String = loadConfig("feedback-frontend.url")
  override protected def mode: Mode = Play.current.mode
  override protected def runModeConfiguration: Configuration = Play.current.configuration
} 
Example 15
Source File: LocalTemplateRenderer.scala    From nisp-frontend   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.nisp.config

import akka.actor.ActorSystem
import com.typesafe.config.Config
import play.api.{Configuration, Play}
import play.api.Mode.Mode
import uk.gov.hmrc.renderer.TemplateRenderer
import uk.gov.hmrc.play.config.{AppName, RunMode, ServicesConfig}
import uk.gov.hmrc.nisp.config.wiring.{NispAuditConnector, WSHttp}
import uk.gov.hmrc.play.audit.http.HttpAuditing
import uk.gov.hmrc.play.http.logging.MdcLoggingExecutionContext._

import scala.concurrent.Future
import scala.concurrent.duration._
import uk.gov.hmrc.http.HeaderCarrier

trait LocalTemplateRenderer extends TemplateRenderer with ServicesConfig {
  override lazy val templateServiceBaseUrl = baseUrl("frontend-template-provider")
  override val refreshAfter: Duration = 10 minutes
  private implicit val hc = HeaderCarrier()
  val wsHttp: WSHttp

  override def fetchTemplate(path: String): Future[String] =  {
    wsHttp.GET(path).map(_.body)
  }
}

object LocalTemplateRenderer extends LocalTemplateRenderer {
  override val wsHttp = WsAllMethods
  override protected def mode: Mode = Play.current.mode
  override protected def runModeConfiguration: Configuration = Play.current.configuration
}

trait WsAllMethods extends WSHttp with HttpAuditing with AppName with RunMode

object WsAllMethods extends WsAllMethods {
  override lazy val auditConnector = NispAuditConnector
  override val hooks = Seq (AuditingHook)

  override protected def appNameConfiguration: Configuration = Play.current.configuration
  override protected def mode: Mode = Play.current.mode
  override protected def runModeConfiguration: Configuration = Play.current.configuration
  override protected def actorSystem: ActorSystem = Play.current.actorSystem
  override protected def configuration: Option[Config] = Option(Play.current.configuration.underlying)
} 
Example 16
Source File: ApplicationGlobal.scala    From nisp-frontend   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.nisp.config

import com.typesafe.config.Config
import net.ceedubs.ficus.Ficus._
import play.api.Mode.Mode
import play.api.i18n.{I18nSupport, Messages, MessagesApi}
import play.api.mvc.Request
import play.api.{Application, Configuration, Play}
import play.twirl.api.Html
import uk.gov.hmrc.crypto.ApplicationCrypto
import uk.gov.hmrc.nisp.config.wiring.NispAuditConnector
import uk.gov.hmrc.nisp.controllers.NispFrontendController
import uk.gov.hmrc.nisp.controllers.partial.PartialRetriever
import uk.gov.hmrc.play.config.{AppName, ControllerConfig, RunMode}
import uk.gov.hmrc.play.frontend.bootstrap.DefaultFrontendGlobal
import uk.gov.hmrc.play.frontend.filters.{FrontendAuditFilter, FrontendLoggingFilter, MicroserviceFilterSupport}

object ApplicationGlobal extends ApplicationGlobalTrait {
  override protected def mode: Mode = Play.current.mode
  override protected def runModeConfiguration: Configuration = Play.current.configuration
  override def messagesApi = Play.current.injector.instanceOf[MessagesApi]
}

trait ApplicationGlobalTrait extends DefaultFrontendGlobal with RunMode with PartialRetriever with NispFrontendController with I18nSupport {

  implicit lazy val app:Application = Play.current

  override val auditConnector = NispAuditConnector
  override val loggingFilter = NispLoggingFilter
  override val frontendAuditFilter = NispFrontendAuditFilter

  override def onStart(app: Application) {
    super.onStart(app)
    new ApplicationCrypto(Play.current.configuration.underlying).verifyConfiguration()
  }

  override def internalServerErrorTemplate(implicit request: Request[_]): Html =
    uk.gov.hmrc.nisp.views.html.service_error_500()

  override def standardErrorTemplate(pageTitle: String, heading: String, message: String)(implicit request: Request[_]): Html =
    uk.gov.hmrc.nisp.views.html.global_error(pageTitle, heading, message)

  override def notFoundTemplate(implicit request: Request[_]): Html = {
    uk.gov.hmrc.nisp.views.html.page_not_found_template()
  }

  override def microserviceMetricsConfig(implicit app: Application): Option[Configuration] = app.configuration.getConfig(s"microservice.metrics")
}

object ControllerConfiguration extends ControllerConfig {
  lazy val controllerConfigs = Play.current.configuration.underlying.as[Config]("controllers")
}

object NispLoggingFilter extends FrontendLoggingFilter with MicroserviceFilterSupport {
  override def controllerNeedsLogging(controllerName: String): Boolean = ControllerConfiguration.paramsForController(controllerName).needsLogging
}

object NispFrontendAuditFilter extends FrontendAuditFilter with RunMode with AppName with MicroserviceFilterSupport {
  override lazy val maskedFormFields = Seq.empty
  override lazy val applicationPort = None
  override lazy val auditConnector = NispAuditConnector
  override def controllerNeedsAuditing(controllerName: String): Boolean = ControllerConfiguration.paramsForController(controllerName).needsAuditing
  override protected def mode: Mode = Play.current.mode
  override protected def runModeConfiguration: Configuration = Play.current.configuration
  override protected def appNameConfiguration: Configuration = Play.current.configuration
} 
Example 17
Source File: WSHttp.scala    From nisp-frontend   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.nisp.config.wiring

import akka.actor.ActorSystem
import com.typesafe.config.Config
import play.api.{Configuration, Play}
import uk.gov.hmrc.http._
import uk.gov.hmrc.http.hooks.HttpHooks
import uk.gov.hmrc.play.audit.http.HttpAuditing
import uk.gov.hmrc.play.audit.http.connector.AuditConnector
import uk.gov.hmrc.play.config.AppName
import uk.gov.hmrc.play.http.ws.{WSDelete, WSGet, WSPost, WSPut}

trait WSHttp extends HttpGet with WSGet with HttpPut with WSPut with HttpPost with WSPost with HttpDelete with WSDelete with Hooks with AppName

object WSHttp extends WSHttp {
  override protected def appNameConfiguration: Configuration = Play.current.configuration
  override protected def actorSystem: ActorSystem = Play.current.actorSystem
  override protected def configuration: Option[Config] = Option(Play.current.configuration.underlying)
}

trait Hooks extends HttpHooks with HttpAuditing {
  override val hooks = Seq(AuditingHook)
  override lazy val auditConnector: AuditConnector = NispAuditConnector
} 
Example 18
Source File: ExclusionController.scala    From nisp-frontend   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.nisp.controllers

import play.api.Play.current
import play.api.i18n.Messages.Implicits._
import play.api.mvc.{Action, AnyContent}
import play.api.{Logger, Play}
import uk.gov.hmrc.nisp.config.wiring.{NationalInsuranceService, StatePensionService}
import uk.gov.hmrc.nisp.controllers.auth.{AuthDetails, ExcludedAuthAction, ExcludedAuthActionImpl}
import uk.gov.hmrc.nisp.controllers.partial.PartialRetriever
import uk.gov.hmrc.nisp.models.enums.Exclusion
import uk.gov.hmrc.nisp.services._
import uk.gov.hmrc.nisp.views.html._

object ExclusionController extends ExclusionController with PartialRetriever with NispFrontendController {
  override val statePensionService: StatePensionService = StatePensionService
  override val authenticate: ExcludedAuthActionImpl = Play.current.injector.instanceOf[ExcludedAuthActionImpl]
  override val nationalInsuranceService: NationalInsuranceService = NationalInsuranceService
}

trait ExclusionController extends NispFrontendController {

  val statePensionService: StatePensionService
  val nationalInsuranceService: NationalInsuranceService
  val authenticate: ExcludedAuthAction

  def showSP: Action[AnyContent] = authenticate.async {
    implicit request =>
      implicit val authDetails: AuthDetails = request.authDetails

      val statePensionF = statePensionService.getSummary(request.nino)
      val nationalInsuranceF = nationalInsuranceService.getSummary(request.nino)

      for (
        statePension <- statePensionF;
        nationalInsurance <- nationalInsuranceF
      ) yield {
        statePension match {
          case Right(sp) if sp.reducedRateElection =>
            Ok(excluded_sp(Exclusion.MarriedWomenReducedRateElection, Some(sp.pensionAge), Some(sp.pensionDate), false, None))
          case Left(exclusion) =>
            if (exclusion.exclusion == Exclusion.Dead)
              Ok(excluded_dead(Exclusion.Dead, exclusion.pensionAge))
            else if (exclusion.exclusion == Exclusion.ManualCorrespondenceIndicator)
              Ok(excluded_mci(Exclusion.ManualCorrespondenceIndicator, exclusion.pensionAge))
            else {
              Ok(excluded_sp(exclusion.exclusion, exclusion.pensionAge, exclusion.pensionDate, nationalInsurance.isRight, exclusion.statePensionAgeUnderConsideration))
            }
          case _ =>
            Logger.warn("User accessed /exclusion as non-excluded user")
            Redirect(routes.StatePensionController.show())
        }
      }
  }

  def showNI: Action[AnyContent] = authenticate.async {
    implicit request =>
      implicit val authDetails: AuthDetails = request.authDetails
      nationalInsuranceService.getSummary(request.nino).map {
        case Left(exclusion) =>
          if (exclusion == Exclusion.Dead) {
            Ok(excluded_dead(Exclusion.Dead, None))
          }
          else if (exclusion == Exclusion.ManualCorrespondenceIndicator) {
            Ok(excluded_mci(Exclusion.ManualCorrespondenceIndicator, None))
          } else {
            Ok(excluded_ni(exclusion))
          }
        case _ =>
          Logger.warn("User accessed /exclusion/nirecord as non-excluded user")
          Redirect(routes.NIRecordController.showGaps())
      }
  }
} 
Example 19
Source File: KBModule.scala    From daf-semantics   with Apache License 2.0 5 votes vote down vote up
package modules

import javax.inject._

import play.api.inject.ApplicationLifecycle
import play.api.mvc._

import scala.concurrent.Future
import com.google.inject.ImplementedBy
import play.api.Play
import play.api.Application
import play.api.Environment
import play.api.Configuration
import scala.concurrent.ExecutionContext
import play.api.Logger
import it.almawave.linkeddata.kb.utils.ConfigHelper
import it.almawave.linkeddata.kb.repo._
import scala.concurrent.ExecutionContext.Implicits.global
import java.nio.file.Paths
import play.api.Mode
import java.io.File
import it.almawave.linkeddata.kb.repo.RDFRepository
import com.typesafe.config.ConfigFactory

@ImplementedBy(classOf[KBModuleBase])
trait KBModule

@Singleton
class KBModuleBase @Inject() (lifecycle: ApplicationLifecycle) extends KBModule {

  // TODO: SPI per dev / prod
  val kbrepo = RDFRepository.memory()

  val logger = Logger.underlyingLogger

  // when application starts...
  @Inject
  def onStart(
    env: Environment,
    configuration: Configuration)(implicit ec: ExecutionContext) {

    // get configs
    val app_type = configuration.underlying.getString("app.type")

    val data_dir = app_type match {
      case "dev"  => "./dist/data"
      case "prod" => "./data"
    }
    logger.debug(s"app_type: ${app_type}")
    logger.debug(s"data_dir: ${data_dir}")

    // starting VocabularyAPI service
    var conf_voc = ConfigFactory.parseFile(new File("./conf/semantic_repository.conf").getAbsoluteFile)
    conf_voc = ConfigHelper.injectParameters(conf_voc, ("data_dir", data_dir))

    kbrepo.configuration(conf_voc)

    logger.info("KBModule.START....")
    logger.debug("KBModule using configuration:\n" + ConfigHelper.pretty(conf_voc))

    println("KBModule using configuration:\n" + ConfigHelper.pretty(conf_voc))

    // this is needed for ensure proper connection(s) etc
    kbrepo.start()

    

    // CHECK the initial (total) triples count
    var triples = kbrepo.store.size()

    logger.info(s"KBModule> ${triples} triples loaded")

  }

  // when application stops...
  lifecycle.addStopHook({ () =>

    Future.successful {

      // this is useful for saving files, closing connections, release indexes, etc
      kbrepo.stop()
      logger.info("KBModule.STOP....")

    }

  })

} 
Example 20
Source File: Config.scala    From incubator-s2graph   with Apache License 2.0 5 votes vote down vote up
package org.apache.s2graph.rest.play.config

import play.api.Play

object Config {
  // HBASE
  lazy val HBASE_ZOOKEEPER_QUORUM = conf.getString("hbase.zookeeper.quorum").getOrElse("localhost")


  // HBASE CLIENT
  lazy val ASYNC_HBASE_CLIENT_FLUSH_INTERVAL = conf.getInt("async.hbase.client.flush.interval").getOrElse(1000).toShort
  lazy val RPC_TIMEOUT = conf.getInt("hbase.client.operation.timeout").getOrElse(1000)
  lazy val MAX_ATTEMPT = conf.getInt("hbase.client.operation.maxAttempt").getOrElse(3)

  // PHASE
  lazy val PHASE = conf.getString("phase").getOrElse("dev")
  lazy val conf = Play.current.configuration

  // CACHE
  lazy val CACHE_TTL_SECONDS = conf.getInt("cache.ttl.seconds").getOrElse(600)
  lazy val CACHE_MAX_SIZE = conf.getInt("cache.max.size").getOrElse(10000)

  //KAFKA
  lazy val KAFKA_METADATA_BROKER_LIST = conf.getString("kafka.metadata.broker.list").getOrElse("localhost")

  lazy val KAFKA_LOG_TOPIC = s"s2graphIn${PHASE}"
  lazy val KAFKA_LOG_TOPIC_JSON = s"s2graphIn${PHASE}Json"
  lazy val KAFKA_LOG_TOPIC_ASYNC = s"s2graphIn${PHASE}Async"
  lazy val KAFKA_LOG_TOPIC_ASYNC_JSON = s"s2graphIn${PHASE}AsyncJson"
  lazy val KAFKA_FAIL_TOPIC = s"s2graphIn${PHASE}Failed"
  lazy val KAFKA_FAIL_TOPIC_JSON = s"s2graphIn${PHASE}FailedJson"
  lazy val KAFKA_MUTATE_FAIL_TOPIC = s"mutateFailed_${PHASE}"

  // is query or write
  lazy val IS_QUERY_SERVER = conf.getBoolean("is.query.server").getOrElse(true)
  lazy val IS_WRITE_SERVER = conf.getBoolean("is.write.server").getOrElse(true)


  // query limit per step
  lazy val QUERY_HARD_LIMIT = conf.getInt("query.hard.limit").getOrElse(300)

  // local queue actor
  lazy val LOCAL_QUEUE_ACTOR_MAX_QUEUE_SIZE = conf.getInt("local.queue.actor.max.queue.size").getOrElse(10000)
  lazy val LOCAL_QUEUE_ACTOR_RATE_LIMIT = conf.getInt("local.queue.actor.rate.limit").getOrElse(1000)
} 
Example 21
Source File: JsonBodyParser.scala    From incubator-s2graph   with Apache License 2.0 5 votes vote down vote up
package org.apache.s2graph.rest.play.controllers

import akka.util.ByteString
import org.apache.s2graph.core.utils.logger
import play.api.Play
import play.api.libs.iteratee.Iteratee
import play.api.libs.json.{JsValue, Json}
import play.api.libs.streams.Streams
import play.api.mvc._

import scala.concurrent.Future
import scala.util.control.NonFatal

object s2parse extends BodyParsers {

  import parse._

  val defaultMaxTextLength = 1024 * 512
  val defaultMaxJsonLength = 1024 * 512

  def json: BodyParser[JsValue] = json(defaultMaxTextLength)

  
  def jsonText: BodyParser[String] = when(
    _.contentType.exists(m => m.equalsIgnoreCase("text/json") || m.equalsIgnoreCase("application/json")),
    jsonText(defaultMaxTextLength),
    createBadResult("Expecting text/json or application/json body")
  )

  private def jsonText(maxLength: Int): BodyParser[String] = BodyParser("json, maxLength=" + maxLength) { request =>
    import play.api.libs.iteratee.Execution.Implicits.trampoline
    import play.api.libs.iteratee.Traversable

    val iteratee = Traversable.takeUpTo[ByteString](maxLength)
      .transform(Iteratee.consume[ByteString]().map(_.utf8String))
      .flatMap(Iteratee.eofOrElse(Results.EntityTooLarge))

    Streams.iterateeToAccumulator(iteratee)
  }

  def json(maxLength: Int): BodyParser[JsValue] = when(
    _.contentType.exists(m => m.equalsIgnoreCase("text/json") || m.equalsIgnoreCase("application/json")),
    tolerantJson(maxLength),
    createBadResult("Expecting text/json or application/json body")
  )

  def tolerantJson(maxLength: Int): BodyParser[JsValue] =
    tolerantBodyParser[JsValue]("json", maxLength, "Invalid Json") { (request, bytes) =>
      // Encoding notes: RFC 4627 requires that JSON be encoded in Unicode, and states that whether that's
      // UTF-8, UTF-16 or UTF-32 can be auto detected by reading the first two bytes. So we ignore the declared
      // charset and don't decode, we passing the byte array as is because Jackson supports auto detection.
      Json.parse(bytes)
    }

  private def tolerantBodyParser[A](name: String, maxLength: Int, errorMessage: String)(parser: (RequestHeader, Array[Byte]) => A): BodyParser[A] =
    BodyParser(name + ", maxLength=" + maxLength) { request =>
      import play.api.libs.iteratee.Execution.Implicits.trampoline
      import play.api.libs.iteratee.Traversable

      import scala.util.control.Exception._

      val bodyParser: Iteratee[ByteString, Either[Result, Either[Future[Result], A]]] =
        Traversable.takeUpTo[ByteString](maxLength).transform(
          Iteratee.consume[ByteString]().map { bytes =>
            allCatch[A].either {
              parser(request, bytes.toByteBuffer.array())
            }.left.map {
              case NonFatal(e) =>
                val txt = bytes.utf8String
                logger.error(s"$errorMessage: $txt", e)
                createBadResult(s"$errorMessage: $e")(request)
              case t => throw t
            }
          }
        ).flatMap(Iteratee.eofOrElse(Results.EntityTooLarge))

      Streams.iterateeToAccumulator(bodyParser).mapFuture {
        case Left(tooLarge) => Future.successful(Left(tooLarge))
        case Right(Left(badResult)) => badResult.map(Left.apply)
        case Right(Right(body)) => Future.successful(Right(body))
      }
    }

  private def createBadResult(msg: String): RequestHeader => Future[Result] = { request =>
    Play.maybeApplication.map(_.global.onBadRequest(request, msg))
      .getOrElse(Future.successful(Results.BadRequest))
  }
}