use*_*987 6 typescript ionic-framework angular
这个问题有点类似Ionic 2 - 从存储值中获取令牌并在HTTP请求之前设置Header(不是重复)
但问题与从本地存储返回值有关.
我需要为所有请求设置默认标头(授权标记).必须是典型问题,但无法找到解决方案.以及大多数可用信息 - 关于为每个请求设置它.这很简单,但不太合理. - 如果可能的话,为什么设置为所有请求的原因.
我试过了:
情况1:
import {Injectable} from "@angular/core";
import {BaseRequestOptions, RequestOptions, RequestOptionsArgs} from "@angular/http";
import { Storage } from '@ionic/storage';
@Injectable()
export class MyRequestOptions extends BaseRequestOptions {
constructor(private storage: Storage) {
super();
this.headers.set('Content-Type', 'application/json');
}
merge(options?: RequestOptionsArgs): RequestOptions {
const newOptions = super.merge(options);
console.log("setting auth header");
function setAuthHeader(storage) {
return storage.get('jwt_token').then(value => {
newOptions.headers.set('Authorization',`Bearer ${value}`);
return newOptions;
});
}
return setAuthHeader(this.storage).then(()=>{
return newOptions;
})
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,它只是没有编译,但它是为了表明我想做什么.
案例#2:
@Injectable()
export class MyRequestOptions extends BaseRequestOptions {
constructor(private storage: Storage) {
super();
this.headers.set('Content-Type', 'application/json');
}
merge(options?: RequestOptionsArgs): RequestOptions {
const newOptions = super.merge(options);
console.log("setting auth header");
return this.getApiToken().flatMap( data => {
newOptions.headers.set('Authorization',`Bearer ${data}`);
return newOptions;
});
}
getApiToken(): Observable<RequestOptions> {
return Observable.fromPromise(this.storage.get('jwt_token'));
}
}
Run Code Online (Sandbox Code Playgroud)
(它类似于提到的SO主题),但.flatMap()抛出一个错误:
argument of type '(data: Headers) => RequestOptions' is not assignable to parameter of type '(value: Headers, index: number) => ObservableInput<{}>'. Type 'RequestOptions' is not assignable to type 'ObservableInput<{}>'. Type 'RequestOptions' is not assignable to type 'ArrayLike<{}>'. Property 'length' is missing in type 'RequestOptions'.
Run Code Online (Sandbox Code Playgroud)
案例#3:
let api_token = await this.storage.get('jwt_token');- > await根本就不在这里工作.
任何的想法?
Wes*_*zee 12
我实际上在我的Ionic应用程序中实现了这个,请看下面:
我创建了一个自定义的Http Interceptor,
http.interceptor.ts
import { Events } from 'ionic-angular';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import 'rxjs';
import { Storage } from '@ionic/storage';
import {Http, RequestOptionsArgs, Response, RequestOptions, ConnectionBackend, Headers} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import {Storage} from '@ionic/storage';
import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/map';
export class HttpInterceptor extends Http {
constructor(connectionBackend: ConnectionBackend, requestOptions: RequestOptions, public storage: Storage) {
super(connectionBackend, requestOptions);
}
public get(url: string, options?: RequestOptionsArgs): Observable<Response> {
return Observable.fromPromise(
this.getRequestOptionArgs(options)
).mergeMap((options) => {
return super.get(url, options)
});
}
public post(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
return Observable.fromPromise(
this.getRequestOptionArgs(options)
).mergeMap((options) => {
return super.post(url, body, options)
})
}
public put(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
return Observable.fromPromise(
this.getRequestOptionArgs(options)
).mergeMap((options) => {
return super.put(url, body, options)
})
}
public delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
return Observable.fromPromise(
this.getRequestOptionArgs(options)
).mergeMap((options) => {
return super.delete(url, options)
});
}
private getRequestOptionArgs(options?: RequestOptionsArgs) {
return this.storage.get('token').then((token) => {
if (options == null) {
options = new RequestOptions();
}
if (options.headers == null) {
options.headers = new Headers();
}
if (token !== null) {
options.headers.append('Authorization', 'Bearer ' + token);
}
options.headers.append('Content-Type', 'application/json');
return options;
});
}
}
Run Code Online (Sandbox Code Playgroud)
在我的app.module.ts里面
app.module.ts
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {IonicApp, IonicModule} from 'ionic-angular';
import {Storage, IonicStorageModule} from '@ionic/storage';
import {HttpModule, XHRBackend, RequestOptions, Http} from '@angular/http';
import {HttpInterceptor} from '../auth/http.interceptor';
import {SplashScreen} from "@ionic-native/splash-screen";
import {StatusBar} from '@ionic-native/status-bar';
import {Keyboard} from '@ionic-native/keyboard';
import {InAppBrowser} from '@ionic-native/in-app-browser';
export function httpInterceptorFactory(xhrBackend: XHRBackend, requestOptions: RequestOptions, storage: Storage) {
return new HttpInterceptor(xhrBackend, requestOptions, storage);
}
@NgModule({
declarations: [
...
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp, {mode: 'md'}),
IonicStorageModule.forRoot(),
HttpModule
],
bootstrap: [IonicApp],
entryComponents: [
...
],
providers: [StatusBar, SplashScreen, Keyboard, InAppBrowser, //these are just things I needed in my app
{
provide: Http,
useFactory: httpInterceptorFactory,
deps: [XHRBackend, RequestOptions, Storage]
}
]
})
export class AppModule {
}
Run Code Online (Sandbox Code Playgroud)
然后在我的提供程序中,我像常规的http请求一样使用它
app.provider.ts
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
import { CONFIG } from '../config/app.config';
@Injectable()
export class AppProvider {
private baseUrl:string = CONFIG.apiEndpoint;
constructor(private http: Http) {
}
public getSomething():Observable<any> {
let url:string = this.baseUrl + 'some endpoint';
return this.http.get(url).map((res:Response) => res.json());
}
}
Run Code Online (Sandbox Code Playgroud)
希望这会有所帮助
似乎实现这一目标的最佳方法是实施拦截器.但是,当前(在写这个答案的时候)Ionic版本正在使用Angular 4.1.3,它使用HttpModule,它本身还没有实现拦截器.Angular 4.3.1的下一个版本(https://angular.io/guide/http)使用HttpClientModule,它有Interecptors ..拦截器的方法是捕获请求,从存储中读取,应该返回承诺(https://ionicframework.com/docs/storage/ - 查看底部的"实例成员").然后在解析时,调用next.handle(req),它将转到下一个/最后一个事件,即API请求.
我现在正在实现的解决方案(这可能是浪费时间,如果下一周对Angular 4.3.1进行Ionic更新......提示提示),就是通过扩展Http(https来编写"自定义"拦截器)://medium.com/aviabird/http-interceptor-angular2-way-e57dc2842462).
祝好运!