使用Aurelia的Fetch Client时Azure Translator API(认知服务)的CORS错误 [英] CORS errors on Azure Translator API (Cognitive Services) when using Aurelia's Fetch Client

查看:84
本文介绍了使用Aurelia的Fetch Client时Azure Translator API(认知服务)的CORS错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用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());
  }
}

请注意,在此示例中,您不需要requestuuid库.您只需要:

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.

如果您收到大量401,则出现

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆