Почему функция Azure SignalR возвращает ошибку CORS при тестировании локального хоста

Я пытаюсь научиться использовать Azure function и SignalR для создания безсерверного дизайна. для этого я создал следующий класс для Azure function:

    public static class NotifactionR
    {

        [FunctionName("negotiate")]
        public static SignalRConnectionInfo Negotiate(
            [HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequest req,
            [SignalRConnectionInfo(HubName = "my-hub")]
            SignalRConnectionInfo connectionInfo)
        {
            // connectionInfo contains an access key token with a name identifier claim set to the authenticated user
            return connectionInfo;
        }

        [FunctionName("NotifactionR")]
        public static Task NotifactionR([EventGridTrigger]EventGridEvent eventGridEvent,
            [SignalR(HubName = "my-hub")]IAsyncCollector<SignalRMessage> signalRMessages,
            ILogger log)
        {
            log.LogInformation(eventGridEvent.Data.ToString());

            return signalRMessages.AddAsync(
                new SignalRMessage
                {
                    // the message will only be sent to these user IDs
                    UserId = "userId1",
                    Target = "OnNewEvent",
                    Arguments = new[] { eventGridEvent.Data }
                });
        }
    }

Я использовал следующую конфигурацию на моем local.settings.json, чтобы включить локальное тестирование:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "AzureSignalRConnectionString": "Endpoint=https://myservice.service.signalr.net;AccessKey=myaccess-token;Version=1.0;",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet"
  },
  "Host": {
    "CORS": "http://localhost:7071",
    "CORSCredentials": true
  }
}

и чтобы проверить это, просто создал HTML file, который содержит следующий скрипт:

const connection = new signalR.HubConnectionBuilder()
      .withUrl("http://localhost:7071/api", { headers: { 'Access-Control-Allow-Origin': 'http://localhost:7071'}})
      .configureLogging(signalR.LogLevel.Trace)
      .build();

connection.on('OnNewEvent', ProcessMyEvent);
connection.onclose(() => console.log('disconnected'));
console.log('connecting...');

connection.start()
    .then(() => data.ready = true)
    .catch(console.error);

Когда я открываю HTML-файл в своем Chrome, я вижу следующую ошибку (проблема почти такая же и в Firefox):

connecting...
Utils.ts:189 [2019-07-27T16:13:01.573Z] Debug: Starting HubConnection.
Utils.ts:189 [2019-07-27T16:13:01.573Z] Debug: Starting connection with transfer format 'Text'.
Utils.ts:189 [2019-07-27T16:13:01.575Z] Debug: Sending negotiation request: http://localhost:7071/api/negotiate.

SignalRTest.html:1 Access to XMLHttpRequest at 'http://localhost:7071/api/negotiate' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Utils.ts:182 [2019-07-27T16:13:02.147Z] Warning: Error from HTTP request. 0: .
Utils.ts:179 [2019-07-27T16:13:02.148Z] Error: Failed to complete negotiation with the server: Error
Utils.ts:179 [2019-07-27T16:13:02.148Z] Error: Failed to start the connection: Error
Error
    at new HttpError (Errors.ts:20)
    at XMLHttpRequest.xhr.onerror (XhrHttpClient.ts:76)

Есть ли у кого-нибудь идеи относительно того, что я здесь делаю не так?

Обновление 1

Вот мой test.html файл, который я использую

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="https://unpkg.com/@aspnet/[email protected]/dist/browser/signalr.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js"></script>
    <script>
        window.apiBaseUrl = 'http://localhost:7071';

        function initialize() {
            const connection = new signalR.HubConnectionBuilder()
                .withUrl(window.apiBaseUrl + "/api", { headers: { 'Access-Control-Allow-Origin': 'http://localhost:7071' } })
                .configureLogging(signalR.LogLevel.Trace)
                .build();

            connection.on('OnNewEvent', ProcessMyEvent);
            connection.onclose(() => console.log('disconnected'));
            console.log('connecting...');

            connection.start({ withCredentials: false })
                .then(() => console.log('ready...'))
                .catch(console.error);

        }
        function ProcessMyEvent(vehicle) {
            alert("ProcessMyEvent CALLED");
        }

        initialize();


    </script>
</head>
<body>

</body>

</html>

Обновление 2:

Я также попытался запустить это из командной строки с помощью следующей команды:

c:\Users\Kiran\AppData\Local\AzureFunctionsTools\Releases\2.26.0\cli\func host start --cors * --pause-on-error

все же я получаю ту же ошибку


person Kiran    schedule 27.07.2019    source источник
comment
Ваша конфигурация CORS в local.settings.json неверна. В настоящее время у вас есть запись http://localhost:7071, и это хост функции. В этой записи вам нужно указать происхождение веб-страницы.   -  person Anthony Chu    schedule 28.07.2019
comment
Нет необходимости добавлять заголовки в клиент JavaScript. Вам также не следует использовать тире - в имени концентратора. Это может сработать, но есть шанс, что это не так.   -  person Anthony Chu    schedule 28.07.2019
comment
Также ... как вы открываете test.html?   -  person Anthony Chu    schedule 28.07.2019
comment
@AnthonyChu: Спасибо, я тоже тестировал CORS:"*", но вижу те же ошибки. Также .withUrl(window.apiBaseUrl + "/api") не помогает. Есть идеи, что еще мне может не хватать?   -  person Kiran    schedule 28.07.2019
comment
Также я открываю файл в своем браузере прямо как file:///d:/myTestfile.html   -  person Kiran    schedule 28.07.2019
comment
Ваше приложение размещено на GitHub? Вы не можете использовать *, потому что поддержка учетных данных включена, он должен быть источником вашей веб-страницы. Кроме того, какой браузер и ОС вы используете?   -  person Anthony Chu    schedule 28.07.2019
comment
Привет ! У меня такая же проблема в течение 3 дней, но из приложения Angular есть ли у вас какое-нибудь решение?   -  person Christophe Gigax    schedule 28.09.2019
comment
@ChristopheGigax: На самом деле проблема заключалась в том, что я просто открывал html-файл напрямую, и это вызывало эту проблему. Как только я разместил эту страницу, эта проблема была решена.   -  person Kiran    schedule 30.09.2019


Ответы (1)


Это немного отвлекающий маневр и, похоже, не связан со мной CORS. Я вижу, вы используете службу Azure SignalR, способ подключения к ней отличается от стандартного SignalR.

Функция negotiate по-разному ведет себя со службой SignalR. negotiate вернет некоторые данные вместе с accessToken и URL-адресом вашей службы SignalR, вам нужно будет использовать этот URL-адрес вместо этого для подключения.

Ниже я добавил пример того, как это должно работать. (Я не тестировал это, но, надеюсь, вы поняли идею).

function initialize() {
    axios.get(window.apiBaseUrl+"/api/negotiate").then(response => {        
        const options = {
            accessTokenFactory: () => response.data.accessToken
        }
        const socket = new SignalR.HubConnectionBuilder()
            .withUrl(response.data.url, options)
            .build(SignalR.HttpTransportType.None)

        connection.on('OnNewEvent', ProcessMyEvent);
        connection.onclose(() => console.log('disconnected'));
        console.log('connecting...');

        connection.start({ withCredentials: false })
            .then(() => console.log('ready...'))
            .catch(console.error);
    });
}
person Charlie.H    schedule 30.07.2019
comment
Это то, что сработало для нас, когда мы хотим использовать приложение-функцию Linux, а также в случае, если вы хотите использовать * в качестве разрешенных источников в конфигурации cors на портале Azure в разделе Конфигурация для приложения-функции. Большое спасибо. - person Hardik Mistry; 27.12.2019