Otrzymuję „Odpowiedź błędu HTTP dla (nieznany adres URL): 0 Nieznany błąd” zamiast rzeczywistego komunikatu o błędzie w Angular


121

Używam Angular 4 HttpClientdo wysyłania żądań do usługi zewnętrznej. To bardzo standardowa konfiguracja:

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

Problem polega na tym, że gdy żądanie nie powiedzie się, Http failure response for (unknown url): 0 Unknown Errorw konsoli pojawia się ogólny komunikat. W międzyczasie, gdy sprawdzam nieudane żądanie w chrome, widzę, że status odpowiedzi to 422, aw zakładce "podgląd" widzę aktualny komunikat opisujący przyczynę niepowodzenia.

Jak uzyskać dostęp do rzeczywistego komunikatu odpowiedzi, który widzę w narzędziach programistycznych Chrome?

Oto zrzut ekranu przedstawiający problem: wprowadź opis obrazu tutaj


spróbuj zarejestrować cały errobiekt - nie tylkomessage
Pavel Agarkov

Stoję przed tym samym problemem i miałem zamiar utworzyć pytanie również do tego, oto kompletny obiekt err: gist.github.com/GO3LIN/7cffc3b0aa1f24d3e23e28cc907237fc
Mehdi Benmoha

1
Albo lepiej {"headers": {"normalizedNames": {}, "lazyUpdate": null, "headers": {}}, "status": 0, "statusText": "Nieznany błąd", "url": null, "ok": false, "name": "HttpErrorResponse", "message": "Odpowiedź o niepowodzeniu HTTP dla (nieznany adres URL): 0 nieznany błąd", "błąd": {"isTrusted": true}}
Mehdi Benmoha

@PavelAgarkov, Nie chodzi o logowanie tylko wiadomości. HttpErrorResponse, które otrzymuję, po prostu nie zawiera rzeczywistego komunikatu o błędzie. Oto zrzut ekranu przedstawiający problem. Widać tam, że zarejestrowany przeze mnie błąd zawiera komunikat "... nieznany błąd ...", ale kiedy spojrzysz na podgląd odpowiedzi na żądanie powyżej, zobaczysz rzeczywisty, znaczący komunikat.
grdl

Czy korzystasz z usług pracownika serwisu?
Mackelito,

Odpowiedzi:


96

Problem był związany z CORS . Zauważyłem, że pojawił się inny błąd w konsoli Chrome:

Żądany zasób nie zawiera nagłówka „Access-Control-Allow-Origin”. Dlatego źródło „ http: // localhost: 4200 ” nie ma dostępu. Odpowiedź miała kod statusu HTTP 422. "

Oznacza to, że w odpowiedzi z serwera zaplecza brakowało Access-Control-Allow-Originnagłówka, mimo że nginx zaplecza został skonfigurowany do dodawania tych nagłówków do odpowiedzi z add_headerdyrektywą .

Jednak ta dyrektywa dodaje nagłówki tylko wtedy, gdy kod odpowiedzi to 20X lub 30X. W odpowiedziach na błędy brakowało nagłówków. Musiałem użyć alwaysparametru, aby upewnić się, że nagłówek jest dodawany niezależnie od kodu odpowiedzi:

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

Po prawidłowym skonfigurowaniu zaplecza mogłem uzyskać dostęp do rzeczywistego komunikatu o błędzie w kodzie Angular.


również poniższy link może być pomocny przy włączaniu CORS: docs.microsoft.com/en-us/aspnet/web-api/overview/security/ ...
Bobs

11
gdzie należy dodać tę linię?
Omid Ataollahi

1
jak dodać „always” do funkcji express.js .use? Zazwyczaj struktura to: app.use (function (req, res, next) {res.header ("Access-Control-Allow-Origin", " localhost: 4200" );…}); Jak widać, res.header dopuszcza dwa parametry ... łańcuch sterujący i wartość. Próbowałem dodać „zawsze” na różne sposoby, ale wydaje się, że wszystkie zawodzą. Jakieś sugestie?
AppDreamer

@grdl, gdzie należy dodać wiersz add_header?
sattva_venu

gdzie dodać tę linię? Używam php do mojego api
Mustafa UYSAL

19

Na wypadek, gdyby ktoś inny zgubił się tak samo jak ja ... Moje problemy NIE były spowodowane przez CORS (mam pełną kontrolę nad serwerami i CORS został poprawnie skonfigurowany!).

Mój problem polegał na tym, że używam platformy Android na poziomie 28, która domyślnie wyłącza komunikację sieciową w postaci zwykłego tekstu i próbowałem opracować aplikację, która wskazuje adres IP mojego laptopa (na którym działa serwer API). Podstawowy adres URL interfejsu API to http: // [LAPTOP_IP]: 8081 . Ponieważ nie jest to protokół HTTPS , Android Webview całkowicie blokuje xfer sieciowy między telefonem / emulatorem a serwerem na moim laptopie. Aby to naprawić:

Dodaj konfigurację zabezpieczeń sieci

Nowy plik w projekcie: 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>

UWAGA: Należy tego używać ostrożnie, ponieważ zezwoli na cały zwykły tekst z Twojej aplikacji (nic nie jest zmuszone do używania https). Jeśli chcesz, możesz to jeszcze bardziej ograniczyć.

Odwołaj się do konfiguracji w głównym 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>

Otóż ​​to! Stamtąd przebudowałem APK i aplikacja była teraz w stanie komunikować się zarówno z emulatora, jak i telefonu.

Więcej informacji na temat sieci sec: https://developer.android.com/training/articles/security-config.html#CleartextTrafficPermitted


Dziękuję bardzo! Używałem również adresu URL „http”. Zmieniłem go na „https” i działało. Przy okazji, po prostu zmiana adresu URL na https nie zadziała, potrzebujesz certyfikatu, aby to obsłużyć. Serwer, z którego korzystałem, obsługuje oba, więc było mi łatwiej. Tak czy inaczej, wielkie dzięki!
Xonshiz

1
tak ... dla mnie to jest o zwykłego tekstu zbyt .... bo używam http.. to nie jest problem, jeśli mogę użyć https.... ale w przypadku nadal chcę korzystać http, i bezpośrednio dodać android:usesCleartextTraffic="true"w applicationtagu AndroidManifest.xml. ..i działa .... dzięki za wzmiankę o cleartext...
Syamsoul Azrien

Jak mogę to włączyć w Spring boot? Przepraszam, jeśli pytanie jest zbyt trywialne, ale jestem początkującym i nie mogę znaleźć żadnych rozwiązań online
Asma Rahim Ali Jafri

13

działa u mnie po wyłączeniu rozszerzenia blokującego reklamy w chrome, ten błąd czasami pojawia się ponieważ coś blokuje http w przeglądarce

wprowadź opis obrazu tutaj


1
dla mnie był to uBlock Origin, który zablokował pobieranie pliku z 'analytics' w nazwie
marke

9

Jeśli korzystasz z aplikacji .NET Core, to rozwiązanie może pomóc!

Co więcej, może to nie być błąd Angulara lub inny błąd żądania w Twojej aplikacji front-end

Najpierw musisz dodać pakiet Microsoft CORS Nuget:

Install-Package Microsoft.AspNetCore.Cors

Następnie musisz dodać usługi CORS do pliku startup.cs. W metodzie ConfigureServices powinieneś mieć coś podobnego do następującego:

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

Następnie dodaj oprogramowanie pośredniczące CORS do swojej aplikacji. W swoim startup.cs powinieneś mieć metodę Configure. Musisz mieć podobny do tego:

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

Opcje lambda to płynny interfejs API, dzięki czemu możesz dodawać / usuwać dodatkowe opcje, których potrzebujesz. W rzeczywistości możesz użyć opcji „AllowAnyOrigin”, aby zaakceptować dowolną domenę, ale zdecydowanie odradzam to robić, ponieważ otwiera to połączenia między źródłami od kogokolwiek. Możesz również ograniczyć wywołania między źródłami do ich metody HTTP (GET / PUT / POST itp.), Dzięki czemu możesz ujawniać tylko wywołania GET między domenami itp.


5

Ten błąd występował u mnie w przeglądarce Firefox, ale nie w Chrome podczas lokalnego programowania, i okazało się, że jest on spowodowany tym, że Firefox nie ufa certyfikatowi ssl mojego lokalnego interfejsu API (który jest nieprawidłowy, ale dodałem go do mojego lokalnego magazynu certyfikatów, co pozwoliło chrome mu wierzy, ale nie ff). Bezpośrednie przejście do interfejsu API i dodanie wyjątku w przeglądarce Firefox rozwiązało problem.


1
Przeszedłem przez kilka odpowiedzi CORS i jedna po drugiej nie zapewniała rozwiązania podczas korzystania z przeglądarki Firefox. Spojrzałem na ten post i pomyślałem, "nie ma mowy, to jest to, ale nie mam pomysłów co do cholery" i na pewno zadziałało. Dziękuję bardzo!
Aaron Jordan

@frax, miałem dokładnie ten sam przypadek! Dzięki! :)
W92

5

U mnie było to spowodowane przez wyjątek JsonSerializerException po stronie serwera.

Wystąpił nieobsługiwany wyjątek podczas wykonywania żądania Newtonsoft.Json.JsonSerializationException: wykryto pętlę odwołującą się do siebie z typem ...

Klient powiedział:

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

Uproszczenie typu odpowiedzi poprzez wyeliminowanie pętli rozwiązało problem.


2

Jeśli używasz Laravel jako zaplecza, edytuj plik .htaccess, po prostu wklejając ten kod, aby rozwiązać problem CROS w projekcie Angular lub IONIC

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

6
Nigdy nie powinieneś pozwalać na "*"! Ogólnie wiesz, kto rozmawia z Twoim zapleczem i powinieneś wyraźnie ustawić jego hosta.
itmuckel

@itmuckel, ale jeśli robisz aplikację na Androida, host nie jest znany. Czy każdy telefon komórkowy będzie korzystał z Twojej usługi, prawda?
Martin

2
Musieliśmy użyć cordova-plugin-advanced-http i wrappera @ ionic / native, aby wywołania http z urządzenia były natywnie, zamiast korzystać z wywołania ajax opartego na przeglądarce. @Martin
user323774

2

Podobny błąd może wystąpić, gdy nie podałeś ważnego certyfikatu klienta i tokena, które Twój serwer rozumie:

Błąd:

Odpowiedź o błędzie HTTP dla (nieznany adres URL): 0 Nieznany błąd

Przykładowy kod:

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)) );
  }

}

Zauważ, że oba MyClientCert& MyTokensą pustymi ciągami, stąd błąd.
MyClientCert& MyTokenmoże być dowolną nazwą zrozumiałą dla Twojego serwera.


używam tego kodu w mojej aplikacji jonowej. moja aplikacja ionic używana jako indeks w mojej witrynie. ale te sztuczki nie mogą mi pomóc. wygląda na to, że moja apis w laravel wymaga konfiguracji, może w ngnix lub laravel lub na moim hoście docker ... użyłem oprogramowania pośredniego cors dla włączonych cors i działało na moim lokalnym z http, ale po wdrożeniu na dockerze nie mogę wywołać mojego interfejsu API z https
saber tabatabaee yazdi

kiedy dzwonię do moich pozostałych interfejsów API z http, te działały, ale kiedy dzwonię do https, nie odpowiedzieli moim klientom. i zwróć błąd typu mieszanego. Myślę, że wystąpił błąd certyfikatu lub coś takiego jak konfiguracja nginx lub .htaccess, ponieważ dodaję oprogramowanie pośredniczące cors dla cors i wszystko działało dobrze bez https. mój klient hostowany na połączenie http, wynik http jest prawidłowy. ale kiedy mój klient hostuje na https i wywołuje błędy https
saber tabatabaee yazdi

Ok, jednym rozwiązaniem jest, przejdź do adresu URL https: //, który masz, i kliknij ikonę kłódki obok https, pobierz certyfikat do pliku, przeczytaj ten plik przez import / require / fs, a następnie podaj / przepuść to ciąg certyfikatu do wywołania adresu URL, to zadziała.
Manohar Reddy Poreddy

2

Używam rozszerzeń ASP.NET SPA, które tworzą proxy na portach 5000 i 5001, które przechodzą do portu 4200 Angulara podczas programowania.

Miałem poprawnie skonfigurowany CORS dla portu https 5001 i wszystko było w porządku, ale nieumyślnie przeszedłem do starej zakładki, która była dla portu 5000. Wtedy nagle pojawił się ten komunikat. Jak powiedzieli inni w konsoli, pojawił się komunikat o błędzie „preflight”.

Dlatego niezależnie od środowiska, jeśli używasz CORS, upewnij się, że określono wszystkie porty - ponieważ host i port mają znaczenie.


2

Otrzymywałem tę dokładną wiadomość, gdy moje prośby zajmowały więcej niż 2 minuty. Przeglądarka rozłączała się z żądaniem, ale żądanie w zapleczu trwało aż do zakończenia. Serwer (ASP.NET Web API w moim przypadku) nie wykrył rozłączenia.

Po całodniowych poszukiwaniach w końcu znalazłem tę odpowiedź , wyjaśniając, że jeśli używasz konfiguracji proxy , ma domyślny limit czasu wynoszący 120 sekund (lub 2 minuty).

Możesz więc edytować konfigurację serwera proxy i ustawić ją na dowolną potrzebną:

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

Teraz używałem agentkeepalive, aby działało z uwierzytelnianiem NTLM i nie wiedziałem, że limit czasu agenta nie ma nic wspólnego z limitem czasu serwera proxy, więc oba muszą być ustawione. Trochę mi to zajęło, więc oto przykład:

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

Dla mnie był to problem z przeglądarką, ponieważ moje żądania działały dobrze w programie Postman.

Okazuje się, że z jakiegoś powodu Firefox i Chrome zablokowały żądania przechodzące do portu 6000, kiedy zmieniłem port API ASP.NET na 4000, błąd zmienił się na znany błąd CORS, który mogłem naprawić.

Chrome przynajmniej pokazał mi, ERR_UNSAFE_PORTco dało mi wskazówkę, co może być nie tak.


1

Jeśli masz odpowiedni nagłówek cors na miejscu. Twoja sieć firmowa może usuwać nagłówek cors. Jeśli witryna jest dostępna z zewnątrz, spróbuj uzyskać do niej dostęp spoza sieci, aby sprawdzić, czy to sieć powoduje problem - dobry pomysł niezależnie od przyczyny.


1

W asp.net core, jeśli kontroler API nie ma wywoływanej adnotacji [AllowAnonymous], dodaj ją powyżej nazwy kontrolera, na przykład

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


0

Mój był spowodowany nieprawidłową relacją w modelach, które próbowałem sprawdzić. Zrozumiano, debugując odpowiedź, która spowodowała awarię w relacji.


0

Dla mnie to nie był problem kątowy. Czy w bazie danych było pole typu DateTime, które ma wartość (0000-00-00), a mój model nie może powiązać tej właściwości poprawnie, więc zmieniłem na prawidłową wartość, taką jak (2019-08-12).

Używam .net core, OData v4 i MySql (złącze EF pomelo)


0

Dodaj te kody do pliku połączenia

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

Jeśli jest to usługa węzłowa, wykonaj czynności opisane tutaj

Zasadniczo jest to błąd udostępniania zasobów między źródłami (CORS). Więcej informacji o takich błędach tutaj .

Po zaktualizowaniu usługi węzła następującymi wierszami zadziałało:

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

Mój błąd polegał na tym, że plik był zbyt duży (rdzeń dotnet wydaje się mieć limit @ ~ 25 MB). Oprawa

  • maxAllowedContentLength do 4294967295 (maksymalna wartość uint) w web.config
  • dekorowanie akcji kontrolera za pomocą [DisableRequestSizeLimit]
  • services.Configure (options => {options.MultipartBodyLengthLimit = 4294967295;}); w Startup.cs

rozwiązał problem za mnie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.