ionic 3 从离子存储设置默认请求标头 [英] ionic 3 Set default requests header from ionic storage
问题描述
这个问题有点类似Ionic 2 - 从 Storage 值中获取令牌并在 HTTP 请求之前设置标头(不是重复的)
This question is a bit similar Ionic 2 - Get token from Storage value and set Header before HTTP Request ( not a duplicate)
但问题与从本地存储返回值有关.
But the issue is connected with returning a value from local storage.
我需要为所有请求设置默认标头(授权令牌).一定是一个典型的问题,但找不到解决方案.以及大多数可用信息 - 关于为每个请求设置它.这很简单,但不是很合理.- 如果可能的话,为什么要为每个请求设置.
I need to set the default header(Authorization token) for all requests. Must be a typical problem, but can't find a solution. And most of the available info - about setting it for each request. Which is simple, but not very reasonable. - why set for each request if possible to set for all.
我试过:
案例 #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;
})
}
}
在这种情况下,它不是编译,而是显示我想要做什么.
in this case it's just not compiling, but it's to show what do i want to do.
案例#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'));
}
}
(类似于前面提到的 SO 主题),但是 .flatMap()
抛出错误:
(it is similar to mentioned SO topic), but .flatMap()
throwing a error:
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'.
案例 #3:
let api_token = await this.storage.get('jwt_token');
-> await
在这里根本行不通.
let api_token = await this.storage.get('jwt_token');
-> await
simply isn't work here.
有什么想法吗?
推荐答案
我实际上已经在我的 Ionic 应用程序中实现了这个,请看下面:
I've actually implemented this inside my Ionic Application, please see below:
我创建了一个自定义的 Http 拦截器,
I created a custom 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;
});
}
}
在我的 app.module.ts 中
Inside my 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 {
}
然后在我的提供者内部,我像普通的 http 请求一样使用它
Then inside my provider I used it like a regular http request
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());
}
}
希望这会有所帮助
这篇关于ionic 3 从离子存储设置默认请求标头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!