Я получаю «Ответ об ошибке HTTP для (неизвестный URL): 0 Неизвестная ошибка» вместо фактического сообщения об ошибке в Angular

121

Я использую Angular 4 HttpClientдля отправки запросов во внешнюю службу. Это очень стандартная установка:

this.httpClient.get(url).subscribe(response => {
  //do something with response
}, err => {
  console.log(err.message);
}, () => {
  console.log('completed');
}

Проблема в том, что когда запрос не выполняется, я вижу Http failure response for (unknown url): 0 Unknown Errorв консоли общее сообщение. Между тем, когда я проверяю неудавшийся запрос в chrome, я вижу статус ответа 422, а на вкладке «предварительный просмотр» я вижу фактическую причину сбоя в сообщении.

Как мне получить доступ к фактическому ответному сообщению, которое я вижу в инструментах Chrome dev?

Вот скриншот, демонстрирующий проблему: введите описание изображения здесь

grdl
источник
попробуйте зарегистрировать весь errобъект - не толькоmessage
Павел Агарков
Я столкнулся с той же проблемой и собирался создать вопрос для этого тоже, вот полный объект ошибки
Мехди Бенмоха
1
Или лучше {"headers": {"normalizedNames": {}, "lazyUpdate": null, "headers": {}}, "status": 0, "statusText": "Неизвестная ошибка", "url": null, "ok": false, "name": "HttpErrorResponse", "message": "Ответ HTTP с ошибкой для (неизвестный URL): 0 Неизвестная ошибка", "error": {"isTrusted": true}}
Мехди Бенмоха,
@PavelAgarkov, дело не в логировании только сообщения. Полученный мной HttpErrorResponse просто не содержит фактического сообщения об ошибке. Вот скриншот проблемы. Вы можете видеть, что в журнале ошибок есть сообщение "... неизвестная ошибка ...", но когда вы посмотрите на предварительный просмотр ответа на запрос выше, вы увидите фактическое содержательное сообщение.
grdl 08
Вы пользуетесь услугами сервисного работника?
Mackelito

Ответы:

97

Проблема была связана с CORS . Я заметил, что в консоли Chrome произошла еще одна ошибка:

На запрошенном ресурсе отсутствует заголовок Access-Control-Allow-Origin. Происхождение « HTTP: // локальный: 4200 », следовательно , не имеет права доступа. Ответ имел код состояния HTTP 422.

Это означает, что в ответе внутреннего сервера отсутствовал Access-Control-Allow-Originзаголовок, хотя серверный nginx был настроен на добавление этих заголовков в ответы с помощью add_headerдирективы .

Однако эта директива добавляет заголовки только тогда, когда код ответа равен 20X или 30X. В сообщениях об ошибках отсутствовали заголовки. Мне нужно было использовать alwaysпараметр, чтобы убедиться, что заголовок добавлен независимо от кода ответа:

add_header 'Access-Control-Allow-Origin' 'http://localhost:4200' always;

Как только бэкэнд был правильно настроен, я мог получить доступ к фактическому сообщению об ошибке в коде Angular.

grdl
источник
также следующая ссылка может быть полезна для включения CORS: docs.microsoft.com/en-us/aspnet/web-api/overview/security/…
Bobs
11
где нужно добавить эту строку?
Омид
1
как добавить слово «всегда» к функции .use в express.js? Обычно структура выглядит так: app.use (function (req, res, next) {res.header ("Access-Control-Allow-Origin", " localhost: 4200" );…}); Как видите, res.header допускает два параметра ... управляющую строку и значение. Я пытался добавить «всегда» разными способами, но все они, похоже, терпели неудачу. Какие-либо предложения?
AppDreamer
@grdl, где нужно добавить строку add_header?
sattva_venu
где добавить эту строчку? Я использую php для своего api
Мустафа UYSAL
19

В случае, если кто-то еще окажется таким же потерянным, как и я ... Мои проблемы НЕ были связаны с CORS (я полностью контролирую сервер (ы), и CORS был настроен правильно!).

Моя проблема заключалась в том, что я использую платформу Android уровня 28, которая по умолчанию отключает сетевую связь в открытом виде, и я пытался разработать приложение, которое указывает на IP-адрес моего ноутбука (на котором запущен сервер API). Базовый URL-адрес API выглядит примерно так : http: // [LAPTOP_IP]: 8081 . Поскольку это не https , android webview полностью блокирует xfer сети между телефоном / эмулятором и сервером на моем ноутбуке. Чтобы это исправить:

Добавить конфигурацию сетевой безопасности

Новый файл в проекте: resources / android / xml / network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <!-- Set application-wide security config -->
  <base-config cleartextTrafficPermitted="true"/>
</network-security-config>

ПРИМЕЧАНИЕ. Это следует использовать осторожно, так как это разрешит весь открытый текст из вашего приложения (ничто не заставляет использовать https). Вы можете ограничить его, если хотите.

Ссылка на конфигурацию в основном config.xml

<platform name="android">
    ...
    <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application" xmlns:android="http://schemas.android.com/apk/res/android">
        <application android:networkSecurityConfig="@xml/network_security_config" />
    </edit-config>
    <resource-file src="resources/android/xml/network_security_config.xml" target="app/src/main/res/xml/network_security_config.xml" />
    ....
</platform>

Это оно! Оттуда я восстановил APK, и теперь приложение могло связываться как с эмулятором, так и с телефона.

Дополнительная информация о сетевой сек: https://developer.android.com/training/articles/security-config.html#CleartextTrafficPermitted

haggy
источник
Большое спасибо! Я также использовал URL-адрес "http". Изменил его на «https», и все заработало. Кстати, просто изменить URL-адрес на https не получится, для этого нужен сертификат. Сервер, который я использовал, поддерживает оба, так что мне было проще. В любом случае, спасибо большое!
Xonshiz
1
да ... для меня это не о .... слишком открытом тексте , потому что я использую http.. это бы не быть проблемой , если я использую https.... но в случае , если я все еще хочу использовать http, я сразу добавить android:usesCleartextTraffic="true"в applicationтеге в AndroidManifest.xml. ..и это работает .... спасибо за упоминание о cleartext...
Syamsoul Azrien
Как я могу включить это при загрузке Spring? Прошу прощения, если вопрос слишком тривиален, но я новичок и не могу найти никаких решений в Интернете
Асма Рахим Али Джафри
13

работает для меня после отключения расширения блокировки рекламы в Chrome, эта ошибка иногда появляется из-за того, что что-то блокирует http в браузере

введите описание изображения здесь

Дви Януар Ильхам
источник
1
для меня это было uBlock Origin , который заблокировал загрузку файла с «аналитикой» в этом имени
Marke
9

Если вы используете приложение .NET Core, это решение может помочь!

Более того, это может быть не ошибка Angular или другая ошибка запроса в вашем клиентском приложении.

Во-первых, вам нужно добавить пакет Microsoft CORS Nuget:

Install-Package Microsoft.AspNetCore.Cors

Затем вам нужно добавить службы CORS в файл startup.cs. В вашем методе ConfigureServices должно быть что-то похожее на следующее:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors();
}

Затем добавьте в свое приложение промежуточное ПО CORS. В вашем startup.cs у вас должен быть метод настройки. Вам нужно, чтобы это было примерно так:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
ILoggerFactory loggerFactory)
{
    app.UseCors( options => 
    options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
    app.UseMvc();
}

Лямбда параметров - это удобный API, поэтому вы можете добавлять / удалять любые дополнительные параметры, которые вам нужны. Фактически вы можете использовать опцию «AllowAnyOrigin», чтобы принять любой домен, но я настоятельно рекомендую вам не делать этого, поскольку он открывает вызовы из разных источников от кого-либо. Вы также можете ограничить перекрестные вызовы источников их HTTP-методом (GET / PUT / POST и т. Д.), Чтобы вы могли только открывать перекрестные доменные вызовы GET и т. Д.

Sathish
источник
5

Эта ошибка возникала у меня в Firefox, но не в Chrome при локальной разработке, и оказалось, что Firefox не доверяет моему локальному сертификату ssl API (который недействителен, но я добавил его в свое локальное хранилище сертификатов, что позволило хром доверять ему но не ff). Непосредственный переход к API и добавление исключения в Firefox устранили проблему.

FRAX
источник
1
Я просмотрел несколько ответов CORS, и один за другим каждый из них не предлагал решения при использовании Firefox. Я посмотрел на этот пост и подумал: «Да нет, но у меня нет идей, какого черта», и, конечно же, это сработало. Спасибо вам большое!
Аарон Джордан
@frax, у меня точно такой же был случай! Спасибо! :)
W92
5

Для меня это было вызвано исключением JsonSerializerException на стороне сервера.

Произошло необработанное исключение при выполнении запроса Newtonsoft.Json.JsonSerializationException: обнаружен цикл самореференции с типом ...

Клиент сказал:

POST http://localhost:61495/api/Action net::ERR_INCOMPLETE_CHUNKED_ENCODING
ERROR HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: null, ok: false, …}

Упрощение типа ответа за счет устранения петель решило проблему.

Perrier
источник
2

Если вы используете Laravel в качестве Backend, отредактируйте файл .htaccess, просто вставив этот код, чтобы решить проблему CROS в вашем проекте Angular или IONIC.

Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Methods: "GET,POST,OPTIONS,DELETE,PUT"
Ширджил Хан
источник
6
Никогда не позволяйте "*"! В общем, вы знаете, кто разговаривает с вашим сервером, и вам следует явно указать его хост.
itmuckel
@itmuckel, но если вы делаете приложение для Android, хост не известен. Будет ли каждый мобильный телефон использовать ваши услуги, я прав?
Martin
2
нам нужно было использовать cordova-plugin-advanced-http и @ ionic / native wrapper для нативных HTTP-вызовов с устройства вместо использования ajax-вызова на основе браузера. @Martin
user323774
2

Аналогичная ошибка может возникнуть, если вы не предоставили действующий сертификат клиента и токен, который понимает ваш сервер:

Ошибка:

Ответ об ошибке HTTP для (неизвестный URL): 0 Неизвестная ошибка

Пример кода:

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';

class MyCls1 {

  constructor(private http: HttpClient) {
  }

  public myFunc(): void {

    let http: HttpClient;

    http.get(
      'https://www.example.com/mypage',
      {
        headers:
          new HttpHeaders(
            {
              'Content-Type': 'application/json',
              'X-Requested-With': 'XMLHttpRequest',
              'MyClientCert': '',        // This is empty
              'MyToken': ''              // This is empty
            }
          )
      }
    ).pipe( map(res => res), catchError(err => throwError(err)) );
  }

}

Обратите внимание, что оба MyClientCert& MyTokenявляются пустыми строками, отсюда и ошибка.
MyClientCert& MyTokenможет быть любым именем, понятным вашему серверу.

Манохар Редди Поредди
источник
Я использую этот код в своем ионном приложении. мое ионное приложение используется в качестве индекса на моем сайте. но эти уловки мне не помогут. кажется, мой apis в laravel нуждается в конфигурации, возможно, в ngnix или laravel или моем хосте докера ... я использовал промежуточное программное обеспечение cors для включения cors, и он работал на моем локальном компьютере с http, но при развертывании на докере не мог вызвать мой api с https
saber tabatabaee yazdi
когда я вызываю свой отдых apis из http, они работали, но при вызове https они не отвечали моим клиентам. и вернуть ошибку смешанного типа. Я думаю, что есть ошибка сертификата или что-то вроде конфигурации nginx или .htaccess, потому что я добавляю промежуточное ПО cors для cors, и все работает хорошо без https. мой клиент размещен на http-вызове http-результат в порядке. но когда мой клиентский хост на https и вызов https произошли ошибки
saber tabatabaee yazdi
Хорошо, одно из решений - перейдите по URL-адресу https: //, который у вас есть, и щелкните значок замка рядом с https, загрузите сертификат в файл, прочтите этот файл через import / require / fs, затем дайте / передайте это строка сертификата на вызов по URL-адресу, тогда он будет работать.
Манохар Редди Поредди
2

Я использую расширения ASP.NET SPA, которые создают мне прокси на портах 5000 и 5001, которые передаются на порт 4200 Angular во время разработки.

Я правильно настроил CORS для https-порта 5001, и все было в порядке, но я случайно перешел на старую закладку, которая была для порта 5000. Затем внезапно возникло это сообщение. Как другие говорили в консоли, появилось сообщение об ошибке «предполетная».

Итак, независимо от вашей среды, если вы используете CORS, убедитесь, что у вас указаны все порты - поскольку хост и порт имеют значение.

Simon_Weaver
источник
2

Я получал именно это сообщение всякий раз, когда выполнение моих запросов занимало более 2 минут. Браузер отключился от запроса, но запрос на серверной части продолжался, пока не был завершен. Сервер (в моем случае веб-API ASP.NET) не обнаружил разъединение.

После целого дня поиска я наконец нашел этот ответ , объяснив, что если вы используете конфигурацию прокси , у него по умолчанию тайм-аут 120 секунд (или 2 минуты).

Итак, вы можете отредактировать конфигурацию прокси и установить все, что вам нужно:

{
  "/api": {
    "target": "http://localhost:3000",
    "secure": false,
    "timeout": 6000000
  }
}

Теперь я использовал agentkeepalive, чтобы заставить его работать с аутентификацией NTLM , и не знал, что тайм-аут агента не имеет ничего общего с тайм-аутом прокси, поэтому оба должны быть установлены. Мне потребовалось время, чтобы осознать это, поэтому вот пример:

const Agent = require('agentkeepalive');

module.exports = {
    '/api/': {
        target: 'http://localhost:3000',
        secure: false,
        timeout: 6000000,          // <-- this is needed as well
        agent: new Agent({
            maxSockets: 100,
            keepAlive: true,
            maxFreeSockets: 10,
            keepAliveMsecs: 100000,
            timeout: 6000000,      // <-- this is for the agentkeepalive
            freeSocketTimeout: 90000
        }),
        onProxyRes: proxyRes => {
            let key = 'www-authenticate';
            proxyRes.headers[key] = proxyRes.headers[key] &&
                proxyRes.headers[key].split(',');
        }
    }
};
Маркос Димитрио
источник
2

Для меня это была проблема браузера, так как мои запросы нормально работали в Postman.

Оказывается, по какой-то причине Firefox и Chrome заблокировали запросы, идущие на порт 6000, после того как я изменил порт API ASP.NET на 4000, ошибка изменилась на известную ошибку CORS, которую я мог исправить.

Chrome по крайней мере показал мне, ERR_UNSAFE_PORTчто дало мне понять, что может быть не так.

Шахин Дохан
источник
1

Если у вас есть правильный заголовок cors. Возможно, в вашей корпоративной сети отсутствует заголовок cors. Если веб-сайт доступен извне, попробуйте получить к нему доступ из-за пределов своей сети, чтобы проверить, не вызывает ли сеть проблема - хорошая идея независимо от причины.

N-поели
источник
1

В ядре asp.net, если ваш контроллер api не имеет вызываемой аннотации [AllowAnonymous], добавьте ее над именем вашего контроллера, например

[ApiController]
    [Route("api/")]
    [AllowAnonymous]
    public class TestController : ControllerBase
dgncn
источник
0

Не такой старый, как другие вопросы, но я просто боролся с этим в приложении Ionic-Laravel, и здесь ничего не работает (и другие сообщения), поэтому я установил дополнение https://github.com/barryvdh/laravel-cors в Laravel и запустился, и он работает очень хорошо.

gersonmontenegro
источник
0

Моя была вызвана недопустимыми отношениями в моделях, которые я пытался запросить. Выяснилось путем отладки ответа, что он разбился в отношении.

J.Kirk.
источник
0

Для меня это не было проблемой. Было поле типа DateTime в БД, которое имеет значение (0000-00-00), и моя модель не может правильно привязать это свойство, поэтому я изменил на допустимое значение, например (2019-08-12).

Я использую ядро ​​.net, OData v4 и MySql (коннектор EF pomelo)

Луис Лопес
источник
0

Добавьте эти коды в файл подключения

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: PUT,GET,POST,DELETE");
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
Абдельхаким Эззахрауи
источник
0

Если это служба узла, попробуйте шаги, описанные здесь

По сути, это ошибка общего доступа к ресурсам (CORS). Подробнее о таких ошибках здесь .

Как только я обновил службу узлов, добавив следующие строки, все заработало:

let express = require("express");
let app = express();

app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");    
    next();
  });
Кулак ярости
источник
-2

Моя ошибка заключалась в том, что файл был слишком большим (ядро dotnet, похоже, имеет ограничение @ ~ 25 МБ). настройка

  • maxAllowedContentLength до 4294967295 (максимальное значение uint) в web.config
  • украшение действия контроллера [DisableRequestSizeLimit]
  • services.Configure (options => {options.MultipartBodyLengthLimit = 4294967295;}); в Startup.cs

решил проблему для меня.

Spikolynn
источник