Azure APIM returns 空响应 body 预检时状态代码为 200 并且从 axios 发出 GET 请求
Azure APIM returns empty response body with status code 200 on preflight and GET requests made from axios
我们在 Azure API 管理中添加了 REST API。
但是,当尝试从我们的前端(Vue.js 使用 axios)访问它时,请求失败并且我们收到一条错误消息“Access to XMLHttpRequest at 'https://test-vue-backend.io/' from origin 'https://test-vue-frontend.io' has been blocked by CORS 策略:请求的资源上不存在 'Access-Control-Allow-Origin' header。”在 GET 请求和 POST 请求上。
对于 POST 请求,我可以看到正在进行预检请求。
此请求获得 200 状态代码作为响应,但响应 body 为空。
预检请求的错误消息是“从来源 'https://test-vue-frontend.io' 到 'https://test-vue-backend.io/' 处的 XMLHttpRequest 的访问已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:否'Access-Control-Allow-Origin' header 出现在请求的资源上。"
我没有看到 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,就可以了。
我已经检查了 and 但这两个似乎都与我的问题无关,因为 forward-request 政策在我的顶级(所有 api)上启用并且我没有政策.
编辑:
感谢下面的评论,我发现如果我从入站和出站部分中删除 </base>
,CORS 就会起作用。
然而,我不明白基地是什么原因。
ALL APIs 的子句如下所示:
<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 请求产生空的 200 响应。您有两个选择:
- 确保每个请求管道中只有一个策略
- 在 CORS 策略上使用 terminate-unmatched-request 属性来控制在请求不匹配任何指定来源时应对请求执行的操作。
我们在 Azure API 管理中添加了 REST API。 但是,当尝试从我们的前端(Vue.js 使用 axios)访问它时,请求失败并且我们收到一条错误消息“Access to XMLHttpRequest at 'https://test-vue-backend.io/' from origin 'https://test-vue-frontend.io' has been blocked by CORS 策略:请求的资源上不存在 'Access-Control-Allow-Origin' header。”在 GET 请求和 POST 请求上。
对于 POST 请求,我可以看到正在进行预检请求。
此请求获得 200 状态代码作为响应,但响应 body 为空。
预检请求的错误消息是“从来源 'https://test-vue-frontend.io' 到 'https://test-vue-backend.io/' 处的 XMLHttpRequest 的访问已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:否'Access-Control-Allow-Origin' header 出现在请求的资源上。"
我没有看到 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,就可以了。
我已经检查了
编辑:
感谢下面的评论,我发现如果我从入站和出站部分中删除 </base>
,CORS 就会起作用。
然而,我不明白基地是什么原因。
ALL APIs 的子句如下所示:
<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 请求产生空的 200 响应。您有两个选择:
- 确保每个请求管道中只有一个策略
- 在 CORS 策略上使用 terminate-unmatched-request 属性来控制在请求不匹配任何指定来源时应对请求执行的操作。