Играть! 2.4: Как разрешить CORS из исходного файла://

Я использую 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, потому что фильтр не применяется. Но если это для приложения кордовы, оно должно работать достаточно хорошо.

Ответ 1

Хорошо, проблема исходит из этой строки кода в платформе Play: https://github.com/playframework/playframework/blob/master/framework/src/play-filters-helpers/src/main/scala/play/filters/cors/AbstractCORSPolicy.scala#L322

Поскольку URI является "file://", домен/хост URI имеет значение null, поэтому new URI выдает ошибку, а затем Play возвращает ошибку 403. Чтобы исправить это, нам нужно исправить фреймворк или попытаться изменить начало координат на "file://".

Я нашел обходной путь для моего варианта использования: отключите CORS на Play. Затем, когда я использую ajax из моего приложения cordova, источник не проверяется.

Проблема с этим обходным решением заключается в том, что если я хочу включить CORS в свой проект Play по какой-либо причине, приложение cordova не будет работать, так как Play проверит происхождение и отклонит его.