CORS

Cross-Origin Resource Sharing allows to control which resources browsers are allowed to access and how they are allowed to do so. For example, if you would like to access a webservice from a website hosted on another domain, the browser will send the Origin header along with requests to the webservice and analyze the response to determine, whether the server allows clients to access the resource from this origin.

To allow all clients to access a resource with no restrictions, you can add a permissive policy to your handler:

Kotlin
import org.genhttp.modules.layouting.Layout
import org.genhttp.modules.security.CorsPolicy
import org.genhttp.modules.webservices.ResourceMethod
import org.genhttp.modules.webservices.addService

class BookResource {

    @ResourceMethod
    fun list(): List<String> = listOf("Dune", "Hyperion")

}

class AuthorResource {

    @ResourceMethod
    fun list(): List<String> = listOf("Frank Herbert", "Dan Simmons")

}

val api = Layout.create()
    .addService<BookResource>("books")
    .addService<AuthorResource>("authors")
    .add(CorsPolicy.permissive())

This will set the required headers for requests as well as preflight requests (which are answered with 204 No Content). By default, the permissive policy allows the Authorization header to be sent - pass allowAuthorization = false to leave it out. To restrict the access to a specific origin, create a restrictive() policy and add the configuration for the desired origin:

Kotlin
val policy = CorsPolicy.restrictive()
    .add("https://mydomain.com", allowedMethods = null, allowedHeaders = null, exposedHeaders = null, allowCredentials = true)

val api = Layout.create()
    .add(policy)

Passing null for the methods or headers allows any of them. Instead of these arguments, you may also pass an OriginPolicy, which additionally specifies how long browsers may cache the policy (maxAge in seconds, a day by default).

This way, browsers will deny requests that do not originate from https://mydomain.com. For development purposes, you may combine the snippets above - as Kotlin has no preprocessor directives, decide at runtime, e.g. by an environment variable:

Kotlin
val development = System.getenv("APP_ENVIRONMENT") == "development"

val policy = if (development) {
    CorsPolicy.permissive()
} else {
    CorsPolicy.restrictive().add("https://mydomain.com", null, null, null, true)
}