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であることがわかり、"preview"タブには失敗の原因を説明する実際のメッセージが表示されます。
クロームの開発ツールで見ることができる実際の応答メッセージにアクセスするにはどうすればよいでしょうか?
問題はCORSに関連していました。Chromeのコンソールで別のエラーが出ていることに気づきました。
要求されたリソースに 'Access-Control-Allow-Origin'ヘッダーがありません。Origin 'http://localhost:4200' は、したがって、アクセスが許可されていません。レスポンスはHTTPステータスコード422でした。
これは、バックエンドのnginxがadd_header`ディレクティブを使ってこれらのヘッダーをレスポンスに追加するように設定されているにもかかわらず、バックエンドサーバーからのレスポンスにAccess-Control-Allow-Origin
ヘッダーがないことを意味します。
しかし、このディレクティブは、レスポンスコードが 20X または 30X の場合にのみヘッダーを追加します。エラー応答では、ヘッダがありませんでした。レスポンスコードに関係なくヘッダが追加されるようにするためには、always
パラメータを使う必要がありました。
add_header 'Access-Control-Allow-Origin' 'http://localhost:4200' always;
バックエンドが正しく設定されると、Angularのコードで実際のエラーメッセージにアクセスできるようになりました。
他の誰かが私と同じように迷子になった場合に備えて。.. 私の問題はCORSによるものではありません(サーバーを完全に制御でき、CORSは正しく構成されていました)。!)。
私の問題は、Androidプラットフォームレベル28を使用しているため、デフォルトでクリアテキストネットワーク通信を無効にし、ラップトップのIP(APIサーバーを実行している)を指すアプリを開発しようとしていたためです。 APIベースURLは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を使用する必要はありません)。 必要に応じてさらに制限できます。
<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。
.NET Coreアプリケーションを使用している場合、このソリューションが役立つ可能性があります。!
さらに、これはフロントエンドアプリケーションの角度またはその他のリクエストエラーではない場合があります。
まず、Microsoft CORS Nugetパッケージを追加する必要があります。
Install-Package Microsoft.AspNetCore.Cors
次に、startup.csにCORSサービスを追加する必要があります。 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();
}
オプションlambdaは流 ⁇ なAPIであるため、必要な追加オプションを追加/削除できます。 「AllowAnyOrigin」オプションを使用して任意のドメインを受け入れることができますが、だれかからのクロスオリジンコールを開くため、これを行わないことを強くお勧めします。 クロスオリジンコールをHTTPメソッド(GET / PUT / POSTなど)に制限することもできるため、GETコールクロスドメインなどのみを公開できます。
私の場合は、サーバー側で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, …}
ループをなくしてレスポンスタイプをシンプルにすることで問題が解決しました。
有効なクライアント証明書とサーバーが理解できるトークンを指定しなかった場合、同様のエラーが発生する可能性があります。
エラー:
(不明なURL)のHttp障害応答: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
は、サーバーが理解できる任意の名前にすることができます。
私はASP.NET SPA拡張機能を使用しています。これにより、開発中にAngularのポート4200に渡るポート5000および5001にプロキシが作成されます。
私はCORSをhttpsポート5001に正しく設定していましたが、すべて問題ありませんが、誤ってポート5000の古いブックマークに行きました。 それから突然このメッセージが浮かびました。 他の人がコンソールで言ったように、「飛行前」のエラーメッセージがありました。
したがって、環境に関係なく、CORSを使用している場合は、すべてのポートが指定されていることを確認してください。ホストとポートの両方が重要です。
リクエストが完了するまでに2分以上かかるたびに、その正確なメッセージが表示されていました。 ブラウザはリクエストから切断されますが、バックエンドのリクエストは終了するまで続きました。 サーバー(私の場合はASP.NET Web API)は切断を検出しません。
1日検索した後、ようやくこの回答を見つけました。 プロキシ構成を使用します.
したがって、プロキシ構成を編集して、必要なものに設定できます。
{
"/api": {
"target": "http://localhost:3000",
"secure": false,
"timeout": 6000000
}
}
現在、私はエージェントキープを使用して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(',');
}
}
};
私のエラーは、ファイルが大きすぎることでした(ドットネットコアには@〜25Mbの制限があるようです)。 設定。
-web.configでのmaxAllowedContentLengthから4294967295(uintの最大値)。 -[DisableRequestSizeLimit]でコントローラーアクションを装飾します。 -services.Configure< FormOptions>(options => {options.MultipartBodyLengthLimit = 4294967295;}); Startup.cs。
問題を解決しました。