英文:
Azure Machine Learning REST Endpoint - Failed to Fetch
问题
我创建了一个带有REST终点的Azure机器学习模型,以便消费它。当我使用Postman运行服务时,一切似乎都正常工作。
然而,当我尝试创建一个HTML网站(Codepen),使用JavaScript调用REST终点时,我只得到一个错误消息:Failed to Fetch。
我还尝试了Azure静态Web应用,但也没有成功。
然而,我能够在控制台中验证,通过Codepen发送到REST终点的输入与Postman中的相同。
这是我的JavaScript示例:
<script>
const form = document.querySelector('#agriculture-form');
form.addEventListener('submit', (event) => {
event.preventDefault();
const areaHarvest = parseFloat(document.querySelector('#area-harvest').value);
const farmGatePrice = parseFloat(document.querySelector('#farm-gate-price').value);
const volumeOfImport = parseFloat(document.querySelector('#volume-of-import').value);
const lowTemp = parseFloat(document.querySelector('#low-temp').value);
const averageTemp = parseFloat(document.querySelector('#average-temp').value);
const highTemp = parseFloat(document.querySelector('#high-temp').value);
const precipitationMm = parseFloat(document.querySelector('#precipitation-mm').value);
const precipitationDays = parseFloat(document.querySelector('#precipitation-days').value);
const tropicalCyclones = parseFloat(document.querySelector('#tropical-cyclones').value);
const volumeProductionGuess = 0;
const data = {
"Area_Harvested": areaHarvest,
"FarmGatePricePHPPSA": farmGatePrice,
"Volume_of_Import": volumeOfImport,
"temp_low": lowTemp,
"temp_ave": averageTemp,
"temp_high": highTemp,
"precipitation_mm": precipitationMm,
"precipitation_days": precipitationDays,
"tropical_cyclone": tropicalCyclones,
"Volume_of_Production": volumeProductionGuess
};
const formattedData = [data];
console.log('formatted data:', formattedData);
const testData = JSON.stringify(formattedData);
console.log('test data:', testData);
document.getElementById("demo").innerHTML = testData;
fetch('http://ziggyapimanagementservice.azure-api.net/score', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': 'cd529cc993494fdfb1530eaf04ae63dc'
},
body: testData
})
.then(response => response.json())
.then(data => {
console.log(data);
const result = data.result[0]; // 从响应中获取结果数组
const volumeForecastElement = document.querySelector('#volume-forecast');
volumeForecastElement.textContent = result.join(', '); // 使用逗号分隔的结果数组更新<b>元素的文本内容
document.getElementById("result").innerHTML = result;
})
.catch(error => {
document.getElementById("error").innerHTML = error.message;
console.error(error.message)
});
});
</script>
这是我在Postman中获得的结果。
英文:
I created an Azure Machine Learning model with a REST Endpoint as a way to consume it. When I run the service using Postman everything seems to work fine.
However, when I try to create an HTML website (Codepen) with a javascript to call the REST Endpoint I only get an Error: Failed to Fetch message.
I also tried with Azure Static Web Apps and I am unsuccessful as well.
I was however able to verify (in the Console) that my input to the Rest Endpoint via Codepen is the same as Postman.
Is there anything I am missing out here?
Here is a sample of my javascript:
<script>
const form = document.querySelector('#agriculture-form');
form.addEventListener('submit', (event) => {
event.preventDefault();
const areaHarvest = parseFloat(document.querySelector('#area-harvest').value);
const farmGatePrice = parseFloat(document.querySelector('#farm-gate-price').value);
const volumeOfImport = parseFloat(document.querySelector('#volume-of-import').value);
const lowTemp = parseFloat(document.querySelector('#low-temp').value);
const averageTemp = parseFloat(document.querySelector('#average-temp').value);
const highTemp = parseFloat(document.querySelector('#high-temp').value);
const precipitationMm = parseFloat(document.querySelector('#precipitation-mm').value);
const precipitationDays = parseFloat(document.querySelector('#precipitation-days').value);
const tropicalCyclones = parseFloat(document.querySelector('#tropical-cyclones').value);
const volumeProductionGuess = 0;
const data = {
"Area_Harvested": areaHarvest,
"FarmGatePricePHPPSA": farmGatePrice,
"Volume_of_Import": volumeOfImport,
"temp_low": lowTemp,
"temp_ave": averageTemp,
"temp_high": highTemp,
"precipitation_mm": precipitationMm,
"precipitation_days": precipitationDays,
"tropical_cyclone": tropicalCyclones,
"Volume_of_Production": volumeProductionGuess
};
const formattedData = [data];
console.log('formatted data:', formattedData);
const testData = JSON.stringify(formattedData);
console.log('test data:', testData);
document.getElementById("demo").innerHTML = testData;
fetch('http://ziggyapimanagementservice.azure-api.net/score', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': 'cd529cc993494fdfb1530eaf04ae63dc'
},
body: testData
})
.then(response => response.json())
.then(data => {
console.log(data);
const result = data.result[0]; // Get the result array from the response
const volumeForecastElement = document.querySelector('#volume-forecast');
volumeForecastElement.textContent = result.join(', '); // Update the text content of the <b> element with the result array joined by commas
document.getElementById("result").innerHTML = result;
})
.catch(error => {
document.getElementById("error").innerHTML = error.message;
console.error(error.message)
});
});
</script>
And here is what I get in Postman:
update:
I added the CORS setting in the Azure API Management and still has the issue:
3-10-2023 update: I added the Accept Header in the Javascript and removed the access key for the moment. Also changed the API to HTTPS just to see if things change.Also changed the CORS value in the API
答案1
得分: 2
如我的评论中所述,错误很可能与跨域资源共享(CORS)有关。
请考虑配置您的REST端点以发送适用于您的JavaScript应用程序的CORS标头。
您似乎正在使用API管理来暴露REST端点:如果是这样,您可以通过定义适当的策略来配置CORS。
此页面提供了有关如何设置或编辑API管理策略的必要信息。
CORS策略的文档在这个其他页面中有说明。文档提供了适用于您的用例的示例配置:
<cors allow-credentials="true">
<allowed-origins>
<!-- 用于开发的本地主机 -->
<origin>http://localhost:8080/</origin>
<origin>http://your-javascript-app-domain.com/</origin>
</allowed-origins>
<allowed-methods preflight-result-max-age="300">
<method>POST</method>
</allowed-methods>
<allowed-headers>
<header>content-type</header>
<header>accept</header>
</allowed-headers>
</cors>
这个相关的SO问题也可能会有帮助。
此外,请在提交信息时考虑包含一个Accept
标头,我们在调用API管理服务暴露的API时遇到了问题,当该标头不存在时,我们经历了问题,我不是绝对确定,但我认为与fetch
(与Postman相反)默认不包含它有关:
fetch('http://ziggyapimanagementservice.azure-api.net/score', {
method: 'POST',
headers: {
'Accept': '*/*',
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': 'cd529cc993494fdfb1530eaf04ae63dc'
},
body: testData
})
.then(response => response.json())
.then(data => {
console.log(data);
const result = data.result[0]; // 从响应中获取结果数组
const volumeForecastElement = document.querySelector('#volume-forecast');
volumeForecastElement.textContent = result.join(', '); // 使用逗号分隔的结果数组更新<b>元素的文本内容
document.getElementById("result").innerHTML = result;
})
.catch(error => {
document.getElementById("error").innerHTML = error.message;
console.error(error.message)
});
英文:
As stated in my comment, the error could be very likely related to a CORS problem.
Please, consider configuring your REST endpoint for sending the CORS headers appropriate for your Javascript application.
You seem to be using API Management for exposing the REST endpoint: if that is correct, you can configure CORS by defining the appropriate policy.
This page provides the necessary information about how to set or edit API Management policies.
The CORS policy is documented in this other page. The documentation provides a sample configuration, adapted for your use case:
<cors allow-credentials="true">
<allowed-origins>
<!-- Localhost useful for development -->
<origin>http://localhost:8080/</origin>
<origin>http://your-javascript-app-domain.com/</origin>
</allowed-origins>
<allowed-methods preflight-result-max-age="300">
<method>POST</method>
</allowed-methods>
<allowed-headers>
<header>content-type</header>
<header>accept</header>
</allowed-headers>
</cors>
This related SO question could be of help as well.
Additionally, please, consider including an Accept
header when posting your information, we have experienced problems when this header is not present when invoking an API exposed by the API Management service, I am not absolutely sure, but I think it is not included by default by fetch
(in contrast to Postman):
fetch('http://ziggyapimanagementservice.azure-api.net/score', {
method: 'POST',
headers: {
'Accept': '*/*',
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': 'cd529cc993494fdfb1530eaf04ae63dc'
},
body: testData
})
.then(response => response.json())
.then(data => {
console.log(data);
const result = data.result[0]; // Get the result array from the response
const volumeForecastElement = document.querySelector('#volume-forecast');
volumeForecastElement.textContent = result.join(', '); // Update the text content of the <b> element with the result array joined by commas
document.getElementById("result").innerHTML = result;
})
.catch(error => {
document.getElementById("error").innerHTML = error.message;
console.error(error.message)
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论