扩展 HTTP - returns 未授权时重定向
Extend HTTP - Redirect when returns unauthorized
当我收到 401 http 状态时,我正在尝试重定向到登录页面。
拳头尝试是:
public getPatients(extraHttpRequestParams?: any): Observable<Array<models.Patient>> {
const path = this.basePath + '/api/patient';
let queryParameters = new URLSearchParams();
let headerParams = this.defaultHeaders;
let requestOptions: RequestOptionsArgs = {
method: 'GET',
headers: headerParams,
search: queryParameters
};
return this.httpInterceptor.request(path, requestOptions)
.map((response: Response) => {
if (response.status === 204) {
return undefined;
} else {
if (response.status === 401) {
this.router.navigate(['/login']);
}
return response.json();
}
});
}
但是当我得到401时,我没有进入地图功能,它在浏览器中给出了未经授权的错误。
所以阅读一些帖子,有一种方法可以扩展 http 服务,似乎是正确的方法,但是当我尝试在 app.module.ts 上实例化 http 依赖项时遇到了一些问题。在我的例子中,我只需要重写拦截器方法,但如果其他人需要其他部分,我会把所有代码都放上去。
这是我的 http 扩展:
import { Http, Request, RequestOptionsArgs, Response, XHRBackend, RequestOptions, ConnectionBackend, Headers} from '@angular/http';
import { Router } from '@angular/router';
import { LocationStrategy, HashLocationStrategy} from '@angular/common';
import { Observable } from 'rxjs/Observable';
import {Injectable} from '@angular/core';
@Injectable()
export class HttpInterceptor extends Http {
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private _router: Router) {
super(backend, defaultOptions);
};
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.request(url, options));
};
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.get(url, options));
};
post(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.post(url, body, this.getRequestOptionArgs(options)));
};
put(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.put(url, body, this.getRequestOptionArgs(options)));
};
delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.delete(url, options));
};
getRequestOptionArgs(options?: RequestOptionsArgs): RequestOptionsArgs {
if (options == null) {
options = new RequestOptions();
}
if (options.headers == null) {
options.headers = new Headers();
}
options.headers.append('Content-Type', 'application/json');
return options;
};
intercept(observable: Observable<Response>): Observable<Response> {
return observable.catch((err, source) => {
if (err.status == 401) {
this._router.navigate(['/login']);
return Observable.empty();
} else {
return Observable.throw(err);
}
});
}
};
在我的 app.module.ts 中,我必须添加:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { routing, appRoutingProviders } from './app.routing';
import { FormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { PatientsComponent } from './pacientes/pacientes.component';
import { HttpInterceptor } from '../api/api/HttpInterceptor';
import { RequestOptions, ConnectionBackend} from '@angular/http';
import { HttpModule, JsonpModule } from '@angular/http';
const routes: Routes = [
];
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
JsonpModule,
routing,
RouterModule.forRoot(routes, { useHash: true }), // .../#/crisis-center/
],
declarations: [
AppComponent,
PatientsComponent,
],
providers: [
appRoutingProviders,
HttpInterceptor,
RequestOptions
],
bootstrap: [AppComponent]
})
export class AppModule { }
现在一切都很好,但是当我尝试使用我创建的新 httpInterceptor 服务,将其导入并将其添加到构造函数并为我的新 http 拦截器实例替换 http 实例时,我得到了 ConnectionBackend 的 No provider,我尝试将 ConnectionBackend 添加到提供程序,但它显示 'types of property providers are incompatible'。然后我尝试添加 httpInterceptor 但我收到未捕获错误:无法解析 RequestOptions 的所有参数:(?).
所以总而言之,必须有一种方法可以正确扩展 http 方法或以其他方式处理 401..
我该怎么做,是否有一些教程,link 或可以看一看的东西?
没有使用令牌 ConnectionBackend
注册的提供商。你可以做的是在配置拦截器时使用工厂
providers: [
{
provide: HttpInterceptor,
useFactory: (backend: XHRBackend, options: RequestOptions, router: Router) => {
return new HttpInterceptor(backend, options, router);
},
deps: [XHRBackend, RequestOptions, Router ]
}
]
我已经用您的代码对此进行了测试,它应该可以工作。
当我收到 401 http 状态时,我正在尝试重定向到登录页面。 拳头尝试是:
public getPatients(extraHttpRequestParams?: any): Observable<Array<models.Patient>> {
const path = this.basePath + '/api/patient';
let queryParameters = new URLSearchParams();
let headerParams = this.defaultHeaders;
let requestOptions: RequestOptionsArgs = {
method: 'GET',
headers: headerParams,
search: queryParameters
};
return this.httpInterceptor.request(path, requestOptions)
.map((response: Response) => {
if (response.status === 204) {
return undefined;
} else {
if (response.status === 401) {
this.router.navigate(['/login']);
}
return response.json();
}
});
}
但是当我得到401时,我没有进入地图功能,它在浏览器中给出了未经授权的错误。
所以阅读一些帖子,有一种方法可以扩展 http 服务,似乎是正确的方法,但是当我尝试在 app.module.ts 上实例化 http 依赖项时遇到了一些问题。在我的例子中,我只需要重写拦截器方法,但如果其他人需要其他部分,我会把所有代码都放上去。
这是我的 http 扩展:
import { Http, Request, RequestOptionsArgs, Response, XHRBackend, RequestOptions, ConnectionBackend, Headers} from '@angular/http';
import { Router } from '@angular/router';
import { LocationStrategy, HashLocationStrategy} from '@angular/common';
import { Observable } from 'rxjs/Observable';
import {Injectable} from '@angular/core';
@Injectable()
export class HttpInterceptor extends Http {
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private _router: Router) {
super(backend, defaultOptions);
};
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.request(url, options));
};
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.get(url, options));
};
post(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.post(url, body, this.getRequestOptionArgs(options)));
};
put(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.put(url, body, this.getRequestOptionArgs(options)));
};
delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.delete(url, options));
};
getRequestOptionArgs(options?: RequestOptionsArgs): RequestOptionsArgs {
if (options == null) {
options = new RequestOptions();
}
if (options.headers == null) {
options.headers = new Headers();
}
options.headers.append('Content-Type', 'application/json');
return options;
};
intercept(observable: Observable<Response>): Observable<Response> {
return observable.catch((err, source) => {
if (err.status == 401) {
this._router.navigate(['/login']);
return Observable.empty();
} else {
return Observable.throw(err);
}
});
}
};
在我的 app.module.ts 中,我必须添加:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { routing, appRoutingProviders } from './app.routing';
import { FormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { PatientsComponent } from './pacientes/pacientes.component';
import { HttpInterceptor } from '../api/api/HttpInterceptor';
import { RequestOptions, ConnectionBackend} from '@angular/http';
import { HttpModule, JsonpModule } from '@angular/http';
const routes: Routes = [
];
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
JsonpModule,
routing,
RouterModule.forRoot(routes, { useHash: true }), // .../#/crisis-center/
],
declarations: [
AppComponent,
PatientsComponent,
],
providers: [
appRoutingProviders,
HttpInterceptor,
RequestOptions
],
bootstrap: [AppComponent]
})
export class AppModule { }
现在一切都很好,但是当我尝试使用我创建的新 httpInterceptor 服务,将其导入并将其添加到构造函数并为我的新 http 拦截器实例替换 http 实例时,我得到了 ConnectionBackend 的 No provider,我尝试将 ConnectionBackend 添加到提供程序,但它显示 'types of property providers are incompatible'。然后我尝试添加 httpInterceptor 但我收到未捕获错误:无法解析 RequestOptions 的所有参数:(?).
所以总而言之,必须有一种方法可以正确扩展 http 方法或以其他方式处理 401.. 我该怎么做,是否有一些教程,link 或可以看一看的东西?
没有使用令牌 ConnectionBackend
注册的提供商。你可以做的是在配置拦截器时使用工厂
providers: [
{
provide: HttpInterceptor,
useFactory: (backend: XHRBackend, options: RequestOptions, router: Router) => {
return new HttpInterceptor(backend, options, router);
},
deps: [XHRBackend, RequestOptions, Router ]
}
]
我已经用您的代码对此进行了测试,它应该可以工作。