Ottengo "Http failure response for (unknown url): 0 Unknown Error" invece del messaggio di errore effettivo in Angular


121

Sto usando Angular 4 HttpClientper inviare richieste a un servizio esterno. È una configurazione molto standard:

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

Il problema è che quando la richiesta fallisce vedo un Http failure response for (unknown url): 0 Unknown Errormessaggio generico nella console. Nel frattempo, quando controllo la richiesta non riuscita in Chrome, vedo che lo stato della risposta è 422 e nella scheda "anteprima" vedo il messaggio effettivo che designa la causa dell'errore.

Come si accede al messaggio di risposta effettivo che posso vedere negli strumenti di sviluppo di Chrome?

Ecco uno screenshot che mostra il problema: inserisci qui la descrizione dell'immagine


prova a registrare l'intero erroggetto - non solo ilmessage
Pavel Agarkov

Sto affrontando lo stesso problema e stavo per creare una domanda anche per questo, ecco l'oggetto err completo: gist.github.com/GO3LIN/7cffc3b0aa1f24d3e23e28cc907237fc
Mehdi Benmoha

1
O meglio {"headers": {"normalizedNames": {}, "lazyUpdate": null, "headers": {}}, "status": 0, "statusText": "Unknown Error", "url": null, "ok": false, "name": "HttpErrorResponse", "message": "Http failure response for (unknown url): 0 Unknown Error", "error": {"isTrusted": true}}
Mehdi Benmoha

@PavelAgarkov, non si tratta di registrare solo messaggi. L'HttpErrorResponse che ricevo semplicemente non contiene il messaggio di errore effettivo. Ecco uno screenshot del problema. Puoi vedere che l'errore che registro ha un messaggio che dice "... errore sconosciuto ..." ma quando guardi l'anteprima della risposta alla richiesta sopra puoi vedere il messaggio effettivo e significativo.
grdl

Stai usando un service worker?
Mackelito

Risposte:


96

Il problema era correlato a CORS . Ho notato che c'era un altro errore nella console Chrome:

Nessuna intestazione "Access-Control-Allow-Origin" è presente sulla risorsa richiesta. L'accesso all'origine " http: // localhost: 4200 " non è pertanto consentito. La risposta aveva il codice di stato HTTP 422

Ciò significa che la risposta dal server backend mancava l' Access-Control-Allow-Originintestazione anche se il backend nginx era configurato per aggiungere quelle intestazioni alle risposte con la add_headerdirettiva .

Tuttavia, questa direttiva aggiunge intestazioni solo quando il codice di risposta è 20X o 30X. Nelle risposte di errore mancavano le intestazioni. Avevo bisogno di utilizzare il alwaysparametro per assicurarmi che l'intestazione fosse aggiunta indipendentemente dal codice di risposta:

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

Una volta che il backend è stato configurato correttamente, ho potuto accedere al messaggio di errore effettivo nel codice angolare.


anche il seguente collegamento può essere utile per abilitare CORS: docs.microsoft.com/en-us/aspnet/web-api/overview/security/…
Bobs

11
dove dovrebbe essere aggiunta questa linea?
Omid Ataollahi

1
come si aggiunge "sempre" a una funzione express.js .use? Tipicamente la struttura è: app.use (function (req, res, next) {res.header ("Access-Control-Allow-Origin", " localhost: 4200" );…}); Come puoi vedere, res.header consente due parametri ... una stringa di controllo e un valore. Ho provato ad aggiungere "sempre" in vari modi ma sembrano fallire tutti. Eventuali suggerimenti?
AppDreamer

@grdl, dove aggiungere la riga add_header?
sattva_venu

dove aggiungere questa riga? Uso php per la mia API
Mustafa UYSAL

19

Nel caso in cui qualcun altro finisse perduto come me ... I miei problemi NON erano dovuti a CORS (ho il pieno controllo dei server e CORS è stato configurato correttamente!).

Il mio problema era perché utilizzo la piattaforma Android di livello 28 che disabilita le comunicazioni di rete in chiaro per impostazione predefinita e stavo cercando di sviluppare l'app che punta all'IP del mio laptop (che esegue il server API). L'URL di base dell'API è simile a http: // [LAPTOP_IP]: 8081 . Poiché non è https , android webview blocca completamente la rete xfer tra il telefono / emulatore e il server sul mio laptop. Per risolvere questo problema:

Aggiungi una configurazione di sicurezza di rete

Nuovo file nel progetto: 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>

NOTA: questo dovrebbe essere usato con attenzione in quanto consentirà tutto il testo in chiaro dalla tua app (niente costretto a usare https). Puoi restringerlo ulteriormente se lo desideri.

Fare riferimento alla configurazione nel file config.xml principale

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

Questo è tutto! Da lì ho ricostruito l'APK e l'app era ora in grado di comunicare sia dall'emulatore che dal telefono.

Maggiori informazioni sulla rete sec: https://developer.android.com/training/articles/security-config.html#CleartextTrafficPermitted


Grazie mille! Stavo anche usando un URL "http". L'ho cambiato in "https" e ha funzionato. A proposito, cambiare semplicemente un URL in https non funzionerà, è necessario un certificato per gestirlo. Il server che stavo usando supporta entrambi, quindi è stato più facile per me. Comunque, grazie mille!
Xonshiz

1
sì ... per me si tratta di cleartext troppo .... perché sto utilizzando http.. non sarebbe essere problema se io uso https.... ma nel caso in cui ho ancora voglia di usare http, i direttamente aggiungere android:usesCleartextTraffic="true"in applicationtag AndroidManifest.xml. ..e sta funzionando .... grazie per aver parlato di cleartext...
Syamsoul Azrien

Come posso abilitarlo in Spring Boot? Mi dispiace se la domanda è troppo banale ma sono un principiante e non riesco a trovare alcuna soluzione online
Asma Rahim Ali Jafri

13

funziona per me dopo aver disattivato l'estensione di blocco degli annunci in Chrome, questo errore a volte appare perché qualcosa che blocca http nel browser

inserisci qui la descrizione dell'immagine


1
per me è stato uBlock Origin che ha bloccato il download di file con "analisi" nel nome
marzo

9

Se stai usando l'applicazione .NET Core, questa soluzione potrebbe aiutarti!

Inoltre, questo potrebbe non essere un errore di richiesta angolare o di altro tipo nella tua applicazione front-end

Innanzitutto, devi aggiungere il pacchetto Microsoft CORS Nuget:

Install-Package Microsoft.AspNetCore.Cors

È quindi necessario aggiungere i servizi CORS nel file startup.cs. Nel tuo metodo ConfigureServices dovresti avere qualcosa di simile al seguente:

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

Successivamente, aggiungi il middleware CORS alla tua app. Nel tuo startup.cs dovresti avere un metodo Configure. Devi averlo simile a questo:

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

Le opzioni lambda sono un'API fluente in modo da poter aggiungere / rimuovere tutte le opzioni extra di cui hai bisogno. Puoi effettivamente utilizzare l'opzione "AllowAnyOrigin" per accettare qualsiasi dominio, ma ti consiglio vivamente di non farlo in quanto apre chiamate cross origin da chiunque. Puoi anche limitare le chiamate cross origin al loro metodo HTTP (GET / PUT / POST ecc.), In modo da poter esporre solo le chiamate GET cross-domain ecc.


5

Questo errore si è verificato per me in Firefox ma non in Chrome durante lo sviluppo locale, e si è scoperto che Firefox non si fidava del certificato SSL della mia API locale (che non è valido, ma l'avevo aggiunto al mio archivio di certificati locale, che lasciava chrome si fida di esso ma non ff). Navigare direttamente all'API e aggiungere un'eccezione in Firefox ha risolto il problema.


1
Ho esaminato diverse risposte CORS e una dopo l'altra ciascuna non ha fornito una soluzione quando si utilizza Firefox. Ho guardato questo post e ho pensato, "non è assolutamente così ma sono senza idee che diavolo" e abbastanza sicuro che ha funzionato. Grazie mille!
Aaron Jordan

@frax, ho avuto esattamente lo stesso caso! Grazie! :)
W92

5

Per me è stato causato da un'eccezione JsonSerializerException lato server.

Si è verificata un'eccezione non gestita durante l'esecuzione della richiesta Newtonsoft.Json.JsonSerializationException: loop autoreferenziale rilevato con tipo ...

Il cliente ha detto:

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

Rendere il tipo di risposta più semplice eliminando i loop ha risolto il problema.


2

Se stai usando Laravel come backend, modifica il tuo file .htaccess semplicemente incollando questo codice, per risolvere il problema CROS nel tuo progetto Angular o IONIC

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

6
Non dovresti mai permettere "*"! In generale sai chi sta parlando al tuo backend e dovresti impostare esplicitamente il suo host.
itmuckel

@itmuckel ma se stai facendo un'app per Android l'host non è noto. Ci saranno tutti i cellulari che consumeranno il tuo servizio, giusto?
Martin

2
dovevamo usare cordova-plugin-advanced-http e il wrapper @ ionic / native per avere chiamate http dal dispositivo in modo nativo invece di usare una chiamata ajax basata su browser. @Martin
user323774

2

Un errore simile può verificarsi quando non hai fornito un certificato client e un token validi che il tuo server comprende:

Errore:

Risposta di errore HTTP per (URL sconosciuto): 0 Errore sconosciuto

Codice di esempio:

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

}

Nota che entrambi MyClientCert& MyTokensono stringhe vuote, da cui l'errore.
MyClientCert& MyTokenpuò essere qualsiasi nome compreso dal tuo server.


Uso questo codice nella mia app ionica. la mia app ionica usata come indice nel mio sito. ma questi trucchi non possono aiutarmi. sembra che le mie API in laravel necessitino di configurazione forse in ngnix o laravel o il mio host docker ... ho usato il middleware cors per cors abilitato e ha funzionato sul mio locale con http ma quando distribuito su docker non posso chiamare il mio api con https
sabre tabatabaee yazdi

quando chiamo le mie rest api da http quelle funzionavano ma quando chiamo https non hanno risposto ai miei clienti. e restituisce l'errore di tipo misto. Penso che ci siano errori di certificato o qualcosa come la configurazione di nginx o .htaccess perché aggiungo il middleware cors per cors e tutte le cose hanno funzionato bene senza https. il mio client ospitato su una chiamata http Il risultato http è ok. ma quando il mio host client su https e si sono verificati errori di chiamata https
sabre tabatabaee yazdi

Ok, una soluzione è, vai all'URL https: // che hai e fai clic sull'icona del lucchetto accanto a https, scarica il certificato in un file, leggi quel file tramite import / require / fs, quindi dallo / passa quello stringa del certificato alla chiamata all'URL, quindi funzionerà.
Manohar Reddy Poreddy

2

Sto usando ASP.NET SPA Extensions che mi crea un proxy sulle porte 5000 e 5001 che passano attraverso la porta 4200 di Angular durante lo sviluppo.

Avevo impostato correttamente CORS per la porta https 5001 e tutto andava bene, ma sono andato inavvertitamente a un vecchio segnalibro che era per la porta 5000. Poi improvvisamente è apparso questo messaggio. Come altri hanno detto nella console, c'era un messaggio di errore di "verifica preliminare".

Quindi, indipendentemente dal tuo ambiente, se stai usando CORS assicurati di aver specificato tutte le porte, poiché l'host e la porta sono entrambi importanti.


2

Ricevo esattamente quel messaggio ogni volta che le mie richieste impiegavano più di 2 minuti per finire. Il browser si disconnetteva dalla richiesta, ma la richiesta sul back-end continuava fino al termine. Il server (ASP.NET Web API nel mio caso) non rileva la disconnessione.

Dopo un'intera giornata di ricerche, ho finalmente trovato questa risposta , spiegando che se usi il proxy config , ha un timeout predefinito di 120 secondi (o 2 minuti).

Quindi, puoi modificare la configurazione del proxy e impostarlo su ciò di cui hai bisogno:

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

Ora, stavo usando agentkeepalive per farlo funzionare con l'autenticazione NTLM e non sapevo che il timeout dell'agente non ha nulla a che fare con il timeout del proxy, quindi devono essere impostati entrambi. Mi ci è voluto un po 'per rendermene conto, quindi ecco un esempio:

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

Per me è stato un problema con il browser, poiché le mie richieste funzionavano bene in Postman.

Si scopre che per qualche motivo, Firefox e Chrome hanno bloccato le richieste di 6000trasferimento, una volta modificata la porta dell'API ASP.NET in4000 , l'errore è stato modificato in un errore CORS noto che potevo correggere.

Chrome almeno mi ha mostrato ERR_UNSAFE_PORTche mi ha dato un indizio su cosa potrebbe essere sbagliato.


1

Se disponi di un'intestazione cors corretta. La rete aziendale potrebbe rimuovere l'intestazione cors. Se il sito web è accessibile dall'esterno, prova ad accedervi dall'esterno della rete per verificare se la rete sta causando il problema: una buona idea indipendentemente dalla causa.


1

In asp.net core, se il tuo controller API non ha l'annotazione chiamata [AllowAnonymous], aggiungila sopra il nome del controller come

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


0

Il mio è stato causato da una relazione non valida nei modelli che stavo cercando di interrogare. Capito eseguendo il debug della risposta si è verificato un arresto anomalo nella relazione.


0

Per me non è stato un problema angolare. Era un campo di tipo DateTime nel DB che ha un valore di (0000-00-00) e il mio modello non può legare correttamente quella proprietà, quindi sono passato a un valore valido come (2019-08-12).

Sto usando .net core, OData v4 e MySql (connettore EF pomelo)


0

Aggiungi questo codice nel file di connessione

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

Se questo è un servizio nodo, prova i passaggi descritti qui

Fondamentalmente, è un errore Cross-Origin Resource Sharing (CORS). Maggiori informazioni su tali errori qui .

Una volta aggiornato il mio servizio nodo con le seguenti righe, ha funzionato:

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

Il mio errore è stato che il file era troppo grande (il core dotnet sembra avere un limite a ~ 25 Mb). Ambientazione

  • maxAllowedContentLength su 4294967295 (valore massimo di uint) in web.config
  • decorare l'azione del controller con [DisableRequestSizeLimit]
  • services.Configure (options => {options.MultipartBodyLengthLimit = 4294967295;}); in Startup.cs

ha risolto il problema per me.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.