Recebo “Resposta de falha de HTTP para (URL desconhecido): 0 Erro desconhecido” em vez da mensagem de erro real no Angular

121

Estou usando o Angular 4 HttpClientpara enviar solicitações para serviços externos. É uma configuração muito padrão:

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

O problema é que, quando a solicitação falha, vejo uma Http failure response for (unknown url): 0 Unknown Errormensagem genérica no console. Enquanto isso, quando inspeciono a solicitação com falha no chrome, vejo que o status da resposta é 422 e, na guia "preview", vejo a mensagem real descrevendo a causa da falha.

Como acesso a mensagem de resposta real que posso ver nas ferramentas de desenvolvimento do chrome?

Aqui está uma captura de tela demonstrando o problema: insira a descrição da imagem aqui

grdl
fonte
tente fazer login todo errobjeto - não só amessage
Pavel Agarkov
Eu estou enfrentando o mesmo problema e estava indo para criar uma pergunta para isso também, aqui está o objeto err completa: gist.github.com/GO3LIN/7cffc3b0aa1f24d3e23e28cc907237fc
Mehdi Benmoha
1
Ou melhor {"headers": {"normalizedNames": {}, "lazyUpdate": null, "headers": {}}, "status": 0, "statusText": "Erro desconhecido", "url": null, "ok": false, "name": "HttpErrorResponse", "message": "Resposta de falha de HTTP para (URL desconhecido): 0 Erro desconhecido", "error": {"isTrusted": true}}
Mehdi Benmoha em
@PavelAgarkov, não se trata de registrar apenas mensagens. O HttpErrorResponse que eu recupero simplesmente não contém a mensagem de erro real. Aqui está uma captura de tela do problema. Você pode ver lá que o erro que eu registro tem uma mensagem dizendo "... erro desconhecido ...", mas quando você olha para a visualização da resposta da solicitação acima, pode ver a mensagem real e significativa.
grdl
Você está usando um trabalhador de serviço?
27419 Mackelito

Respostas:

96

O problema estava relacionado ao CORS . Percebi que havia outro erro no console do Chrome:

Nenhum cabeçalho 'Access-Control-Allow-Origin' está presente no recurso solicitado. A origem ' http: // localhost: 4200 ' não é, portanto, permitido o acesso. A resposta tinha o código de status HTTP 422.`

Isso significa que a resposta do servidor de back-end estava ausente do Access-Control-Allow-Origincabeçalho, embora o back-end nginx estivesse configurado para adicionar esses cabeçalhos às respostas com add_headerdiretiva .

No entanto, esta diretiva adiciona cabeçalhos apenas quando o código de resposta é 20X ou 30X. Nas respostas a erros, os cabeçalhos estavam ausentes. Eu precisava usar o alwaysparâmetro para garantir que o cabeçalho fosse adicionado, independentemente do código de resposta:

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

Depois que o back-end foi configurado corretamente, eu pude acessar a mensagem de erro real no código Angular.

grdl
fonte
também o seguinte link pode ser útil para ativar o CORS: docs.microsoft.com/en-us/aspnet/web-api/overview/security/…
Bobs
11
onde essa linha deve ser adicionada?
Omid Ataollahi 15/07/19
1
como você adiciona 'sempre' a uma função express.js .use? Normalmente, a estrutura é: app.use (function (req, res, next) {res.header ("Acesso-Controle-Permitir-Origem", " localhost: 4200" ); ...}); Como você pode ver, o res.header permite dois parâmetros ... uma sequência de controle e um valor. Tentei adicionar 'sempre' de várias maneiras, mas todas parecem falhar. Alguma sugestão?
AppDreamer 10/10/19
@grdl, onde a linha add_header deve ser adicionada?
sattva_venu 26/01
onde adicionar esta linha? Eu uso php para minha API
Mustafa UYSAL
19

Caso alguém acabe tão perdido quanto eu ... Meus problemas NÃO foram causados ​​pelo CORS (eu tenho controle total do (s) servidor (es) e o CORS foi configurado corretamente!).

Meu problema foi porque estou usando a plataforma Android nível 28, que desabilita as comunicações de rede de texto não criptografado por padrão, e estava tentando desenvolver o aplicativo que aponta para o IP do meu laptop (que está executando o servidor da API). O URL base da API é algo como http: // [LAPTOP_IP]: 8081 . Como não é https , o android webview bloqueia completamente o xfer da rede entre o telefone / emulador e o servidor no meu laptop. Para corrigir isso:

Adicionar uma configuração de segurança de rede

Novo arquivo no projeto: 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: Isso deve ser usado com cuidado, pois permitirá todo o texto não criptografado do seu aplicativo (nada forçado a usar https). Você pode restringir ainda mais, se desejar.

Consulte a configuração no arquivo config.xml principal

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

É isso aí! A partir daí, reconstruí o APK e o aplicativo agora conseguia se comunicar pelo emulador e pelo telefone.

Mais informações sobre o segundo da rede: https://developer.android.com/training/articles/security-config.html#CleartextTrafficPermitted

abatido
fonte
Muito obrigado! Eu também estava usando um URL "http". Alterou para "https" e funcionou. Aliás, apenas alterar um URL para https não funcionará, você precisa de um certificado para lidar com isso. O servidor que eu estava usando suporta ambos, por isso foi mais fácil para mim. De qualquer forma, obrigado uma tonelada!
Xonshiz 19/07/19
1
sim ... para mim é sobre cleartext também .... porque eu estou usando http.. que não iria ser um problema se eu usar https.... mas no caso de eu ainda quero usar http, eu diretamente adicionar android:usesCleartextTraffic="true"na applicationtag no AndroidManifest.xml. ..e está funcionando .... obrigado por mencionar cleartext...
Syamsoul Azrien
Como posso habilitar isso na inicialização do Spring? Lamento se a questão é muito trivial, mas eu sou um novato e eu não posso encontrar todas as soluções on-line
Asma Rahim Ali Jafri
13

trabalhando para mim depois de desativar a extensão de bloco de anúncios no chrome, esse erro aparece em algum momento porque algo que bloqueia o http no navegador

insira a descrição da imagem aqui

Dwi Yanuar Ilham
fonte
1
para mim foi uBlock Origem que bloqueou o download de arquivo com 'analytics' nele do nome
marke
9

Se você estiver usando o aplicativo .NET Core, esta solução pode ajudar!

Além disso, isso pode não ser um erro de solicitação angular ou outro no seu aplicativo front-end

Primeiro, você precisa adicionar o pacote Microsoft CORS Nuget:

Install-Package Microsoft.AspNetCore.Cors

Você precisará adicionar os serviços CORS no seu startup.cs. No seu método ConfigureServices, você deve ter algo semelhante ao seguinte:

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

Em seguida, adicione o middleware CORS ao seu aplicativo. No seu startup.cs, você deve ter um método Configure. Você precisa tê-lo semelhante a este:

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

As opções lambda são uma API fluente para que você possa adicionar / remover quaisquer opções extras necessárias. Você pode realmente usar a opção "AllowAnyOrigin" para aceitar qualquer domínio, mas eu recomendo que você não faça isso, pois abre chamadas de origem cruzada de qualquer pessoa. Você também pode limitar as chamadas de origem cruzada ao método HTTP (GET / PUT / POST etc), para que você possa expor apenas as chamadas GET entre domínios, etc.

sathish
fonte
5

Esse erro estava ocorrendo para mim no Firefox, mas não no Chrome, durante o desenvolvimento local, e acabou sendo causado pelo fato de o Firefox não confiar no certificado SSL da minha API local (que não é válido, mas eu o adicionei à minha loja local de certificados , que permite chrome confiar, mas não ff). Navegar para a API diretamente e adicionar uma exceção no Firefox corrigiu o problema.

frax
fonte
1
Passei por várias respostas do CORS e uma após a outra, cada uma não forneceu uma solução ao usar o Firefox. Eu olhei para este post e pensei: "de jeito nenhum, mas estou sem idéias, que diabos" e com certeza funcionou. Muito obrigado!
Aaron Jordan
@ Frax, eu tive exatamente o mesmo caso! Obrigado! :)
W92 13/01/19
5

Para mim, foi causado por um servidor JsonSerializerException.

Ocorreu uma exceção não tratada durante a execução da solicitação Newtonsoft.Json.JsonSerializationException: loop de auto-referência detectado com o tipo ...

O cliente disse:

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

Tornar o tipo de resposta mais simples, eliminando os loops, resolveu o problema.

Perrier
fonte
2

Se você estiver usando o Laravel como seu back-end, edite seu arquivo .htaccess apenas colando este código, para resolver o problema de CROS no seu projeto Angular ou IONIC

Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Methods: "GET,POST,OPTIONS,DELETE,PUT"
shirjeel khan
fonte
6
Você nunca deve permitir "*"! Em geral, você sabe quem está falando com seu back-end e deve definir o host explicitamente.
itmuckel
@itmuckel, mas se você estiver fazendo um aplicativo para Android, o host não é conhecido. Serão todos os dispositivos móveis que consomem o seu serviço, estou certo?
24518 Martin Martin
2
precisávamos usar cordova-plugin-advanced-http e o wrapper @ ionic / native para receber chamadas http do dispositivo nativamente, em vez de usar uma chamada ajax baseada em navegador. @Martin
user323774
2

Um erro semelhante pode ocorrer quando você não fornece um certificado de cliente válido e um token que seu servidor entende:

Erro:

Resposta de falha de HTTP para (URL desconhecido): 0 Erro desconhecido

Código de exemplo:

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

}

Note-se que ambos MyClientCert& MyTokensão strings vazias, daí o erro.
MyClientCert& MyTokenpode ser qualquer nome que seu servidor entenda.

Manohar Reddy Poreddy
fonte
Eu uso esse código no meu aplicativo iônico. meu aplicativo iônico usado como índice no meu site. mas esses truques não podem me ajudar. parece que minhas APIs no laravel precisam de configuração talvez no ngnix ou no laravel ou no meu host docker ... eu usei o cors middleware para cors ativado e funcionou no meu local com http, mas quando implantado no docker não posso chamar minha API com https
sabre tabatabaee yazdi
quando eu chamo o meu resto apis de http aqueles funcionou, mas quando chamar https eles não responderam aos meus clientes. e retorne um erro de tipo misto. Eu acho que há erro de certificado ou algo como configuração nginx ou .htaccess porque eu adiciono cors middleware para cors e todas as coisas funcionaram bem sem https. meu cliente hospedado no resultado http do http está ok. mas quando meu anfitrião cliente em https e chamada https erros aconteceu
sabre tabatabaee Yazdi
Ok, uma solução é: vá para o URL https: // que você possui e clique no ícone de cadeado ao lado do https, faça o download do certificado para um arquivo, leia esse arquivo via import / require / fs e dê / passe esse certificado para a chamada para o URL, ele funcionará.
Manohar Reddy Poreddy
2

Estou usando as extensões ASP.NET SPA, que me criam um proxy nas portas 5000 e 5001 que passam para a porta 4200 da Angular durante o desenvolvimento.

Eu tinha o CORS configurado corretamente para a porta https 5001 e tudo estava bem, mas inadvertidamente fui para um marcador antigo que era para a porta 5000. Então, de repente, essa mensagem surgiu. Como outros já disseram no console, houve uma mensagem de erro 'preflight'.

Portanto, independentemente do seu ambiente, se você estiver usando o CORS, verifique se todas as portas foram especificadas - pois o host e a porta são importantes.

Simon_Weaver
fonte
2

Eu recebia a mensagem exata sempre que meus pedidos demoravam mais de 2 minutos para terminar. O navegador se desconectaria da solicitação, mas a solicitação no back-end continuou até que fosse concluída. O servidor (API Web da ASP.NET no meu caso) não detectou a desconexão.

Depois de um dia inteiro pesquisando, finalmente encontrei esta resposta , explicando que, se você usar a configuração do proxy , ela terá um tempo limite padrão de 120 segundos (ou 2 minutos).

Portanto, você pode editar sua configuração de proxy e configurá-la para o que precisar:

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

Agora, eu estava usando agentkeepalive para fazê-lo funcionar com a autenticação NTLM e não sabia que o tempo limite do agente não tinha nada a ver com o tempo limite do proxy, portanto, é necessário definir os dois. Levei um tempo para perceber isso, então aqui está um exemplo:

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(',');
        }
    }
};
Marcos Dimitrio
fonte
2

Para mim, era um problema de navegador, pois meus pedidos estavam funcionando bem no Postman.

Acontece que, por algum motivo, o Firefox e o Chrome bloquearam solicitações de entrada 6000, depois que mudei a porta da API do ASP.NET para 4000, o erro mudou para um erro conhecido do CORS que eu poderia corrigir.

O Chrome pelo menos me mostrou o ERR_UNSAFE_PORTque me deu uma pista sobre o que poderia estar errado.

Shahin Dohan
fonte
1

Se você tiver um cabeçalho de cors adequado no lugar. Sua rede corporativa pode estar removendo o cabeçalho cors. Se o site estiver acessível externamente, tente acessá-lo de fora da sua rede para verificar se a rede está causando o problema - uma boa ideia, independentemente da causa.

N-ate
fonte
1

No núcleo do asp.net, se o seu controlador de API não tiver uma anotação chamada [AllowAnonymous], adicione-a acima do nome do seu controlador, como

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

Não é tão antigo quanto as outras perguntas, mas apenas lutei com isso em um aplicativo Ionic-Laravel, e nada funciona a partir daqui (e outras postagens), então instalei https://github.com/barryvdh/laravel-cors o complemento em Laravel e começou e funciona muito bem.

Gersonmontenegro
fonte
0

O meu foi causado por um relacionamento inválido nos modelos que eu estava tentando consultar. Descoberto por depuração da resposta que caiu na relação.

J.Kirk.
fonte
0

Para mim, não era um problema angular. Era um campo do tipo DateTime no banco de dados que tem um valor de (0000-00-00) e meu modelo não pode vincular essa propriedade correta, então mudei para um valor válido como (2019-08-12).

Estou usando o .net core, OData v4 e MySql (conector EF pomelo)

Luis Lopez
fonte
0

Adicione este código ao seu arquivo de conexão

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");
Abdelhakim Ezzahraoui
fonte
0

Se este for um serviço de nó, tente as etapas descritas aqui

Basicamente, é um erro de compartilhamento de recursos de origem cruzada (CORS). Mais informações sobre esses erros aqui .

Depois de atualizar meu serviço de nó com as seguintes linhas, ele funcionou:

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();
  });
FistOfFury
fonte
-2

Meu erro foi que o arquivo era muito grande (o núcleo do dotnet parece ter um limite de ~ 25Mb). Configuração

  • maxAllowedContentLength para 4294967295 (valor máximo de uint) em web.config
  • decorando a ação do controlador com [DisableRequestSizeLimit]
  • services.Configure (options => {options.MultipartBodyLengthLimit = 4294967295;}); em Startup.cs

resolveu o problema para mim.

Spikolynn
fonte