Azure APIM 在预检和从 axios 发出的 GET 请求时返回空响应正文,状态代码为 200
Posted
技术标签:
【中文标题】Azure APIM 在预检和从 axios 发出的 GET 请求时返回空响应正文,状态代码为 200【英文标题】:Azure APIM returns empty response body with status code 200 on preflight and GET requests made from axios 【发布时间】:2021-09-21 20:00:11 【问题描述】:我们在 Azure API 管理中添加了一个 REST API。 但是,当尝试从我们的前端(使用 axios 的 Vue.js)访问它时,请求失败并且我们收到一条错误消息:“从源 https://test-vue-backend.io/ 访问 XMLHttpRequest ://test-vue-frontend.io' 已被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头。” GET 请求和 POST 请求。
对于 POST 请求,我可以看到正在发出 Preflight 请求。 此请求获得 200 状态代码作为响应,但响应正文为空。
预检请求的错误消息是“从源 'https://test-vue-frontend.io' 访问 'https://test-vue-backend.io/' 的 XMLHttpRequest 已被 CORS 阻止策略:对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。”
我没有看到 GET 请求的预检请求。它只是立即失败并显示第一个提到的错误消息。
这是该 API 顶层的策略(所有操作):
<policies>
<inbound>
<base />
<cors>
<allowed-origins>
<origin>https://test-vue-frontend.io</origin>
</allowed-origins>
<allowed-methods preflight-result-max-age="300">
<method>GET</method>
<method>POST</method>
<method>PATCH</method>
<method>DELETE</method>
<method>OPTIONS</method>
</allowed-methods>
<allowed-headers>
<header>*</header>
</allowed-headers>
</cors>
<choose>
<when condition="@(context.Request.OriginalUrl.Host.ToLower() == "test-vue-backend.io")">
<set-backend-service base-url="http://localhost:8080/backend/webapi" />
</when>
<when condition="@(context.Request.OriginalUrl.Host.ToLower() == "dev-vue-backend.io")">
<set-backend-service base-url="http://localhost:8081/backend/webapi" />
</when>
</choose>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
<set-header name="Access-Control-Allow-Origin" exists-action="override">
<value>@(context.Request.Headers.GetValueOrDefault("Origin",""))</value>
</set-header>
<set-header name="Access-Control-Allow-Credentials" exists-action="override">
<value>true</value>
</set-header>
<set-header name="Access-Control-Allow-Methods" exists-action="override">
<value>GET, POST, PATCH, DELETE, OPTIONS</value>
</set-header>
</outbound>
<on-error>
<base />
</on-error>
</policies>
出于隐私原因,所有 API 名称都已更改,但我可以向您保证,它们在我的配置中是正确的,不是问题的原因。
axios POST 和 GET 请求如下所示:
axios
.get("https://test-vue-backend.io/getroute?lang=" + lang)
.then(response =>
commit("SET_ADVICEDATA", response.data);
);
axios
.post("https://test-vue-backend.io/postuser", null,
headers: Authorization: "Bearer " + token
)
.then(response =>
commit("SET_USERINFO", response.data);
);
如果我直接在浏览器中输入https://test-vue-backend.io/getroute?lang=nl,它可以工作。
我已经检查了 REST API service when called from azure APIM returning empty response body with Status code 200 和 Azure API Management returning 200 status without response body 但这两个似乎都与我的问题无关,因为在我的顶层(所有 api)上启用了转发请求策略并且我没有策略。
编辑:
感谢下面的 cmets,我发现如果我从入站和出站部分中删除 </base>
,CORS 就可以工作。
但是,我不明白基地的原因是什么。
所有 API 的子句如下所示:
<policies>
<inbound>
<cors allow-credentials="true">
<allowed-origins>
<origin>https://other-host-than-the-one-i-need.net</origin>
</allowed-origins>
<allowed-methods preflight-result-max-age="300">
<method>*</method>
</allowed-methods>
<allowed-headers>
<header>*</header>
</allowed-headers>
<expose-headers>
<header>*</header>
</expose-headers>
</cors>
</inbound>
<backend>
<forward-request />
</backend>
<outbound />
<on-error />
</policies>
我最好的猜测是它只允许基本来源,即使在我的来源之前提到了</base>
标签,但我不确定。
【问题讨论】:
对您正在使用的产品运行“计算有效策略”以进行单次操作并将其粘贴到此处。它显示了什么?在应用 cors 之前是否执行了任何策略? 预检 OPTIONS 请求的响应正文为空,这是意料之中的。它不会引起任何问题。但实际上导致问题的是响应缺少 Access-Control-Allow-Origin 响应标头和 Access-Control-Allow-Methods 响应标头和 Access-Control-Allow-Headers 响应标头。 @SteppingRazor 从我现在可以看到的情况来看,该 API 未在任何产品下列出。这是一个问题吗?如何在应用 cors 之前检查是否执行了任何策略? @sideshowbarker 我明白了。但是我不明白为什么没有响应标头,因为我已经在出站部分配置了它们。 我只能推测,虽然出站部分中的配置可能会导致响应标头添加到 POST 和 GET 响应中,但它不会导致响应标头添加到 OPTIONS 响应中。服务器系统通常对 OPTIONS 请求和响应进行特殊处理,这些处理与处理 GET 和 POST 的代码是分开的。所以我猜预检 OPTIONS 请求被其他一些代码捕获和处理,因此永远不会到达问题中引用的代码。因此,您可能想尝试对该服务器代码进行一些跟踪以查看 【参考方案1】:您的政策解释了这一点。在请求生命周期内只会调用单个 CORS 策略 - 在处理期间遇到的第一个策略。因此,由于来源不匹配,因此对您的 OPTIONS 请求产生空的 200 响应是全局级别的策略。你有两个选择:
-
确保每个请求管道中只有一个策略
在 CORS 策略上使用 terminate-unmatched-request 属性来控制如果请求与任何指定的来源都不匹配,应如何处理。
【讨论】:
以上是关于Azure APIM 在预检和从 axios 发出的 GET 请求时返回空响应正文,状态代码为 200的主要内容,如果未能解决你的问题,请参考以下文章
使用 Azure 应用网关 + APIM 进行 SSL 固定
Azure APIM 网关正在修剪 api url 中的尾部斜杠