Apigee 飞行前选项请求
Posted
技术标签:
【中文标题】Apigee 飞行前选项请求【英文标题】:Apigee Pre-Flight Options Requests 【发布时间】:2014-02-07 05:46:48 【问题描述】:我创建 api 代理并选中“为您的 API 启用直接浏览器访问 - 允许通过 CORS 来自浏览器的直接请求”框。但我的 OPTIONS 请求仍然失败:
"fault":
"faultstring": "Received 405 Response without Allow Header",
"detail":
"errorcode": "protocol.http.Response405WithoutAllowHeader"
根据我对 CORS 飞行前选项请求的了解,客户端首先将 OPTIONS 请求发送到服务器,作为“安全”CORS 的保障。此请求应返回包含可用请求类型列表的响应。
我的问题:如何使 Apigee 正确响应 OPTIONS 请求并且不将 OPTIONS 请求传递给代理后面的我的 api?。如果有帮助,我有 AngularJS javascript 应用程序尝试与我的 Apigee 端点通信。
Javascript 错误:
OPTIONS http://api.example.com No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://client.example.com' is therefore not allowed access.
XMLHttpRequest cannot load http://api.example.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://client.example.com' is therefore not allowed access.
默认“添加 CORS”xml
<AssignMessage async="false" continueOnError="false" enabled="true" name="Add-CORS">
<DisplayName>Add CORS</DisplayName>
<FaultRules/>
<Properties/>
<Add>
<Headers>
<Header name="Access-Control-Allow-Origin">*</Header>
<Header name="Access-Control-Allow-Headers">origin, x-requested-with, accept</Header>
<Header name="Access-Control-Max-Age">3628800</Header>
<Header name="Access-Control-Allow-Methods">GET, PUT, POST, DELETE</Header>
</Headers>
</Add>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>
默认代理端点 xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
<Description/>
<Flows/>
<PreFlow name="PreFlow">
<Request/>
<Response/>
</PreFlow>
<HTTPProxyConnection>
<BasePath>/v1/cnc</BasePath>
<VirtualHost>default</VirtualHost>
<VirtualHost>secure</VirtualHost>
</HTTPProxyConnection>
<RouteRule name="default">
<TargetEndpoint>default</TargetEndpoint>
</RouteRule>
<PostFlow name="PostFlow">
<Request/>
<Response/>
</PostFlow>
</ProxyEndpoint>
默认目标端点 xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TargetEndpoint name="default">
<Description/>
<Flows/>
<PreFlow name="PreFlow">
<Request/>
<Response>
<Step>
<Name>Add-CORS</Name>
</Step>
</Response>
</PreFlow>
<HTTPTargetConnection>
<URL>http://api.example.com/v1/assets.json</URL>
</HTTPTargetConnection>
<PostFlow name="PostFlow">
<Request/>
<Response/>
</PostFlow>
</TargetEndpoint>
【问题讨论】:
我不明白为什么这是一件很难克服的事情。当我选中允许 CORS 的复选框时,为什么不自动处理此问题? OPTIONS 请求是 CORS 请求过程的一部分。 【参考方案1】:由于您不希望 OPTIONS 请求传递到后端 API,因此需要做两件事:
一个指向空目标的 RouteRule,带有 OPTIONS 请求的条件。请注意,没有指定 TargetEndpoint。
<RouteRule name="NoRoute">
<Condition>request.verb == "OPTIONS"</Condition>
</RouteRule>
ProxyEndpoint 中用于处理 CORS 响应的自定义流。由于新的 RouteRule 将消息发送到 null Target(将请求回显给客户端),因此消息不会路由到当前定义 CORS 策略的“默认”TargetEndpoint。
您的 ProxyEndpoint 的更新版本如下所示:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
<Description/>
<Flows>
<Flow name="OptionsPreFlight">
<Request/>
<Response>
<Step>
<Name>Add-CORS</Name>
</Step>
</Response>
<Condition>request.verb == "OPTIONS"</Condition>
</Flow>
</Flows>
<PreFlow name="PreFlow">
<Request/>
<Response/>
</PreFlow>
<HTTPProxyConnection>
<BasePath>/v1/cnc</BasePath>
<VirtualHost>default</VirtualHost>
<VirtualHost>secure</VirtualHost>
</HTTPProxyConnection>
<RouteRule name="NoRoute">
<Condition>request.verb == "OPTIONS"</Condition>
</RouteRule>
<RouteRule name="default">
<TargetEndpoint>default</TargetEndpoint>
</RouteRule>
<PostFlow name="PostFlow">
<Request/>
<Response/>
</PostFlow>
</ProxyEndpoint>
注意:RouteRules 按照 ProxyEnpoint 配置中指定的顺序进行评估。您应该始终在末尾使用默认(无条件)路由。否则,如果在顶部,它将始终匹配并且永远不会评估其他 Route 可能性。
【讨论】:
谢谢!有没有办法让它成为未来代理的默认配置?还是我必须每次都进行此更改? 现在,您必须在任何时候从 UI 创建新代理并需要完整的 CORS 支持时进行更改。 Apigee 需要增强新的 API 代理构建器来解决此问题。 解决此问题后,人们可能还会遇到:XMLHttpRequest cannot load <url>. The 'Access-Control-Allow-Origin' header contains the invalid value 'http://localhost:9090, *'. Origin 'http://localhost:9090' is therefore not allowed access.
如aspnetwebstack.codeplex.com/workitem/1539 中所述...当将两个“Access-Control-Allow-Origin”标头添加到回复。要解决此问题,请从TargetEndpoint
的PreFlow
的Response
中删除Add-CORS
步骤【参考方案2】:
我做了上面答案中提到的同样的事情,但仍然遇到同样的问题。然后在做了一些研究之后问题就解决了。
问题是 cors 标头响应在请求期间未作为标头传递。为了解决这个问题,您可以在代理端点 preflow 中添加 cors 值:
<PreFlow name="PreFlow">
<Request/>
<Response>
<Step>
<Name>Add-CORS</Name>
</Step>
</Response>
</PreFlow>
【讨论】:
以上是关于Apigee 飞行前选项请求的主要内容,如果未能解决你的问题,请参考以下文章
来自基于 OWIN 的 WebAPI 的飞行前选项 CORS 令牌请求出现 400 错误