带有 headerValueByName 问题的 akka http 中的 cors (akka-http-cors)

cors in akka http with headerValueByName issue (akka-http-cors)

我正在尝试在使用 akka-http-cors 时为我的 akka http API 添加 CORS 支持:https://github.com/lomigmegard/akka-http-cors

当我基本上将 cors 支持添加到 简单 路由时,一切正常,例如:

val route = cors() {
    path("ping") {
       get {
           complete("pong")
       }
    }
}

与对应的jQuery调用:

$.ajax({
     url: "http://localhost:9000/ping",
     type: "GET",
     success: function(data) { alert(data); }
  });

returns 正常 "pong" 符合预期


但是当我尝试从请求中提取(服务器端)一些特定的 header 时,对响应的 cors 支持似乎突然被破坏了。例如,使用:

val route = cors() {
    headerValueByName("myheader") { (myheader) =>
       path("ping") {
           get {
               complete("pong")
           }
       }
    }
}

与对应的jQuery调用:

$.ajax({
     url: "http://localhost:9000/ping",
     type: "GET",
     beforeSend: function(xhr){xhr.setRequestHeader('myheader', 'test');},
     success: function(data) { alert('Success!' + data); }
  });

在控制台中因 cors 错误而失败:

XMLHttpRequest cannot load http://localhost:9000/ping. 
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:8080' is therefore not allowed access. 
The response had HTTP status code 400.

似乎在路由中添加 headerValueByName(...) 会破坏 cors 支持,我不明白为什么。

我也尝试过不同的 cors 实现(基于自定义特征),所有这些的行为都是相同的。

我在这里错过了什么?

请使用 curl 等工具调试您的服务器路由,以查看来自服务器的实际响应,而不是 JavaScript 的解释。

curl -X GET -H "Origin: http://example.com" -H "myheader: test" http://localhost:9000/ping

我怀疑您的自定义 header 未在 HTTP 请求中正确发送。 headerValueByName 指令将拒绝该请求。拒绝冒泡(跳过 cors 指令)最终由默认拒绝处理程序处理。因此 CORS-related header 没有响应。

您的拒绝和异常处理程序应该 cors 指令中,而不是在外部(就像默认的那样)。请看下面的例子。

def route: Route = {
  import CorsDirectives._
  import Directives._

  // Your CORS settings
  val corsSettings = CorsSettings.defaultSettings

  // Your rejection handler
  val rejectionHandler = corsRejectionHandler withFallback RejectionHandler.default

  // Your exception handler
  val exceptionHandler = ExceptionHandler {
    ...
  }

  // Combining the two handlers only for convenience
  val handleErrors = handleRejections(rejectionHandler) & handleExceptions(exceptionHandler)

  // Note how rejections and exceptions are handled *before* the CORS directive (in the inner route).
  // This is required to have the correct CORS headers in the response even when an error occurs.
  handleErrors {
    cors(corsSettings) {
      handleErrors {
        ... // your business route here
      }
    }
  }
}

这不会解决您的 header 问题,但至少 CORS headers 将成为 HTTP 响应的一部分,即使路由被拒绝或因异常而失败。