कोणीय - हर अनुरोध के लिए हेडर सेट करें


334

उपयोगकर्ता को हर बाद के अनुरोध के लिए लॉग इन करने के बाद मुझे कुछ प्राधिकरण हेडर सेट करने की आवश्यकता है।


किसी विशेष अनुरोध के लिए हेडर सेट करने के लिए,

import {Headers} from 'angular2/http';
var headers = new Headers();
headers.append(headerName, value);

// HTTP POST using these headers
this.http.post(url, data, {
  headers: headers
})
// do something with the response

संदर्भ

लेकिन यह इस तरह से हर अनुरोध के लिए मैन्युअल रूप से अनुरोध हेडर सेट करने के लिए संभव नहीं होगा।

उपयोगकर्ता द्वारा लॉग इन करने के बाद मैं हेडर सेट कैसे सेट करूं और लॉगआउट पर उन हेडर को भी हटा दूं?



जवाबों:


379

जवाब देने के लिए, आप सवाल करते हैं कि आप एक सेवा प्रदान कर सकते हैं जो मूल Httpवस्तु को कोणीय से लपेटता है । कुछ इस तरह से नीचे वर्णित है।

import {Injectable} from '@angular/core';
import {Http, Headers} from '@angular/http';

@Injectable()
export class HttpClient {

  constructor(private http: Http) {}

  createAuthorizationHeader(headers: Headers) {
    headers.append('Authorization', 'Basic ' +
      btoa('username:password')); 
  }

  get(url) {
    let headers = new Headers();
    this.createAuthorizationHeader(headers);
    return this.http.get(url, {
      headers: headers
    });
  }

  post(url, data) {
    let headers = new Headers();
    this.createAuthorizationHeader(headers);
    return this.http.post(url, data, {
      headers: headers
    });
  }
}

और Httpऑब्जेक्ट को इंजेक्ट करने के बजाय आप इसे एक ( HttpClient) इंजेक्ट कर सकते हैं ।

import { HttpClient } from './http-client';

export class MyComponent {
  // Notice we inject "our" HttpClient here, naming it Http so it's easier
  constructor(http: HttpClient) {
    this.http = httpClient;
  }

  handleSomething() {
    this.http.post(url, data).subscribe(result => {
        // console.log( result );
    });
  }
}

मुझे यह भी लगता है कि किसी Httpवर्ग के लिए बहु प्रदाताओं का उपयोग करके कुछ किया जा सकता है, जो आपकी अपनी कक्षा को प्रदान Httpकरता है ... इस लिंक को देखें: http://blog.thoughtram.io/angular2/2015/11/23/multi-providers -इन-कोणीय 2.html


1
'this.http = http?' से आता है, मुझे विश्वास है कि हमें उपयोग करने से पहले इसे घोषित करने की आवश्यकता है?
co2f2e

1
कोणीय हेडर (सेट और अपेंडेड फ़ंक्शंस) हेडर की कुंजी को "सामान्य" कर रहा है और इसे लोअर-केस बनाता है। Headers.d.ts से: // "HTTP कैरेक्टर सेट को केस-असंवेदनशील टोकन द्वारा पहचाना जाता है" // tools.ietf.org/html/rfc2616 पर कल्पना करें उन लोगों के लिए जिनके पास बैकएंड नहीं है जो ऐनक द्वारा काम करता है; यहाँ बाईपास करें: हेडरस्पोर्ट = .get (विकल्प, 'हेडर._हेडर्सपैप', नया मैप ()) दें; हेडरस्पोर्ट.सेट ('प्राधिकरण', [ .replace ( Bearer ${token}, / \ "/ g, '')]);
sangress

@DiegoUnanue मैं कोणीय 2 और थियरी के कार्यान्वयन कार्यों के अंतिम संस्करण का उपयोग कर रहा हूं। आयात विवरणों में 'angular2' को '@angular' में बदलें।
3

मार्क Pieszak- क्या मुझे HttpClient के लिए प्रदाताओं को शामिल करना चाहिए?
user3127109

अब TS त्रुटि फेंकता है: 'प्रकार का तर्क' {हेडर: हेडर; } 'RequestOptionsArgs'` प्रकार के पैरामीटर के लिए असाइन नहीं किया जा सकता है
elporfirio

142

HTTP इंटरसेप्टर अब नए HttpClientसे @angular/common/http, कोणीय 4.3.x संस्करणों और उससे आगे के माध्यम से उपलब्ध हैं

अब हर अनुरोध के लिए हेडर जोड़ना बहुत सरल है:

import {
  HttpEvent,
  HttpInterceptor,
  HttpHandler,
  HttpRequest,
} from '@angular/common/http';
import { Observable } from 'rxjs';

export class AddHeaderInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Clone the request to add the new header
    const clonedRequest = req.clone({ headers: req.headers.set('Authorization', 'Bearer 123') });

    // Pass the cloned request instead of the original request to the next handle
    return next.handle(clonedRequest);
  }
}

अपरिवर्तनीयता का एक सिद्धांत है , यही कारण है कि इस पर कुछ नया स्थापित करने से पहले अनुरोध को क्लोन करने की आवश्यकता है।

हेडर को संपादित करना एक बहुत ही सामान्य कार्य है, वास्तव में इसके लिए एक शॉर्टकट है (अनुरोध को क्लोन करते समय):

const clonedRequest = req.clone({ setHeaders: { Authorization: 'Bearer 123' } });

इंटरसेप्टर बनाने के बाद, आपको इसे HTTP_INTERCEPTORSप्रदान का उपयोग करके पंजीकृत करना चाहिए ।

import { HTTP_INTERCEPTORS } from '@angular/common/http';

@NgModule({
  providers: [{
    provide: HTTP_INTERCEPTORS,
    useClass: AddHeaderInterceptor,
    multi: true,
  }],
})
export class AppModule {}

मैंने इसे लागू किया और जब मैं एनजी सर्व कर रहा था, तो मैं अनुरोध हेडर देख सकता हूं, हालांकि जब बी बी प्रोडक्ट कर रहा है और एक टॉमकैट के अंदर तैनाती कर रहा है, तो मुझे हेडर दिखाई नहीं दे रहा है ... स्प्रिंग-बूट का उपयोग करके हेडर कहां गए?
नोरू

1
नहीं जानता कि क्या यह है क्योंकि मैं एक एक्सप्रेस नोड एपीआई के साथ काम कर रहा हूँ, लेकिन यह मेरे लिए भी आधिकारिक कोणीय डॉक्टर के साथ काम नहीं करता है। : /
मैक्सिमे लाफारी

त्रुटि टाइपर: CreateListFromArrayLike गैर-ऑब्जेक्ट पर कॉल किया जाता है
DAG

1
आप HttpInterceptor में कुछ भी कैसे इंजेक्ट करेंगे?
zaitsman

मैंने इसे लागू किया है लेकिन PUT और DELETE API अनुरोध शीर्षलेख मेरे लिए काम नहीं करता है।
पूजा

78

BaseRequestOptionsइस परिदृश्य में विस्तार से बहुत मदद मिल सकती है। निम्नलिखित कोड देखें:

import {provide} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
import {HTTP_PROVIDERS, Headers, Http, BaseRequestOptions} from 'angular2/http';

import {AppCmp} from './components/app/app';


class MyRequestOptions extends BaseRequestOptions {
  constructor () {
    super();
    this.headers.append('My-Custom-Header','MyCustomHeaderValue');
  }
} 

bootstrap(AppCmp, [
  ROUTER_PROVIDERS,
  HTTP_PROVIDERS,
  provide(RequestOptions, { useClass: MyRequestOptions })
]);

इसमें हर कॉल में 'माय-कस्टम-हेडर' शामिल होना चाहिए।

अपडेट करें:

ऊपर दिए गए कोड के बजाय आप कभी भी हेडर को बदलने में सक्षम होने के लिए एक नए हेडर को जोड़ने के लिए निम्न कोड का उपयोग कर सकते हैं:

this.http._defaultOptions.headers.append('Authorization', 'token');

हटाने के लिए आप कर सकते हैं

this.http._defaultOptions.headers.delete('Authorization');

इसके अलावा एक और फ़ंक्शन है जिसका उपयोग आप मूल्य निर्धारित करने के लिए कर सकते हैं:

this.http._defaultOptions.headers.set('Authorization', 'token');

उपरोक्त समाधान अभी भी टाइपस्क्रिप्ट संदर्भ में पूरी तरह से मान्य नहीं है। _defaultHeaders सुरक्षित है और इसे इस तरह इस्तेमाल नहीं किया जाना चाहिए। मैं जल्दी ठीक करने के लिए उपरोक्त समाधान की सिफारिश करूंगा, लेकिन लंबे समय तक अपने बेहतर आवरण को http कॉल के आसपास लिखने के लिए बेहतर है जो कि ऑर्ट को भी संभालता है। उदाहरण 0 से निम्नलिखित को लें जो बेहतर और साफ है।

https://github.com/auth0/angular2-jwt/blob/master/angular2-jwt.ts

अद्यतन - जून २०१ I मैं इस समाधान के लिए बहुत से लोगों को देखता हूं लेकिन मैं सलाह दूंगा। विश्व स्तर पर शीर्ष लेख में जोड़ देने प्रमाणन टोकन भेजने होगा हर API कॉल करके आपके एप्लिकेशन की बाहर जा रहा है। तो इंटरकॉम या zendesk या किसी अन्य एपीआई की तरह तीसरे पक्ष के प्लगइन्स पर जा रहे एप कॉल आपके प्राधिकरण हेडर को भी ले जाएंगे। यह एक बड़ा सुरक्षा दोष हो सकता है। इसलिए इसके बजाय, वैश्विक स्तर पर इंटरसेप्टर का उपयोग करें लेकिन मैन्युअल रूप से जांचें कि आउटगोइंग कॉल आपके सर्वर के एपी एंडपॉइंट की ओर है या नहीं और फिर हेडर को संलग्न करें।


1
this.http._defaultOptions.headers.delete ('My-Custom-Header') तो उपरोक्त प्रक्रिया को इस कोड को फॉलो करके छोटा किया जा सकता है ।http._defaultOptions.headers.append ('My-New-Custom-Header', 'newvalue) ')
अनित २''१६ को ३:२

2
@ डिनिस्ट्रो हाँ, अब मैं खुद को ऐसा करने की सलाह नहीं दूंगा। मुझे कोणीय बीटा सीमाओं और वैश्विक स्तर पर स्थिति प्रवाह को नियंत्रित करने की मेरी आदत के कारण मुझे इस समाधान के साथ आना पड़ा। लेकिन मेरा मानना ​​है कि अब के लिए github.com/auth0/angular2-jwt/blob/master/angular2-jwt.ts का बेहतर और साफ समाधान है।
अनीत

1
BaseRequestOptions का उपयोग करने की समस्या यह है कि यह इसका निर्माण है, यह केवल एक बार ब्राउज़र में जीवनकाल में केवल एक बार चलाया जाता है। इसलिए यदि आप समय के दौरान हेडर मान बदलना चाहते हैं (उदाहरण के लिए csrf_token) तो आप इसे इस तरह से नहीं कर सकते हैं (यहां तक ​​कि इस वर्ग में मर्ज विधि को ओवरराइड करने से भी मदद नहीं मिलती है :()
कामिल कील्वेज़ेस्की

1
समस्या यह है कि यदि आप एक रैपर 3 पार्टी लाइब्रेरियों का उपयोग करते हैं जो सीधे HTTP तक पहुँचते हैं तो इसका उपयोग करने के लिए फिर से लिखना होगा। मैं अभी भी नहीं जानता कि कैसे चारों ओर पाने के लिए। एक इंटरसेप्टर की वास्तव में जरूरत होती है। यकीन नहीं होता कि किसी को बेहतर तरीका पता है।
पियोट्र स्टुलिंस्की

6
नमस्ते, कोणीय 4 _defaultOptionsमें संरक्षित किया गया है इसलिए सेवा से नहीं बुलाया जा सकता है
एंडुरिट

24

हालांकि मैं इसका उत्तर बहुत देर से दे रहा हूं लेकिन यह किसी और की मदद कर सकता है। @NgModuleउपयोग किए जाने पर सभी अनुरोधों को हेडर इंजेक्ट करने के लिए , एक निम्नलिखित कर सकता है:

(मैंने इसका परीक्षण कोणीय 2.0.1 में किया है)

/**
 * Extending BaseRequestOptions to inject common headers to all requests.
 */
class CustomRequestOptions extends BaseRequestOptions {
    constructor() {
        super();
        this.headers.append('Authorization', 'my-token');
        this.headers.append('foo', 'bar');
    }
}

अब @NgModuleनिम्नलिखित कार्य करें:

@NgModule({
    declarations: [FooComponent],
    imports     : [

        // Angular modules
        BrowserModule,
        HttpModule,         // This is required

        /* other modules */
    ],
    providers   : [
        {provide: LocationStrategy, useClass: HashLocationStrategy},
        // This is the main part. We are telling Angular to provide an instance of
        // CustomRequestOptions whenever someone injects RequestOptions
        {provide: RequestOptions, useClass: CustomRequestOptions}
    ],
    bootstrap   : [AppComponent]
})

4
आपको @ इनजेक्टेबल और क्लास में हेडर्स को परिभाषित करने की आवश्यकता है, मैंने @Injectable () एक्सपोर्ट क्लास CustomRequestOptions द्वारा सफल परीक्षण किया, BaseRequestOptions {हेडर: हेडर = नए हेडर ({'प्राधिकरण': 'xxx'}); }
ईजीबोनलैक

ठीक है, मैंने इसे 2.0.0 में किया, 2.0.1 की जांच नहीं की
ईजोनब्लैक

महत्वपूर्ण नोट यहां मैं एक ऐसे मुद्दे पर भाग गया, जिसमें CustomRequestOptions@ Injectable / @ Injectable का उपयोग करते हुए भी कुछ भी इंजेक्ट करना असंभव था । मुझे एहसास हुआ कि समाधान का विस्तार करना है RequestOptions, नहीं BaseRequestOptions। प्रदान करने BaseRequestOptionsसे काम नहीं चलेगा, बल्कि RequestOptionsइसके बजाय का विस्तार करने से डीआई फिर से काम करेगा।
संसद

5
यह समाधान सरल है, लेकिन यदि उपयोगकर्ता लॉग आउट करेगा और वापस अपने टोकन में बदलाव करेगा - यह अब काम नहीं करेगा, क्योंकि Authorizationहेडर केवल एक बार इनिट पर सेट किया गया है।
एलेक्स परमोनोव

हां, सही है @AlexeyVParamonov। यह तभी उपयोगी है जब टोकन एक बार सेट किया जा रहा हो। अन्यथा हम मामले के लिए इंटरसेप्टर लिखेंगे जैसे आपने कहा था।
शशांक अग्रवाल

15

में Angular 2.1.2मैं विस्तार से इस संपर्क किया कोणीय Http:

import {Injectable} from "@angular/core";
import {Http, Headers, RequestOptionsArgs, Request, Response, ConnectionBackend, RequestOptions} from "@angular/http";
import {Observable} from 'rxjs/Observable';

@Injectable()
export class HttpClient extends Http {

  constructor(protected _backend: ConnectionBackend, protected _defaultOptions: RequestOptions) {

    super(_backend, _defaultOptions);
  }

  _setCustomHeaders(options?: RequestOptionsArgs):RequestOptionsArgs{
    if(!options) {
      options = new RequestOptions({});
    }
    if(localStorage.getItem("id_token")) {

      if (!options.headers) {

        options.headers = new Headers();


      }
      options.headers.set("Authorization", localStorage.getItem("id_token"))
    }
    return options;
  }


  request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {
    options = this._setCustomHeaders(options);
    return super.request(url, options)
  }
}

तब मेरे ऐप प्रदाताओं में मैं 'Http' प्रदान करने के लिए एक कस्टम फैक्टरी का उपयोग करने में सक्षम था

import { RequestOptions, Http, XHRBackend} from '@angular/http';
import {HttpClient} from './httpClient';
import { RequestOptions, Http, XHRBackend} from '@angular/http';
import {HttpClient} from './httpClient';//above snippet

function httpClientFactory(xhrBackend: XHRBackend, requestOptions: RequestOptions): Http {
  return new HttpClient(xhrBackend, requestOptions);
}

@NgModule({
  imports:[
    FormsModule,
    BrowserModule,
  ],
  declarations: APP_DECLARATIONS,
  bootstrap:[AppComponent],
  providers:[
     { provide: Http, useFactory: httpClientFactory, deps: [XHRBackend, RequestOptions]}
  ],
})
export class AppModule {
  constructor(){

  }
}

अब मुझे हर Http विधि की घोषणा करने की आवश्यकता नहीं है और httpअपने पूरे आवेदन में सामान्य रूप से उपयोग कर सकते हैं ।


इस उत्तर ने मेरे लिए सबसे अच्छा काम किया क्योंकि मैं अपने एपीआई सर्वर पर यूआरएल को फ़िल्टर करने में सक्षम था और केवल इसमें किए गए कॉलों के लिए प्रामाणिक टोकन जोड़ें। मैंने अनुरोध को इसमें बदल दिया: अनुरोध (url: string। अनुरोध, विकल्प ;: RequestOptionsArgs): अवलोकन योग्य <प्रतिक्रिया> {var _url: string = url.toString (); if (_url.indexOf ('api.myserver.com')> -1) {विकल्प = this._setCustomHeaders (विकल्प); } वापसी super.request (url, options)}
क्रिस

मेरे मामले में अनुरोध विधि में url पैरामीटर से हेडर और हेडर लिए गए थे। मैंने इस तरह कोड बदल दिया: अनुरोध (url: string; अनुरोध, विकल्प ;: RequestOptionsArgs): अवलोकन योग्य <प्रतिक्रिया> {विकल्प = this._setCustomHeaders (विकल्प); if (टाइपोफ़ (url) === "ऑब्जेक्ट") {(<Request> url) .withCredentials = options.withCredentials; (<अनुरोध> url)। हेडर = विकल्प.हेडर्स; } वापसी super.request (url, विकल्प)}
Argnist

request()विधि है, जो आप अधिक भार कर रहे हैं, दो कॉल हस्ताक्षर है और optionsसंपत्ति केवल जब प्रयोग किया जाता है urlस्ट्रिंग के रूप में निर्दिष्ट। ऐसे मामले में जहां urlएक उदाहरण है Request, optionsसंपत्ति को केवल नजरअंदाज कर दिया जाता है। इससे त्रुटियों को पकड़ने में कठिनाई हो सकती है। कृपया अधिक जानकारी के लिए मेरा जवाब देखें।
स्लाव फोमिन II


यह मेरे लिए कोणीय 4.2 तक काम किया। 4.3 में इंटरसेप्टर हैं।
cabaji99

12

कोणीय 2 Httpप्रदाता का विस्तार करके एक कस्टम Http कक्षा बनाएं और बस कस्टम Http वर्ग में constructorऔर requestविधि को ओवरराइड करें । नीचे दिया गया उदाहरण Authorizationप्रत्येक http अनुरोध में हेडर जोड़ता है ।

import {Injectable} from '@angular/core';
import {Http, XHRBackend, RequestOptions, Request, RequestOptionsArgs, Response, Headers} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class HttpService extends Http {

  constructor (backend: XHRBackend, options: RequestOptions) {
    let token = localStorage.getItem('auth_token'); // your custom token getter function here
    options.headers.set('Authorization', `Bearer ${token}`);
    super(backend, options);
  }

  request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {
    let token = localStorage.getItem('auth_token');
    if (typeof url === 'string') { // meaning we have to add the token to the options, not in url
      if (!options) {
        // let's make option object
        options = {headers: new Headers()};
      }
      options.headers.set('Authorization', `Bearer ${token}`);
    } else {
    // we have to add the token to the url object
      url.headers.set('Authorization', `Bearer ${token}`);
    }
    return super.request(url, options).catch(this.catchAuthError(this));
  }

  private catchAuthError (self: HttpService) {
    // we have to pass HttpService's own instance here as `self`
    return (res: Response) => {
      console.log(res);
      if (res.status === 401 || res.status === 403) {
        // if not authenticated
        console.log(res);
      }
      return Observable.throw(res);
    };
  }
}

फिर प्रदाता और अपने कस्टम Http वर्ग app.module.tsके XHRBackendरूप में प्रदान करने के लिए अपने मुख्य को कॉन्फ़िगर करें :ConnectionBackendRequestOptions

import { HttpModule, RequestOptions, XHRBackend } from '@angular/http';
import { HttpService } from './services/http.service';
...
@NgModule({
  imports: [..],
  providers: [
    {
      provide: HttpService,
      useFactory: (backend: XHRBackend, options: RequestOptions) => {
        return new HttpService(backend, options);
      },
      deps: [XHRBackend, RequestOptions]
    }
  ],
  bootstrap: [ AppComponent ]
})

उसके बाद, आप अब अपनी सेवाओं में अपने कस्टम http प्रदाता का उपयोग कर सकते हैं। उदाहरण के लिए:

import { Injectable }     from '@angular/core';
import {HttpService} from './http.service';

@Injectable()
class UserService {
  constructor (private http: HttpService) {}

  // token will added automatically to get request header
  getUser (id: number) {
    return this.http.get(`/users/${id}`).map((res) => {
      return res.json();
    } );
  }
}

यहाँ एक व्यापक गाइड है - http://adonespitogo.com/articles/angular-2-extending-http-provider/


वैकल्पिक कक्षा प्रदाता का उपयोग करने के लिए यह दृष्टिकोण अच्छी तरह से अनुकूल है। अपने मॉड्यूल में "प्रदान करें: HttpService" के बजाय, आप इसके बजाय "प्रदान करें: Http" का उपयोग कर सकते हैं जो आपको आमतौर पर Http के साथ काम करने की अनुमति देता है।
गिल्बर्ट एरेनास डैगर

मैं इस विस्तारित http वर्ग में अतिरिक्त गुण कैसे जोड़ सकता हूं? उदाहरण के लिए, राउटर: राउटर या कोई कस्टम इंजेक्शन सेवाएं।
शफीकुमेत

@shafeequemat आप इसका उपयोग नहीं कर सकते। आप अपने कस्टम http वर्ग में एक और विधि को परिभाषित कर सकते हैं, उदाहरण के लिए setRouter(router)। या आप एक और वर्ग बना सकते हैं और अपने कस्टम http वर्ग को विपरीत के बजाय वहां इंजेक्ट कर सकते हैं।
पोडोगो

9

5 और इसके बाद के संस्करण के लिए, हम अनुरोध और प्रतिक्रिया संचालन को सामान्य बनाने के लिए HttpInterceptor का उपयोग कर सकते हैं। इससे हमें नकल करने से बचने में मदद मिलती है:

1) आम हेडर

2) प्रतिक्रिया प्रकार निर्दिष्ट करना

3) क्वेरी का अनुरोध

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor,
  HttpResponse,
  HttpErrorResponse
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/do';

@Injectable()
export class AuthHttpInterceptor implements HttpInterceptor {

  requestCounter: number = 0;
  constructor() {
  }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    request = request.clone({
      responseType: 'json',
      setHeaders: {
        Authorization: `Bearer token_value`,
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
      }
    });

    return next.handle(request).do((event: HttpEvent<any>) => {
      if (event instanceof HttpResponse) {
        // do stuff with response if you want
      }
    }, (err: any) => {
      if (err instanceof HttpErrorResponse) {
        // do stuff with response error if you want
      }
    });
  }
}

हम इस AuthHttpInterceptor वर्ग को HttpInterceptors के लिए एक प्रदाता के रूप में उपयोग कर सकते हैं:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app.routing-module';
import { AuthHttpInterceptor } from './services/auth-http.interceptor';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    BrowserAnimationsModule,
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthHttpInterceptor,
      multi: true
    }
  ],
  exports: [],
  bootstrap: [AppComponent]
})
export class AppModule {
}

8

देर से बेहतर कभी नहीं ... =)

आप विस्तारित BaseRequestOptions(यहां से https://angular.io/docs/ts/latest/guide/server-communication.html# !# override-default-request-options) की अवधारणा को ले सकते हैं और मक्खी पर हेडर को ताज़ा कर सकते हैं। "(केवल निर्माता में नहीं)। आप गेट्टर / सेटर "हेडर्स" प्रॉपर्टी को इस तरह से ओवरराइड कर सकते हैं:

import { Injectable } from '@angular/core';
import { BaseRequestOptions, RequestOptions, Headers } from '@angular/http';

@Injectable()
export class DefaultRequestOptions extends BaseRequestOptions {

    private superHeaders: Headers;

    get headers() {
        // Set the default 'Content-Type' header
        this.superHeaders.set('Content-Type', 'application/json');

        const token = localStorage.getItem('authToken');
        if(token) {
            this.superHeaders.set('Authorization', `Bearer ${token}`);
        } else {
            this.superHeaders.delete('Authorization');
        }
        return this.superHeaders;
    }

    set headers(headers: Headers) {
        this.superHeaders = headers;
    }

    constructor() {
        super();
    }
}

export const requestOptionsProvider = { provide: RequestOptions, useClass: DefaultRequestOptions };

थोड़ा अद्यतन: बेहतर प्रदर्शन के लिए आप कंस्ट्रक्टर के लिए सभी स्थिर हेडर (जैसे 'सामग्री-प्रकार') पर विचार कर सकते हैं
Александр Ильинский

7

इस तरह मैंने हर अनुरोध के साथ टोकन स्थापित करने के लिए किया।

import { RequestOptions, BaseRequestOptions, RequestOptionsArgs } from '@angular/http';

export class CustomRequestOptions extends BaseRequestOptions {

    constructor() {
        super();
        this.headers.set('Content-Type', 'application/json');
    }
    merge(options?: RequestOptionsArgs): RequestOptions {
        const token = localStorage.getItem('token');
        const newOptions = super.merge(options);
        if (token) {
            newOptions.headers.set('Authorization', `Bearer ${token}`);
        }

        return newOptions;
    }
}

और app.module.ts में रजिस्टर करें

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule
    ],
    providers: [
        { provide: RequestOptions, useClass: CustomRequestOptions }
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

6

यहां स्वीकार किए गए उत्तर का एक उन्नत संस्करण है, जिसे Angular2 फाइनल के लिए अपडेट किया गया है:

import {Injectable} from "@angular/core";
import {Http, Headers, Response, Request, BaseRequestOptions, RequestMethod} from "@angular/http";
import {I18nService} from "../lang-picker/i18n.service";
import {Observable} from "rxjs";
@Injectable()
export class HttpClient {

    constructor(private http: Http, private i18n: I18nService ) {}

    get(url:string):Observable<Response> {
        return this.request(url, RequestMethod.Get);
    }

    post(url:string, body:any) {   
        return this.request(url, RequestMethod.Post, body);
    }

    private request(url:string, method:RequestMethod, body?:any):Observable<Response>{

        let headers = new Headers();
        this.createAcceptLanguageHeader(headers);

        let options = new BaseRequestOptions();
        options.headers = headers;
        options.url = url;
        options.method = method;
        options.body = body;
        options.withCredentials = true;

        let request = new Request(options);

        return this.http.request(request);
    }

    // set the accept-language header using the value from i18n service that holds the language currently selected by the user
    private createAcceptLanguageHeader(headers:Headers) {

        headers.append('Accept-Language', this.i18n.getCurrentLang());
    }
}

बेशक, इसे deleteऔर जैसे तरीकों के लिए बढ़ाया जाना चाहिएput यदि आवश्यक हो (मुझे अपनी परियोजना में इस बिंदु पर अभी तक उनकी आवश्यकता नहीं है)।

लाभ यह है कि get/ में कम डुप्लिकेट कोड हैpost / ... विधियों ।

ध्यान दें कि मेरे मामले में मैं प्रमाणीकरण के लिए कुकीज़ का उपयोग करता हूं। मुझे i18n ( Accept-Languageहेडर) के लिए हेडर की आवश्यकता थी क्योंकि हमारे एपीआई द्वारा लौटाए गए कई मान उपयोगकर्ता की भाषा में अनुवादित हैं। मेरे ऐप में i18n सेवा उपयोगकर्ता द्वारा वर्तमान में चुनी गई भाषा रखती है।


हेडर को अनदेखा करने के लिए आपको कैसे tllint मिला?
विन्नमुक्का

5

कैसे एक अलग सेवा रखने के बारे में इस प्रकार है

            import {Injectable} from '@angular/core';
            import {Headers, Http, RequestOptions} from '@angular/http';


            @Injectable()
            export class HttpClientService extends RequestOptions {

                constructor(private requestOptionArgs:RequestOptions) {
                    super();     
                }

                addHeader(headerName: string, headerValue: string ){
                    (this.requestOptionArgs.headers as Headers).set(headerName, headerValue);
                }
            }

और जब आप इसे दूसरी जगह से उपयोग कर रहे हैं this.httpClientService.addHeader("Authorization", "Bearer " + this.tok);

और आपको एडेड हेडर दिखाई देगा जैसे: - प्राधिकरण इस प्रकार है

यहां छवि विवरण दर्ज करें


5

कुछ जांच के बाद, मैंने पाया कि अंतिम और सबसे आसान तरीका विस्तारित करना है BaseRequestOptionsजिसे मैं पसंद करता हूं।
निम्नलिखित तरीके हैं जो मैंने कोशिश की और किसी कारण के लिए छोड़ देते हैं:
1. BaseRequestOptionsमें डायनेमिक हेडर बढ़ाएं और जोड़ें constructor()। अगर मैं लॉगिन करता हूं तो यह काम नहीं कर सकता। इसे एक बार बनाया जाएगा। तो यह गतिशील नहीं है।
2. विस्तार Http। उपरोक्त कारण से, मैं डायनेमिक हेडर नहीं जोड़ सकता constructor()। और अगर मैं request(..)विधि को फिर से लिखना , और हेडर सेट करना, जैसे:

request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {
 let token = localStorage.getItem(AppConstants.tokenName);
 if (typeof url === 'string') { // meaning we have to add the token to the options, not in url
  if (!options) {
    options = new RequestOptions({});
  }
  options.headers.set('Authorization', 'token_value');
 } else {
  url.headers.set('Authorization', 'token_value');
 }
 return super.request(url, options).catch(this.catchAuthError(this));
}

आपको बस इस पद्धति को अधिलेखित करने की आवश्यकता है, लेकिन प्रत्येक प्राप्त / पोस्ट / पुट विधि नहीं।

3. और मेरे पसंदीदा समाधान का विस्तार BaseRequestOptionsऔर अधिलेखित है merge():

@Injectable()
export class AuthRequestOptions extends BaseRequestOptions {

 merge(options?: RequestOptionsArgs): RequestOptions {
  var newOptions = super.merge(options);
  let token = localStorage.getItem(AppConstants.tokenName);
  newOptions.headers.set(AppConstants.authHeaderName, token);
  return newOptions;
 }
}

इस merge()फ़ंक्शन को हर अनुरोध के लिए बुलाया जाएगा।


दिए गए सभी उत्तरों के बीच, यह उत्तर है जिसने मेरा ध्यान खींचा क्योंकि मैं पहले से ही एक समाधान के लिए चला गया हूं जो कि विस्तार पर आधारित है BaseRequestOptions। हालांकि, दुख की बात है कि यह मेरे लिए काम नहीं किया। कोई संभावित कारण?
विग्रह

यह काम कर रहा है। यह समाधान ठीक है और मुझे अपने सर्वर में समस्या थी। मुझे CORS प्री-फ़्लाइट अनुरोधों के लिए कुछ कॉन्फ़िगरेशन करने थे। इस लिंक को देखें stackoverflow.com/a/43962690/3892439
vigamage

आप AuthRequestOptionsबाकी ऐप में कैसे टाई करते हैं? मैंने providersइसे सेक्शन में डालने की कोशिश की लेकिन यह कुछ नहीं कर पाया।
ट्रैविस पार्क

आपको प्रदाता को ओवरराइड करना चाहिए RequestOptions, नहीं BaseRequestOptionsangular.io/api/http/BaseRequestOptions
ट्रैविस पार्क

मेरे ऐप में, मैं बस बेसरेस्टेस्टेओशंस को बढ़ाता हूं, और यह पहले से ही रिक्वेस्ट ऑउटऑन करता है। फिर app.module में, आपको प्रदाताओं को सेट करना चाहिए:{ provide: RequestOptions, useClass: AuthRequestOptions }
मावलर्न

5

हालांकि मैं इसका उत्तर बहुत देर से दे रहा हूं लेकिन अगर कोई आसान समाधान चाहता है।

हम angular2-jwt का उपयोग कर सकते हैं। Angular2-jwt स्वचालित रूप से एक JSON वेब टोकन (JWT) को एक प्राधिकरण हेडर के रूप में संलग्न करता है जब HTTP एक कोणीय 2 ऐप से HTTP अनुरोध करता है।

हम उन्नत कॉन्फ़िगरेशन विकल्प के साथ वैश्विक हेडर सेट कर सकते हैं

export function authHttpServiceFactory(http: Http, options: RequestOptions) {
  return new AuthHttp(new AuthConfig({
    tokenName: 'token',
        tokenGetter: (() => sessionStorage.getItem('token')),
        globalHeaders: [{'Content-Type':'application/json'}],
    }), http, options);
}

और प्रति अनुरोध टोकन भेजना पसंद है

    getThing() {
  let myHeader = new Headers();
  myHeader.append('Content-Type', 'application/json');

  this.authHttp.get('http://example.com/api/thing', { headers: myHeader })
    .subscribe(
      data => this.thing = data,
      err => console.log(error),
      () => console.log('Request Complete')
    );

  // Pass it after the body in a POST request
  this.authHttp.post('http://example.com/api/thing', 'post body', { headers: myHeader })
    .subscribe(
      data => this.thing = data,
      err => console.log(error),
      () => console.log('Request Complete')
    );
}

गोटो github.com/auth0/angular2-jwt#installation के लिए उपयोगी होगा और उनके इंस्टॉलेशन गाइड का उपयोग करके इस उत्तर को अनुकूलित करें
Zuriel

4

मुझे डिफ़ॉल्ट विकल्पों को ओवरराइड करने का विचार पसंद है, यह एक अच्छा समाधान की तरह लगता है।

हालाँकि, यदि आप Httpकक्षा को बढ़ा रहे हैं । इसे ज़रूर पढ़ें!

यहां कुछ जवाब वास्तव में गलत तरीके से ओवरलोडिंग के तरीके दिखा रहे हैं request(), जिससे मुश्किल से लेकर गलतियां और अजीब व्यवहार हो सकता है। मैं इस पर खुद लड़खड़ा गया हूं।

यह समाधान request()एंगुलर में विधि के कार्यान्वयन पर आधारित है 4.2.x, लेकिन भविष्य के अनुकूल होना चाहिए:

import {Observable} from 'rxjs/Observable';
import {Injectable} from '@angular/core';

import {
  ConnectionBackend, Headers,
  Http as NgHttp,
  Request,
  RequestOptions,
  RequestOptionsArgs,
  Response,
  XHRBackend
} from '@angular/http';


import {AuthenticationStateService} from '../authentication/authentication-state.service';


@Injectable()
export class Http extends NgHttp {

  constructor (
    backend: ConnectionBackend,
    defaultOptions: RequestOptions,
    private authenticationStateService: AuthenticationStateService
  ) {
    super(backend, defaultOptions);
  }


  request (url: string | Request, options?: RequestOptionsArgs): Observable<Response> {

    if ('string' === typeof url) {

      url = this.rewriteUrl(url);
      options = (options || new RequestOptions());
      options.headers = this.updateHeaders(options.headers);

      return super.request(url, options);

    } else if (url instanceof Request) {

      const request = url;
      request.url = this.rewriteUrl(request.url);
      request.headers = this.updateHeaders(request.headers);

      return super.request(request);

    } else {
      throw new Error('First argument must be a url string or Request instance');
    }

  }


  private rewriteUrl (url: string) {
    return environment.backendBaseUrl + url;
  }

  private updateHeaders (headers?: Headers) {

    headers = headers || new Headers();

    // Authenticating the request.
    if (this.authenticationStateService.isAuthenticated() && !headers.has('Authorization')) {
      headers.append('Authorization', 'Bearer ' + this.authenticationStateService.getToken());
    }

    return headers;

  }

}

ध्यान दें कि मैं import { Http as NgHttp } from '@angular/http';नाम क्लैश को रोकने के लिए इस तरह से ओरिजनल क्लास इंपोर्ट कर रहा हूं ।

यहां संबोधित समस्या यह है कि request()विधि में दो अलग-अलग कॉल हस्ताक्षर हैं। जब RequestURL के बजाय ऑब्जेक्ट पास किया जाता है string, तो optionsतर्क को Angular द्वारा अनदेखा कर दिया जाता है। तो दोनों मामलों को ठीक से संभाला जाना चाहिए।

और यहां इस बात का उदाहरण दिया गया है कि डीआई कंटेनर के साथ इस ओवरराइड क्लास को कैसे पंजीकृत किया जाए:

export const httpProvider = {
  provide: NgHttp,
  useFactory: httpFactory,
  deps: [XHRBackend, RequestOptions, AuthenticationStateService]
};


export function httpFactory (
  xhrBackend: XHRBackend,
  requestOptions: RequestOptions,
  authenticationStateService: AuthenticationStateService
): Http {
  return new Http(
    xhrBackend,
    requestOptions,
    authenticationStateService
  );
}

इस तरह के दृष्टिकोण से आप इंजेक्शन लगा सकते हैं Http सामान्य रूप से कक्षा , लेकिन आपके ओवरराइड किए गए वर्ग को इसके बजाय जादुई रूप से इंजेक्ट किया जाएगा। यह आपको आवेदन के अन्य भागों (कार्रवाई में बहुरूपता) को बदलने के बिना आसानी से अपने समाधान को एकीकृत करने की अनुमति देता है।

बस अपने मॉड्यूल मेटाडेटा httpProviderकी providersसंपत्ति में जोड़ें ।


1

सब से सरल

एक config.tsफ़ाइल बनाएँ

import { HttpHeaders } from '@angular/common/http';

export class Config {
    url: string = 'http://localhost:3000';
    httpOptions: any = {
        headers: new HttpHeaders({
           'Content-Type': 'application/json',
           'Authorization': JSON.parse(localStorage.getItem('currentUser')).token
        })
    }
}

फिर अपने पर service, बस config.tsफ़ाइल आयात करें

import { Config } from '../config';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class OrganizationService {
  config = new Config;

  constructor(
    private http: HttpClient
  ) { }

  addData(data): Observable<any> {
     let sendAddLink = `${this.config.url}/api/addData`;

     return this.http.post(sendAddLink , data, this.config.httpOptions).pipe(
       tap(snap => {
      return snap;
        })
    );
 } 

मुझे लगता है कि यह सबसे सरल और सबसे सुरक्षित था।


0

कोणीय 2.0.1 और उच्चतर के लिए कुछ बदलाव थे:

    import {RequestOptions, RequestMethod, Headers} from '@angular/http';
    import { BrowserModule } from '@angular/platform-browser';
    import { HttpModule }     from '@angular/http';
    import { AppRoutingModule } from './app.routing.module';   
    import { AppComponent }  from './app.component';

    //you can move this class to a better place
    class GlobalHttpOptions extends RequestOptions {
        constructor() { 
          super({ 
            method: RequestMethod.Get,
            headers: new Headers({
              'MyHeader': 'MyHeaderValue',
            })
          });
        }
      }

    @NgModule({

      imports:      [ BrowserModule, HttpModule, AppRoutingModule ],
      declarations: [ AppComponent],
      bootstrap:    [ AppComponent ],
      providers:    [ { provide: RequestOptions, useClass: GlobalHttpOptions} ]
    })

    export class AppModule { }

काम नहीं करता है, यह खुद की कोशिश की। कुछ भी कहा जाता है, लेकिन ताज़ा नहीं है।
फिल

0

मैं एक सरल समाधान चुनने में सक्षम हूं> अपने Api get (या अन्य) फ़ंक्शन द्वारा मर्ज या लोड होने वाले डिफॉल्ट विकल्पों में एक नया हेडर जोड़ें।

get(endpoint: string, params?: any, options?: RequestOptions) {
  if (!options) {
    options = new RequestOptions();
    options.headers = new Headers( { "Accept": "application/json" } ); <<<<
  }
  // [...] 
}

बेशक आप इस हेडर को डिफ़ॉल्ट विकल्पों में या अपनी कक्षा में जो कुछ भी हो सकते हैं। यह आयोनिक जनित api.ts @Injectable () निर्यात वर्ग API {} में है

यह बहुत जल्दी है और यह मेरे लिए काम करता है। मैं json / ld प्रारूप नहीं चाहता था।


-4

आप canActiveअपने मार्गों में उपयोग कर सकते हैं , जैसे:

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { CanActivate } from '@angular/router';
import { AuthService } from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private auth: AuthService, private router: Router) {}

  canActivate() {
    // If user is not logged in we'll send them to the homepage 
    if (!this.auth.loggedIn()) {
      this.router.navigate(['']);
      return false;
    }
    return true;
  }

}

const appRoutes: Routes = [
  {
    path: '', redirectTo: '/deals', pathMatch: 'full'
  },
  {
    path: 'special',
    component: PrivateDealsComponent,
    /* We'll use the canActivate API and pass in our AuthGuard.
       Now any time the /special route is hit, the AuthGuard will run
       first to make sure the user is logged in before activating and
       loading this route. */
    canActivate: [AuthGuard]
  }
];

से लिया गया: https://auth0.com/blog/angular-2-authentication

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.