Я отримую “Http error error for (unknown URL): 0 Unknown Error” замість фактичного повідомлення про помилку у 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повідомлення в консолі. Тим часом, коли я перевіряю невдалий запит у хромі, я можу побачити стан відповіді 422, а на вкладці "Попередній перегляд" я бачу фактичне повідомлення, яке зневажує причину відмови.

Як отримати доступ до фактичного повідомлення відповіді, яке я бачу в інструментах хромованого розробника?

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


спробуйте зафіксувати весь errоб’єкт - не лишеmessage
Павло Агарков

Я зіткнувся з тією ж проблемою і збирався створити питання і для цього, ось повний об’єкт помилки
Мехді Бенмоха

1
Або краще {"headers": {"normalizedNames": {}, "lazyUpdate": null, "headers": {}}, "status": 0, "statusText": "Невідома помилка", "url": null, "ok": false, "name": "HttpErrorResponse", "message": "Http error error for (unknown URL): 0 Невідома помилка", "error": {"isTrusted": true}}
Mehdi Benmoha

@PavelAgarkov, справа не в реєстрації лише повідомлення. Виправлений я HttpErrorResponse якраз не містить фактичного повідомлення про помилку. Ось скріншот проблеми. Ви можете бачити, що помилка, яку я реєструю, містить повідомлення, що говорить "... невідома помилка ...", але коли ви подивитесь на попередній перегляд відповіді на запит, ви побачите фактичне, змістовне повідомлення.
грдл

Ви використовуєте сервісного працівника?
Маккеліто

Відповіді:


96

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

На запитуваному ресурсі немає заголовка "Access-Control-Allow-Origin". Отже, походження http: // localhost: 4200 'не має доступу. Відповідь мала код статусу HTTP 422. "

Це означає, що у відповіді сервера бекенда відсутній Access-Control-Allow-Originзаголовок, навіть якщо вхідний nginx був налаштований для додавання цих заголовків до відповідей з add_headerдирективою .

Однак ця директива додає заголовки лише тоді, коли код відповіді становить 20X або 30X. У відповідях на помилки заголовки бракували. Мені потрібно використовувати alwaysпараметр, щоб переконатися, що заголовок доданий незалежно від коду відповіді:

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

Після правильної налаштування сервера я отримав доступ до фактичного повідомлення про помилку в кодовому коді.


також наступна посилання може бути корисна для включення CORS: docs.microsoft.com/en-us/aspnet/web-api/overview/security / ...
гойдається

11
куди слід додати цей рядок?
Омід

1
як ви додаєте "завжди" до функції express.js .use? Зазвичай структурою є: app.use (функція (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 , андроїд веб-перегляд повністю блокує мережевий xfer між телефоном / емулятором та сервером на моєму ноутбуці. Щоб виправити це:

Додати конфігурацію мережевої безпеки

Новий файл у проекті: ресурси / 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 у головному 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


Дякую тонну! Я також використовував URL "http". Змінив його на "https" і воно спрацювало. До речі, просто змінити URL на https не вийде, для цього вам потрібен сертифікат. Сервер, яким я користувався, підтримує обидва, так що мені було простіше. У будь-якому випадку, дякую тонну!
Xonshiz

1
да ... для мене це не про .... занадто відкритому тексті , тому що я використовую http.. це б не бути проблемою , якщо я використовую https.... але в разі , якщо я все ще хочу використовувати http, я відразу додати android:usesCleartextTraffic="true"в applicationтезі в AndroidManifest.xml. ..і це працює .... дякую за згадку про cleartext...
Syamsoul Azrien

Як я можу це ввімкнути у весняному завантаженні? Вибачте, якщо питання занадто тривіальне, але я новачок і не можу знайти в Інтернеті жодного рішення
Асма Рахім Алі

13

працює для мене після вимкнення розширення блоку оголошень у хромі, ця помилка колись з’являється через те, що блокує http у браузері

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


1
для мене це було uBlock Origin , який заблокував завантаження файлу з «аналітикою» в цьому імені
Marke

9

Якщо ви використовуєте додаток .NET Core, це рішення може допомогти!

Більше того, це може бути не кутова або інша помилка запиту у вашому додатку

По-перше, ви повинні додати пакет 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 виклики міждоменним дзвінкам тощо.


5

Ця помилка сталася для мене в Firefox, але не в Chrome під час локальної розробки, і виявилося, що причиною цього Firefox не довіряє ssl сертифікат мого локального API (який недійсний, але я додав його до свого локального магазину cert, який дозволив хром довіряйте цьому, але не ff). Перехід до API безпосередньо та додавання виключення у Firefox виправили проблему.


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, …}

Полегшення типу відповіді шляхом усунення циклів вирішило проблему.


2

Якщо ви використовуєте Laravel як бекенд, то відредагуйте файл .htaccess, просто вставивши цей код, щоб вирішити проблему CROS у вашому проекті Angular або IONIC

Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Methods: "GET,POST,OPTIONS,DELETE,PUT"

6
Ви ніколи не повинні дозволяти "*"! Як правило, ви знаєте, хто спілкується з вашим бекендом, і вам слід чітко встановити їх хоста.
itmuckel

@itmuckel, але якщо ви робите додаток для андроїд-хоста, це невідомо. Буде кожен мобільний, який споживає вашу послугу, я правий?
Мартін

2
нам потрібно було використовувати cordova-plugin-advanced-http та оболонку @ ionic / native, щоб мати вхідні дзвінки з пристрою замість використання виклику ajax на основі браузера. @Martin
користувач323774

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 або мій хокер докер ... я використовував проміжне програмне забезпечення для корів, і він працював на моєму локальному з http, але при розгортанні на docker cant зателефонував у мій api з https
saber tabatabaee yazdi

коли я зателефонував на відпочинок з http, який працював, але під час виклику https вони не відповідали моїм клієнтам. і повернути помилку змішаного типу. Я думаю, що є помилка сертифіката або щось на зразок конфігурації nginx або .htaccess, тому що я додаю проміжне програмне забезпечення для cors, і все добре працює без https. мій клієнт, розміщений на http call http, результат - це нормально. але коли у мого клієнта на https та зателефонувавши https, сталися помилки
saber tabatabaee yazdi

Гаразд, одне рішення полягає в тому, перейдіть до https: // url, який у вас є, і натисніть на значок блокування поруч із https, завантажте сертифікат у файл, прочитайте цей файл через імпорт / вимагати / fs, а потім надайте / передайте це рядок сертифіката для виклику до URL-адреси, тоді він буде працювати.
Манохар Редді Поредді

2

Я використовую ASP.NET SPA Extensions, що створює мені проксі на порти 5000 та 5001, які проходять через порт Angular під час розробки.

У мене було правильно встановлено CORS для https-порту 5001, і все було нормально, але я ненавмисно перейшов до старої закладки, яка була для порту 5000. Потім раптом з’явилося це повідомлення. Як говорили інші, в консолі з'явилося повідомлення про помилку "перед польотом".

Тож незалежно від вашого оточення, якщо ви використовуєте CORS, переконайтеся, що у вас вказані всі порти - як хост, так і порт.


2

Я отримував таке точне повідомлення кожного разу, коли мої запити займали більше 2 хвилин. Веб-переглядач від’єднається від запиту, але запит на бекенді продовжувався до його завершення. Сервер (ASP.NET Web API в моєму випадку) не виявив би відключення.

Після цілодобового пошуку я нарешті знайшов цю відповідь , пояснивши, що якщо ви використовуєте конфігурацію проксі-сервера , вона має затримку 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, коли я змінив порт ASP.NET API 4000, помилка змінилася на відому помилку CORS, яку я міг виправити.

Chrome принаймні показав мені, ERR_UNSAFE_PORTщо дало мені зрозуміти, що може бути не так.


1

Якщо у вас є належний заголовок Cors. Можливо, ваша корпоративна мережа знімає заголовок cors. Якщо веб-сайт доступний зовні, спробуйте отримати доступ до нього за межами вашої мережі, щоб перевірити, чи викликає ця проблема проблема - хороша ідея незалежно від причини.


1

Якщо ядро ​​asp.net, якщо ваш контролер api не має анотації [AllowAnonymous], додайте його вище імені контролера

[ApiController]
    [Route("api/")]
    [AllowAnonymous]
    public class TestController : ControllerBase

0

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


0

Моє спричинено невірними стосунками в моделях, які я намагався запитувати. З'ясувалося, налагоджуючи відповідь, вона врізалася у відношення.


0

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

Я використовую .net core, 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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.