Search code examples
playframeworktypesafe-confighocon

Typesafe config HOCON - guidance for environment variable replacement of lists?


Here's what I end up using, because I cannot seem to get the variable replacement in good order. Given the Play Framework HOCON section for CORS Allowed Origins, which allows for local, dev, stage and production deployment, and is NOT 12-factor compliant:

play {
  # https://www.playframework.com/documentation/2.5.x/resources/confs/filters-helpers/reference.conf
  filters {
    # use default values for gzip, csrf & security headers
    # setup cors
    cors {
      # whitelist all paths
      pathPrefixes = ["/"]
      allowedOrigins = [
        "http://localhost:8080"
        "http://app.127.0.0.1.nip.io:8080"
        "http://app.192.168.64.2.nip.io"
        "http://app.192.168.42.173.nip.io"
        "http://app.terradatum.local"
        "http://app.dev.terradatum.com"
        "https://app.dev.terradatum.com"
        "http://app.stage.terradatum.com"
        "https://app.stage.terradatum.com"
        "http://app.terradatum.com"
        "https://app.terradatum.com"
      ]
    }
  }
}

I've tried both of the following HOCON, with the environment being set as shown as well:

# HOCON
allowedOrigins = ${?APP_ALLOWED_ORIGINS}
# ENV
export APP_ALLOWED_ORIGINS='"http://app.127.0.0.1.nip.io:8080","http://app.192.168.64.2.nip.io","http://app.192.168.42.173.nip.io","http://app.terradatum.local","http://app.dev.terradatum.com","https://app.dev.terradatum.com","http://app.stage.terradatum.com","https://app.stage.terradatum.com","http://app.terradatum.com","https://app.terradatum.com"'

And...

# HOCON
allowedOrigins = [
  ${?APP_ALLOWED_ORIGINS}
  "http://app.127.0.0.1.nip.io:8080"
  "http://app.192.168.64.2.nip.io"
  "http://app.192.168.42.173.nip.io"
  "http://app.terradatum.local"
  "http://app.dev.terradatum.com"
  "https://app.dev.terradatum.com"
  "http://app.stage.terradatum.com"
  "https://app.stage.terradatum.com"
  "http://app.terradatum.com"
  "https://app.terradatum.com"
]
# ENV
export APP_ALLOWED_ORIGINS="http://some-new-cors.terradatum.com\nhttps://some-new-cors.terradatum.com\n"

Many other CORS implementations allow for regex, and WTH doesn't play?

That aside, the HOCON processing of Lists has been very problematic for me... with the first implementation above working, but any iteration where I have an existing, default list in the application.conf failing...

What's the recommended method of adding lists or list items to HOCON via Environment Variable replacement?


Solution

  • If I read your Post (I don't see a real "question" in there) correct, you're trying to find a way to add different values to your CORS list, depending on which environment your app is running.

    I would suggest to tackle this from another perspective: Create different configuration files which contain the values you want to customise and include the general application.conf file. In your deployment configuration, make play load your staged configuration instead of application.conf.

    e.g. if you create your dev-stage, add this to your deployment configuration (assuming you're using sbt-native-packager with docker)

    javaOptions in Universal ++= Seq(
      "-Dconfig.resource=application.dev.conf"
    )
    

    your application.dev.conf file would look like this:

    include "application.conf"
    play.filters.cors {
          # whitelist all paths
          pathPrefixes = ["/"]
          allowedOrigins = [
            "http://localhost:8080"
            "http://app.127.0.0.1.nip.io:8080"
            "http://app.192.168.64.2.nip.io"
            "http://app.192.168.42.173.nip.io"
            "http://app.terradatum.local"
            "http://app.dev.terradatum.com"
            "https://app.dev.terradatum.com"
    
          ]
        }
    

    the problem is, that your environment variable is not a list but a string.. there are no transformation methods in HOCON that would split up your string into a list.

    To follow the 12-factor approach, you could try to split up (the changing parts of) your list into something like

    ORIGIN_1=http://localhost:8080
    ORIGIN_2=http://app.127.0.0.1.nip.io:8080
    

    and then include those in your configuration like

    play.filters.cors.allowedOrigins = [${?ORIGIN_1}] ${play.filters.cors.allowedOrigins}
    play.filters.cors.allowedOrigins = [${?ORIGIN_2}] ${play.filters.cors.allowedOrigins}