Search code examples
kotlinherokucorsktor

CORS problems with Ktor on Heroku but not on local


So I just deployed my app on Heroku. I have an application where the front end sends a log in request to the back end. But I cant get rid of the CORS problem on the Heroku side (no problem on the local side).

My frontend is on https://yourclimbfrontend.herokuapp.com/

And this is how I adjust my CORS:

fun Application.configureHTTP() {
    install(CORS) {
        allowMethod(HttpMethod.Options)
        allowMethod(HttpMethod.Put)
        allowMethod(HttpMethod.Delete)
        allowMethod(HttpMethod.Get)
        allowMethod(HttpMethod.Patch)
        allowHeader(HttpHeaders.Authorization)
        allowHeader("cart_session")
        exposeHeader("cart_session")
        allowHeader("MyCustomHeader")
        allowHeader("X-Requested-With")
        allowHeader("X-HTTP-Method-Override")
        allowHeader("Content-Type")
        allowHeader("Authorization")
        allowHeader("Accept")
        allowHeader("Access-Control-Allow-Credentials")
        allowHeader("Accept")
        allowHeader("Access-Control-Allow-Origin")
        allowHost("https://yourclimbfrontend.herokuapp.com")
      //  allowHost("localhost:3000")'
       // anyHost()

    }
}

It works on my local machine if I have the localHost:3000 on and it works on the Heroku side if I have the anyHost() on. But I have read that one should avoid anyHost() so Im trying to only let https://yourclimbfrontend.herokuapp.com send requests.

Am I using the wrong link some how in the allowHost? Or do I need additional lines for allowing Heroku?


Solution

  • It may not be intuitive, but Ktor's CORS middleware expects you to specify the allowed hosts separately from the associated scheme(s). Accordingly, instead of

    install(CORS) {
      // omitted
      allowHost("https://yourclimbfrontend.herokuapp.com")
      // omitted
    }
    
    install(CORS) {
      // omitted
      allowHost("yourclimbfrontend.herokuapp.com", schemes = listOf("https"))
      // omitted
    }
    

    Besides, you can safely drop the following two lines from your CORS config

    allowHeader("Access-Control-Allow-Credentials")
    allowHeader("Access-Control-Allow-Origin")
    

    as those two headers are response headers, not request headers.