У меня есть демо-проект, в котором я тестирую различные архитектурные подходы, шаблоны и технологии для Android. В настоящее время я работаю над серверной частью, используя Kotlin Multiplatform, и столкнулся с технической проблемой, которую не могу решить самостоятельно. Вот задача: у меня есть сервер Ktor, который по запросу возвращает список объектов:
fun main() {
embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = Application::module)
.start(wait = true)
}
fun Application.module() {
routing {
get("/repos/octocat/Spoon-Knife/forks") {
call.respondText(forksJson(), ContentType.Application.Json, HttpStatusCode.OK)
}
}
}
И клиент — сайт, который также использует Ktor для отправки запросов на сервер для получения списка объектов:
HttpClient {
install(ContentNegotiation) {
json(Json {
prettyPrint = true
isLenient = true
ignoreUnknownKeys = true
})
}
}
Я запускаю сервер и веб-приложение на одном ноутбуке (macOS). При попытке выполнить запрос получаю следующую ошибку:
Access to fetch at 'http://localhost:8080/repos/octocat/Spoon-Knife/forks' from origin 'http://localhost:8081' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Я пробовал разные решения, например настройку CORS на сервере:
install(CORS) {
allowMethod(HttpMethod.Options)
allowMethod(HttpMethod.Get)
allowMethod(HttpMethod.Post)
allowHeader(HttpHeaders.XForwardedProto)
allowHeader(HttpHeaders.Authorization)
allowHeader(HttpHeaders.ContentType)
allowCredentials = true
anyHost()
}
И настройки на стороне клиента:
httpClient.get("${baseUrl}repos/octocat/Spoon-Knife/forks") {
headers.append("Access-Control-Allow-Origin", "http://localhost:8080")
headers.append("Access-Control-Allow-Credentials", "true")
}
К сожалению, ничего не помогло добиться желаемого результата. Я был бы благодарен за любую помощь.
Я добавил Access-Control-*
в поисках решения проблемы CORS. Существует вероятность неправильного использования. Поэтому я вынужден обратиться к сообществу за помощью. Чтобы мне подсказали, как это реализовать, чтобы работало без ошибок.
При настройке CORS на сервере вы забыли добавить один заголовок, что и вызывает проблему. Если вы добавите заголовок для источника разрешения контроля доступа, он должен работать нормально. Вы можете добавить его следующим образом:
allowHeader(HttpHeaders.AccessControlAllowOrigin)
Спасибо за совет. ДобавленallowHeader(HttpHeaders.AccessControlAllowOrigin) в заголовок сервера. Но, к сожалению, я получаю ту же ошибку.
Я обнаружил, что эта ошибка возникает, если вы запускаете сервер на локальном хосте и Интернет на одном локальном хосте. Но я не нашел как исправить. Или это особенность разработки на мультиплатформенной стороне. Тогда было бы неплохо посмотреть успешный кейс реализации сервера+веба в мультиплатформенном проекте.
Я написал код создания сервера с нуля и добавил в него правила Cors, добавив к немуallowHeader(HttpHeaders.AccessControlAllowOrigin). И у меня все работало. Возможно, где-то были конфликтующие заголовки или какой-то другой дополнительный код. Окончательный вид рабочего Cors: install(CORS) { AnyHost()allowHeader(HttpHeaders.ContentType)allowHeader(HttpHeaders.AccessControlAllowOrigin) }
Никакой заголовок
Access-Control-*
не должен быть установлен на стороне клиента; это заголовки ответов.