4

我创建 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>
4

2 回答 2

7

由于您不希望 OPTIONS 请求传递到后端 API,因此需要做两件事:

  1. 带有 OPTIONS 请求条件的空目标的 RouteRule。请注意,没有指定 TargetEndpoint。

    <RouteRule name="NoRoute">
        <Condition>request.verb == "OPTIONS"</Condition>
    </RouteRule>
    
  2. ProxyEndpoint 中用于处理 CORS 响应的自定义流。由于新的 RouteRule 将消息发送到空目标(将请求回显给客户端),因此消息不会路由到当前定义 CORS 策略的“默认”目标端点。

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 可能性。

于 2014-01-17T21:24:12.400 回答
0

我做了上面答案中提到的同样的事情,但仍然遇到同样的问题。然后在做了一些研究后,问题就解决了。

问题是 cors 标头响应在请求期间未作为标头传递。为了解决这个问题,您可以在代理端点 preflow 中添加 cors 值:

<PreFlow name="PreFlow">
    <Request/>
    <Response>
        <Step>
            <Name>Add-CORS</Name>
        </Step>
    </Response>
</PreFlow>
于 2020-11-01T11:06:37.390 回答