ionic 3 从离子存储设置默认请求标头 [英] ionic 3 Set default requests header from ionic storage

查看:20
本文介绍了ionic 3 从离子存储设置默认请求标头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题有点类似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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆