使用Aurelia的Fetch Client时Azure Translator API(认知服务)的CORS错误 [英] CORS errors on Azure Translator API (Cognitive Services) when using Aurelia's Fetch Client
问题描述
我尝试使用Windows Azure的一个非常基本的API调用来翻译一些文本.他们给出了快速启动示例代码
I try to use a very basic API call from Windows Azure to translate some texts. They gives a quickstart example code.
我尝试使用此代码,效果很好.文本Hello world
被翻译成荷兰语和意大利语.
I try this code and it works pretty well. The text Hello world
is translated into deutch and italian.
我删除了我的个人订阅密钥.
以下是示例:
const request = require('request');
const uuidv4 = require('uuid/v4');
const subscriptionKey = '........';
let options = {
method: 'POST',
baseUrl: 'https://api.cognitive.microsofttranslator.com/',
url: 'translate',
qs: {
'api-version': '3.0',
'to': ['de', 'it']
},
headers: {
'Ocp-Apim-Subscription-Key': subscriptionKey,
'Content-type': 'application/json',
'X-ClientTraceId': uuidv4().toString()
},
body: [{
'text': 'Hello World!'
}],
json: true,
};
request(options, function(err, res, body){
console.log(JSON.stringify(body, null, 4));
});
该代码似乎是node
的服务器端库.现在,我需要将此代码集成到我的[aurelia] [2]应用程序中.因此,我考虑使用aurelia-fetch-client
代替request
方法.我使用Aurelia CLI.
It looks like this code is a server side library for node
. Now I need to integrate this code into my [aurelia][2] application. So I think of using the aurelia-fetch-client
to replace the request
method. I use the Aurelia CLI.
这是我所做的:
已添加到package.json中:
"dependencies": {
....
"@types/uuidv4": "^2.0.0",
...
"uuidv4": "^4.0.0",
}
添加到aurelia.json中:
"dependencies": [
...
"uuidv4"
]
在控制台中运行npm install
.
创建测试页:
import { HttpClient, json } from 'aurelia-fetch-client';
import { autoinject } from 'aurelia-framework';
import * as uuidv4 from 'uuidv4';
import secret from '../secret';
@autoinject
export class Translator {
constructor(httpClient: HttpClient) {
this.httpClient = httpClient;
}
private httpClient: HttpClient;
private translate(from, to, html) {
debugger;
var init: RequestInit =
{
method: 'POST',
//mode: 'no-cors',
headers: {
'Ocp-Apim-Subscription-Key': secret.translatorKey,
'Content-type': 'application/json',
//'Content-Type': 'application/x-www-form-urlencoded',
'X-ClientTraceId': uuidv4().toString()
},
credentials: 'same-origin',
body: $.param({
'api-version': '3.0',
'from': 'en',
'to': 'fr',
'text': '<b>Hello World!</b>' })
//body: json({ 'text': '<b>Hello World!</b>' })
};
this.httpClient.fetch(`https://api.cognitive.microsofttranslator.com/`, init)
.then((result) => {
debugger;
})
.catch((error) => {
debugger;
});
}
诀窍是能够将选项传递到示例代码的request
并将其调整为aurelia-fetch-client
.我没有成功.
The trick is to be able to get the options passed to the request
of the sample code and adjust it to the aurelia-fetch-client
. I did not succeed.
不幸的是,我总是收到以下错误:
Unfortunately I always get the error below:
可在" https://api.cognitive.microsofttranslator.com/ http://localhost:9000 的a>"已被CORS策略阻止:对预检请求的响应没有无法通过访问控制检查:飞行前请求不允许重定向.
Access to fetch at 'https://api.cognitive.microsofttranslator.com/' from origin 'http://localhost:9000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
有什么建议吗?
推荐答案
TL; DR -与您一样,我很难从浏览器中的文档中获取说明.但是,将Subscription-Key
作为querystring参数附加确实可行.
TL;DR - Just like you, I'm having a hard time getting the instructions from the documentation working in the browser. However, appending the Subscription-Key
as querystring parameter does seem to work.
示例,请阅读注释:
import { HttpClient } from 'aurelia-fetch-client';
import { autoinject } from 'aurelia-framework';
@autoinject
export class App {
constructor(private http: HttpClient) {
}
private async attached(): Promise<void> {
// Important: use either key1 or key2, not the guid from your subscription
const subscriptionKey = 'YOUR-KEY-HERE';
// Important: the endpoint is different per GEO-REGION
const baseUrl = 'https://api-eur.cognitive.microsofttranslator.com';
const body = [{
'text': 'Hello World!'
}];
// Note: I couldn't get 'Ocp-Apim-Subscription-Key' working in the browser (only through Postman, curl)
// Also, trading in the subscriptionKey for a Bearer token did not work for me (in the browser)
// Therefor, we append it to the url later on.
// Also notice, X-ClientTraceId' is NOT neccessary and the docs don't explain why it's needed
const headers = new Headers();
headers.append('Content-Type', 'application/json');
const response = await this.http.fetch(`${baseUrl}/translate?api-version=3.0&to=nl&Subscription-Key=${subscriptionKey}`, {
method: 'POST',
headers: headers,
body: JSON.stringify(body)
});
if (response.ok) console.log(await response.json());
}
}
请注意,在此示例中,您不需要request
和uuid
库.您只需要:
Note that for this example, you don't need request
and uuid
libraries. You just need:
$ npm install --save aurelia-fetch-client whatwg-fetch
我还注意到您正在使用TypeScript,因此将示例更改为使用@autoinject
来使用它.
I also noticed you're using TypeScript, so changed the example to use that by using @autoinject
.
If you're getting a lot of 401's - there is an older MSDN blogpost which is still definitely worth a read. Some highlights:
- 有不同的API终结点,具体取决于您的Azure服务的地理位置.
- 基于地理区域的各个服务(翻译,视觉等)与通用的,范围更广的认知服务(又称为认知多服务订阅)之间的端点有所不同.
- 如果您使用单个服务,则每个服务的API密钥是不同的.
- 有3种不同的身份验证方式:但是,我只能让其中一个在浏览器中工作.
- There are different API endpoints depending on the geolocation of your Azure service.
- There is a difference in endpoints between the individual services (Translator, Vision etc.) which are geo-region based - and the generic, broader Cognitive Services (a.k.a. the Cognitive multi-service subscription).
- If you're using individual services, API keys are different per service.
- There are 3 different ways of authenticating; however, I can only get one of them to work in the browser.
This is also more or less written in the official docs.
话虽如此,文档中的示例实际上并没有任何好处.至少在我看来.首先,您想确保自己确切地知道自己应该做什么.这是一个curl示例:
That being said, the example in the docs aren't really any good. At least, in my opinion. First, you want to make sure you know exactly what you're supposed to do. Here is a curl example:
curl -X POST \
'https://api-eur.cognitive.microsofttranslator.com/translate?api-version=3.0&to=nl' \
-H 'Content-Type: application/json' \
-H 'Ocp-Apim-Subscription-Key: <YOUR-KEY-HERE>' \
-d '[{
'\''text'\'': '\''Hello World!'\''
}]'
虽然这听起来很简单,但我无法在浏览器中正常工作,而我却不断看到401的CORS问题.原因似乎是它没有吞下"Ocp-Apim-Subscription-Key".我还尝试过在subscriptionKey中交换授权载体令牌(示例),它也无法在浏览器中运行.这些示例确实适用于curl或Postman.
While this sounds easy, I cannot get this to work properly in the browser where I keep getting what appears to be CORS issues with 401's. The cause seems to be it doesn't swallow the 'Ocp-Apim-Subscription-Key'. I've also tried trading in the subscriptionKey for an Authorization Bearer token (example) which also didn't work in the browser. These examples do work in curl, or in Postman though.
最后,回到使用SubscriptionKey作为查询字符串会有所帮助.至少对我来说.
Finally, just falling back to using the SubscriptionKey as querystring helped. At least, for me.
希望这会有所帮助!
这篇关于使用Aurelia的Fetch Client时Azure Translator API(认知服务)的CORS错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!