我不想明确写:
options { ... }
我的Spray路线中的每个入口点/路径。我想编写一些通用代码,为所有路径添加OPTIONS
支持。它应该查看路径并从中提取支持的方法。
我无法粘贴任何代码,因为我不知道如何在Spray中处理它。
我之所以这样做,是因为我想提供一个符合HATEOAS原则的自我发现的API。
答案 0 :(得分:2)
以下指令将能够捕获被拒绝的请求,检查它是否是选项请求,并返回:
尝试了解以下代码段并在必要时进行调整。您应该更愿意提供尽可能多的信息,但如果您只想返回允许的方法,我建议您删除其余的信息:)。
import spray.http.{AllOrigins, HttpMethods, HttpMethod, HttpResponse}
import spray.http.HttpHeaders._
import spray.http.HttpMethods._
import spray.routing._
/**
* A mixin to provide support for providing CORS headers as appropriate
*/
trait CorsSupport {
this: HttpService =>
private val allowOriginHeader = `Access-Control-Allow-Origin`(AllOrigins)
private val optionsCorsHeaders = List(
`Access-Control-Allow-Headers`(
"Origin, X-Requested-With, Content-Type, Accept, Accept-Encoding, Accept-Language, Host, " +
"Referer, User-Agent"
),
`Access-Control-Max-Age`(60 * 60 * 24 * 20) // cache pre-flight response for 20 days
)
def cors[T]: Directive0 = mapRequestContext {
context => context.withRouteResponseHandling {
// If an OPTIONS request was rejected as 405, complete the request by responding with the
// defined CORS details and the allowed options grabbed from the rejection
case Rejected(reasons) if (
context.request.method == HttpMethods.OPTIONS &&
reasons.exists(_.isInstanceOf[MethodRejection])
) => {
val allowedMethods = reasons.collect { case r: MethodRejection => r.supported }
context.complete(HttpResponse().withHeaders(
`Access-Control-Allow-Methods`(OPTIONS, allowedMethods :_*) ::
allowOriginHeader ::
optionsCorsHeaders
))
}
} withHttpResponseHeadersMapped { headers => allowOriginHeader :: headers }
}
}
像这样使用:
val routes: Route =
cors {
path("hello") {
get {
complete {
"GET"
}
} ~
put {
complete {
"PUT"
}
}
}
}
答案 1 :(得分:-2)
Methinks options
非常通用,您可以将其用作:
path("foo") {
options {
...
}
} ~
path("bar") {
options {
...
}
}
或者这样:
options {
path("foo") {
...
} ~
path("bar") {
...
}
}
答案 2 :(得分:-2)
我是这样做的:
private val CORSHeaders = List(
`Access-Control-Allow-Methods`(GET, POST, PUT, DELETE, OPTIONS),
`Access-Control-Allow-Headers`("Origin, X-Requested-With, Content-Type, Accept, Accept-Encoding, Accept-Language, Host, Referer, User-Agent"),
`Access-Control-Allow-Credentials`(true)
)
def respondWithCORS(origin: String)(routes: => Route) = {
val originHeader = `Access-Control-Allow-Origin`(SomeOrigins(Seq(HttpOrigin(origin))))
respondWithHeaders(originHeader :: CORSHeaders) {
routes ~ options { complete(StatusCodes.OK) }
}
}
val routes =
respondWithCORS(config.getString("origin.domain")) {
pathPrefix("api") {
// ... your routes here
}
}
因此,对带有/ api前缀的任何URL的每个OPTION请求都会返回200个代码。
更新:添加了Access *标题。