Я использую play 2.4 для создания публичного API REST. Я добавил фильтр CORS, разрешающий все происхождение и заголовки.
См. раздел application.conf:
play.filters {
# CORS filter configuration
cors {
# The path prefixes to filter.
pathPrefixes = ["/"]
# The allowed origins. If null, all origins are allowed.
allowedOrigins = null
# The allowed HTTP methods. If null, all methods are allowed
allowedHttpMethods = null
# The allowed HTTP headers. If null, all headers are allowed.
allowedHttpHeaders = null
# The exposed headers
exposedHeaders = []
# Whether to support credentials
supportsCredentials = true
# The maximum amount of time the CORS meta data should be cached by the client
preflightMaxAge = 1 hour
}
}
Он отлично работает, когда я вызываю API из классического браузера (проверено на chrome/firefox), независимо от происхождения, поскольку я разрешил все.
НО, когда я пытаюсь назвать это формой приложения cordova (в приложениях cordova, начало запросов ajax file://
), я получаю ошибку CORS: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'file://' is therefore not allowed access. The response had HTTP status code 403
. Как будто я не разрешил исходный файл://'
Я попытался использовать другой API, который позволяет CORS (GET https://public.opencpu.org/ocpu/library/), чтобы проверить, не была ли блокировка запроса кордовой но он работал нормально. Поэтому я предполагаю, что проблема исходит от Play.
Я попытался установить allowedOrigins = ["file://"]
, но он тоже не работает...
Любая помощь пожалуйста?
EDIT: Это не дубликат Cross origin GET из локального файла://: я не могу установить веб-сервер, так как это приложение кордовы. Файлы подаются из файловой системы телефона/планшета в WebView. Это специфический для платформы вопрос, у меня не было проблем с более старой версией. Возможно, CorsFilter по умолчанию может быть изменен, чтобы разрешить исходный файл://
EDIT 2: после того, как он был запрошен, здесь (очень простой) код используется для моего настраиваемого фильтра scala.
// CORSFilter.scala
package filters
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import play.api.mvc._
import play.mvc.Http
/**
* Allow CORS from anywhere, any method
*/
class CORSFilter extends EssentialFilter {
def apply(nextFilter: EssentialAction) = new EssentialAction {
def apply(requestHeader: RequestHeader) = {
nextFilter(requestHeader)
.map { result =>
if (requestHeader.method.equals("OPTIONS")) {
Results.Ok.withHeaders(
Http.HeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN -> "*",
Http.HeaderNames.ACCESS_CONTROL_ALLOW_HEADERS -> "X-Requested-With, Accept, Content-Type",
Http.HeaderNames.ACCESS_CONTROL_ALLOW_METHODS -> "HEAD,GET,POST,PUT,PATCH,DELETE")
} else {
result.withHeaders(
Http.HeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN -> "*",
Http.HeaderNames.ACCESS_CONTROL_ALLOW_HEADERS -> "X-Requested-With, Accept, Content-Type",
Http.HeaderNames.ACCESS_CONTROL_ALLOW_METHODS -> "HEAD,GET,POST,PUT,PATCH,DELETE",
Http.HeaderNames.ACCESS_CONTROL_EXPOSE_HEADERS -> "X-Custom-Header-To-Expose")
}
}
}
}
}
Обратите внимание, что я использую это только в режиме разработки, и у него есть некоторые проблемы. Например, если исключение не обнаружено во время выполнения, ответ не будет иметь заголовки CORS, потому что фильтр не применяется. Но если это для приложения кордовы, оно должно работать достаточно хорошо.