带有 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 响应的一部分,即使路由被拒绝或因异常而失败。
我正在尝试在使用 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 响应的一部分,即使路由被拒绝或因异常而失败。