Repository: ktorio/ktor
File: ktor-server/ktor-server-plugins/ktor-server-cors/common/src/io/ktor/server/plugins/cors/CORS.kt (Kotlin)

Code before:
        }

        if (call.request.httpMethod == HttpMethod.Options) {
            LOGGER.trace { "${call.request.id()}: Start preflight handler" }
            call.respondPreflight(
                origin,
                methodsListHeaderValue,
                headersList,
                methods,
                allowsAnyHost,
                allowCredentials,
                maxAgeHeaderValue,
                headerPredicates,
                allHeadersSet
            )
            return@onCall
        }

        if (!call.corsCheckCurrentMethod(methods)) {
            LOGGER.trace {
                "${call.request.id()}: CORS check fails because HTTP method ${call.request.httpMethod.value} " +
                    "is not allowed. Allowed methods: $methods"
            }
            call.respondCorsFailed()
            return@onCall
        }

        LOGGER.trace { "${call.request.id()}: CORS check is succeeded" }

        call.accessControlAllowOrigin(origin, allowsAnyHost, allowCredentials)
        call.accessControlAllowCredentials(allowCredentials)

        if (exposedHeaders != null) {
            call.response.header(HttpHeaders.AccessControlExposeHeaders, exposedHeaders)
        }
    }
}

internal fun ApplicationRequest.id(): String {
    return "${httpMethod.value} $uri"
}

private enum class OriginCheckResult {
    OK,
    SkipCORS,
    Failed,
}

private fun checkOrigin(
    origin: String,
    request: ApplicationRequest,

Review comment (bug):
I think for all the failure scenarios we ought to use severity INFO so it's more generally presented in the logs.

Code after:
        }

        if (call.request.httpMethod == HttpMethod.Options) {
            LOGGER.info { "${call.request.id()}: Start preflight handler" }
            call.respondPreflight(
                origin,
                methodsListHeaderValue,
                headersList,
                methods,
                allowsAnyHost,
                allowCredentials,
                maxAgeHeaderValue,
                headerPredicates,
                allHeadersSet
            )
            return@onCall
        }

        if (!call.corsCheckCurrentMethod(methods)) {
            LOGGER.info {
                "${call.request.id()}: CORS check fails because HTTP method ${call.request.httpMethod.value} " +
                    "is not allowed. Allowed methods: $methods"
            }
            call.respondCorsFailed()
            return@onCall
        }

        LOGGER.info { "${call.request.id()}: CORS check is succeeded" }

        call.accessControlAllowOrigin(origin, allowsAnyHost, allowCredentials)
        call.accessControlAllowCredentials(allowCredentials)

        if (exposedHeaders != null) {
            call.response.header(HttpHeaders.AccessControlExposeHeaders, exposedHeaders)
        }
    }
}

internal fun ApplicationRequest.id(): String {
    return "${httpMethod.value} $uri"
}

private enum class OriginCheckResult {
    OK,
    SkipCORS,
    Failed,
}

private fun checkOrigin(
    origin: String,
    request: ApplicationRequest,