Angular 4アプリでは、http postでサーバーのログインAPIを呼び出します。サーバは、ログインが成功したか否かにかかわらず、常にスタウト200で応答する。私はサーバーの応答データに基づいてエラーをスローしたい。ログインを呼び出す角度4でhttpステータス200のレスポンスを得るために、.mapに観測可能なエラーを投げる方法
export class AuthenticationService {
...
login(username: string, password: string): Observable<any> {
let body = `method=login&username=${username}&password=${password}`;
return this.http.post('http://localhost/rest.php', body)
.map((response: Response) => {
let responsedata = response.json();
if (responsedata && responsedata.success == 1) {
localStorage.setItem('loggedin',1);
} else {
// Not logged in successfully
Observable.throw(new Error('Not logged in'));
}
});
}
そして、私のコード()
trytologin() {
this.loading = true;
this.authenticationService.login(this.model.username, this.model.password)
.subscribe(
data => {
// Always returns here regarless of result of login
this.router.navigate([this.returnUrl]);
},
error => {
// ONLY returns here on a NON-server 200 status
this.alertService.error(error);
this.loading = false;
});
}
私は応答を傍受しHttpInterceptor
を使用してヘッダを変更することができると思うが、これはやり過ぎのように思えます。 subscribe
エラーを200ステータス応答からトリガーする別の方法はありますか?
EDIT
私は成功せずHttpInterceptor
を実装してみました。
import {HttpClient, HttpHeaders} from '@angular/common/http';
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse,HttpHeaderResponse, HttpErrorResponse} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/map';
@Injectable()
export class LoginInterceptor implements HttpInterceptor {
constructor() {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// Need to .map so we can go through each event looking for the HttpResponse
// Can't use .do() as it doesn't update per the docs
return next.handle(req).map(event => {
if (event instanceof HttpResponse) {
let e2 = new HttpErrorResponse({status: 405, statusText: 'Auth error'});
// return Observable(e2); // Cannot return as HttpErrorResponse is NOT part of HttpEvent<any>
Observable.throw(e2); // <-- Still triggers the success in .subscribe(). Does NOT trigger the .subscribe() error
event = event.clone({status: 405, statusText: 'Auth error'}); // <-- change the event status. Can't return HttpErrorResponse as
}
return event;
});
}
}
.subscribe()
成功は常に呼び出されます。
私は間違っていました。 : - 私のコードが失敗した理由/
EDIT#2
掘削のLOTSした後、私が今知っています。しかし、私はまだ解決策がありません!
HttpInterceptor
は..... 移動するための方法であるが、 Observer.throw()のみHttpClient.post()
が同じドメイン上にある場合にのみ、に動作します! localhostにpost()すると、subscribe()エラーが呼び出されます。私が別のドメインにpost()を呼び出すと、subscribe()エラーが呼び出されません。 Observer.throw()
の直後にconsole.log()
を貼ります。別のドメインがある場合はログ出力があります。ドメインが同じ場合はログ出力があります。サーバーの出力を制御しており、Access-Control-Allow-Origin: *
ヘッダー項目が含まれているため、これがCORSの問題であるかどうかはわかりません。
これはおそらく
HttpClient
および/または
HttpInterceptor
のバグですか?あるいはrxjsの問題でしょうか?
編集#3
私は単純にintercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>
でObservable.throw()
を返す場合は、私のエラーコードがトリガーされますブロックします。ただし、これはhttp要求でのみトリガされます。私は処理してhttp応答でエラーを投げる必要があります。これを行うには、return next.handle(req).map()
を使用して、それぞれHttpResponse
イベントを検索する必要があります。
私がしようとするとmap()
内Observer.throw()
を実行すると、それはが私のエラーコードを誘発しないとどこにもキャッチされていません。 Observer.throw()
以降の行が実行されます。
からは、return Observer.throw()
は正しくありません。返品のタイプは正しくありません。
ただし、map()
のプレーンJavaScriptをthrow()
と呼び出すとエラーコードが表示されます。
普通のthrow()
がベストプラクティスなのか、何か他のことをしなければならないかどうかはわかりません。
サーバーからの応答を傍受し、HttpErrorResponse(HTTPではなくHttpClientを使用していると思います)を使用してHTTP応答をエラーにして、そのオブジェクトを返すことができます。このような何かが新しいHttpErrorResponse({status:401、statusText: "Authのエラー"})を返します。 –