KtorMiddleCoding
Как реализовать CORS в приложении Ktor?
Устанавливайте плагин CORS через install(CORS) { allowHost(...); allowMethod(...); allowHeader(...) }. При allowCredentials = true нельзя использовать anyHost() — браузер требует точный Origin в ответе.
CORS в Ktor: плагин и его конфигурация
Ktor реализует CORS через встроенный плагин CORS из артефакта ktor-server-cors. Плагин перехватывает preflight-запросы (OPTIONS) и добавляет нужные заголовки к реальным ответам, не требуя ручной обработки в каждом маршруте.
Подключение зависимости
// build.gradle.kts
dependencies {
implementation("io.ktor:ktor-server-cors:2.3.12")
}
Базовая конфигурация
import io.ktor.server.application.*
import io.ktor.server.plugins.cors.routing.*
import io.ktor.http.*
fun Application.configureHTTP() {
install(CORS) {
// Разрешённые источники
allowHost("example.com", schemes = listOf("https"))
allowHost("localhost:3000", schemes = listOf("http"))
// Разрешённые HTTP-методы
allowMethod(HttpMethod.Get)
allowMethod(HttpMethod.Post)
allowMethod(HttpMethod.Put)
allowMethod(HttpMethod.Delete)
allowMethod(HttpMethod.Patch)
// Разрешённые заголовки запроса
allowHeader(HttpHeaders.ContentType)
allowHeader(HttpHeaders.Authorization)
allowHeader("X-Custom-Header")
// Разрешить передачу куки и заголовков авторизации
allowCredentials = true
// Заголовки, которые браузер может читать из ответа
exposeHeader(HttpHeaders.ContentDisposition)
// Время жизни preflight-кэша в браузере (сек)
maxAgeInSeconds = 3600L
}
}
Разрешить все источники (только для разработки)
install(CORS) {
anyHost() // НЕ использовать в продакшне
allowMethod(HttpMethod.Get)
allowMethod(HttpMethod.Post)
allowHeader(HttpHeaders.ContentType)
}
Паттерн wildcard-поддомена
Ktor не поддерживает wildcards вида *.example.com нативно. Для динамической проверки источника используйте allowOrigins { origin -> ... }:
install(CORS) {
allowOrigins { origin ->
origin.endsWith(".example.com") || origin == "https://example.com"
}
allowMethod(HttpMethod.Get)
allowHeader(HttpHeaders.ContentType)
allowCredentials = true
}
Конфигурация через application.conf (HOCON)
ktor {
application {
modules = [ com.example.ApplicationKt.module ]
}
}
cors {
allowedHosts = ["example.com", "localhost:3000"]
}
Затем в коде читайте через environment.config.property("cors.allowedHosts").getList() и динамически вызывайте allowHost().
Важные нюансы работы плагина
- Плагин устанавливается глобально и применяется ко всем маршрутам. Для route-level CORS нужно оборачивать роутинг вручную.
- Preflight (
OPTIONS) перехватывается плагином и не достигает ваших обработчиков. - При
allowCredentials = trueбраузер требует точного указанияAccess-Control-Allow-Origin;anyHost()в этом режиме недопустим.
Подводные камни
anyHost()совместно сallowCredentials = trueзапрещён спецификацией CORS и вызовет исключение при старте в Ktor 2.x.- Если не добавить
allowHeader(HttpHeaders.ContentType), запросы с JSON-телом (типapplication/json) будут блокироваться как нераспознанные preflight. - Заголовки ответа, не перечисленные в
exposeHeader(), недоступны JavaScript-клиенту даже при правильном CORS. - CORS-плагин необходимо устанавливать до плагина
Authentication, иначе preflight может получить401вместо204. - Ktor проверяет заголовок
Originстрого:http://localhost:3000иhttp://localhost:3000/с трейлинг-слешем — разные строки. - В Ktor 2.x метод называется
allowOrigins { }, а неhost()из Ktor 1.x — при миграции старые проекты ломаются сUnresolved reference. - При
maxAgeInSecondsбраузер кэширует preflight-ответ; изменение CORS-политики на сервере не сразу отражается у клиентов без hard refresh. - Wildcard
*вAccess-Control-Allow-Headersне работает в IE и некоторых мобильных браузерах — явно перечисляйте каждый заголовок.
Common mistakes
- Путать термин «ktor cors» с соседним механизмом Ktor.
- Не называть границу lifecycle, transaction, thread или request для «ktor cors».
- Игнорировать production-эффекты «ktor cors»: latency, SQL shape, memory, security или observability.
What the interviewer is testing
- Попросить объяснить механизм «ktor cors» на минимальном примере.
- Проверить, видит ли кандидат failure mode и диагностику для «ktor cors».
- Уточнить, какие настройки или API меняют «ktor cors» в реальном сервисе.