I am calling REST API from ionic 3 and Http Client, I am using Http Interceptor, When I am setting header name in the code, it is going under "Access-Control-Request-Headers:" see the attached Screenshot
and my code is :
import { Injectable, NgModule } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '#angular/common/http';
import { HTTP_INTERCEPTORS } from '#angular/common/http';
#Injectable()
export class HttpsRequestInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler):
Observable<HttpEvent<any>> {
const dupReq = req.clone({ headers: req.headers.set('Access-Control-Allow-Origin', '*').append('ABC','xxx') });
return next.handle(dupReq);
}
};
#NgModule({
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: HttpsRequestInterceptor, multi: true }
]
})
export class InterceptorModule { }
You have handled cors on the frontend, But it also needs to be handled from the backend, Moreover, install this extension and turn it on before making the http call and you will be able to receive response
https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en
Related
I'm setting up a Ionic 4 project using ngx-translate and a custom loader to load JSON translations from an external domain. I've been following this guys take on it: https://forum.ionicframework.com/t/ngx-translate-translatehttploader-with-external-url/99331/4
Stackblitz link: https://stackblitz.com/edit/ionic-v4-jdfbh6
So this is my custom loader (provider).
#Injectable()
export class TranslationProvider implements TranslateLoader {
constructor(private http: HttpClient) {
console.log('Hello TranslationProvider Provider');
}
getTranslation(lang: string): Observable<any> {
return Observable.create(observer => {
this.http.get<any>(Environment.base_api + '/static/translations/' + lang + 'json', {
headers: {'Content-Type': 'application/json'}}).subscribe((res: Response) => {
observer.next(res.json());
observer.complete();
});
});
}
}
and in my app.module.ts (imports):
imports: [
BrowserModule,
IonicModule.forRoot(App),
IonicStorageModule.forRoot(),
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (TranslationProvider),
deps: [HttpClient]
}
})
],
The error message I receive is:
TypeError: Cannot set property 'http' of undefined at TranslationProvider (http://localhost:8100/build/main.js:1073:19)
I made a working sample app, here's the gist:
https://gist.github.com/olivercodes/a34be66e5b69edcd96038e5a4518b16e
You need to change #Injectable() to
#Injectable({
providedIn: 'root'
})
Also, make sure these are your import locations:
// In the service file
import { HttpClient } from '#angular/common/http';
import { TranslateLoader } from '#ngx-translate/core'
// in app.module
import { TranslateLoader } from '#ngx-translate/core'
import { HttpClient, HttpClientModule } from '#angular/common/http';
Use my provided gist and make sure your imports are right.
I have upgraded my app from ng4 to ng5 v-5.2.9. I have set the headers for every request. But on my app some request does not support headers, so how to disable headers from particular request not every request.
Previously with ng4 I was using http but now facing issues as its not supported any more in ng5
setHeader.ts
import { Injectable } from '#angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpErrorResponse } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
#Injectable()
export class AddHeaderInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let currentUser = JSON.parse(localStorage.getItem('currentUser'));
if (currentUser && currentUser.token) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${currentUser.token}`,
Ip:currentUser.Ip
}
});
}
return next.handle(request);
}
}
app.module.ts:-
import { HTTP_INTERCEPTORS } from '#angular/common/http';
#NgModule({
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: AddHeaderInterceptor,
multi: true,
}],
})
export class AppModule {}
Basically headers are used for token and for autorization nut some of the API doesn't need to be authorized and hence headers are not required, by using setHeader it applies to all api calls. I have got HttpErrorResponse on my browser console. where its not required
Thanks!
I have build an interceptor for making HTTP requests to a PHP backend.
This backend gives an JWT token to the app and I save this in the Ionic Storage.
But I want to get that token from Storage and add it as an header to the HTTP request.
Below is my interceptor with and hardcoded token.
This works and I get a response from the backend.
See update # bottom of this post
http-interceptor.ts
import { HttpInterceptor, HttpRequest } from '#angular/common/http/';
import {HttpEvent, HttpHandler} from '#angular/common/http';
import { AuthProvider } from "../providers/auth/auth";
import {Injectable} from "#angular/core";
import {Observable} from "rxjs/Observable";
import {Storage} from "#ionic/storage";
#Injectable()
export class TokenInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const changedReq = req.clone({headers: req.headers.set('Authorization', 'Bearer MY TOKEN')});
return next.handle(changedReq);
}
}
But how do I get the token from storage into the header.
I searched alot and most of the tutorials / examples are from the older HTTP module. If someone has an idea or has a up2date example ?
UPDATE
Oke below code send the token
intercept(req: HttpRequest<any>, next: HttpHandler) : Observable<HttpEvent<any>>{
return fromPromise(this.Auth.getToken())
.switchMap(token => {
const changedReq = req.clone({headers: req.headers.set('Authorization', 'Bearer ' + token )});
return next.handle(changedReq);
});
}
With 1 exception, namely the first time I access that page :)
You can save JWT token in, for example, localStorage
localStorage.setItem('myToken', res.token);
and then access it with
localStorage.getItem('myToken');
In your case something like this:
import { HttpInterceptor, HttpRequest } from '#angular/common/http/';
import {HttpEvent, HttpHandler} from '#angular/common/http';
import { AuthProvider } from "../providers/auth/auth";
import {Injectable} from "#angular/core";
import {Observable} from "rxjs/Observable";
import {Storage} from "#ionic/storage";
#Injectable()
export class TokenInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const changedReq = req.clone({headers: req.headers.set('Authorization', localStorage.getItem('myToken'))});
return next.handle(changedReq);
}
}
If you want to use Ionic Storage
import { HttpInterceptor, HttpRequest } from '#angular/common/http/';
import {HttpEvent, HttpHandler} from '#angular/common/http';
import { AuthProvider } from "../providers/auth/auth";
import {Injectable} from "#angular/core";
import {Observable} from "rxjs/Observable";
import {Storage} from "#ionic/storage";
#Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(public _storage: Storage) {
_storage.get('myToken').then((val) => {
console.log('Your age is', val);
});
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const changedReq = req.clone({headers: req.headers.set('Authorization', this.val)});
return next.handle(changedReq);
}
}
Caching the token in the interceptor is a bad idea because if the token changes the interceptor will not be aware of those changes.
// Don't do this.
token: string;
constructor(private storage: Storage) {
this.storage.get('token').then((res) => {
this.token = res;
})
}
If you want to use Ionic Storage and the interceptor together you can do so by using Observable.flatMap like so...
app.module.ts
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true},
SecurityStorageService
]
AuthInterceptor.ts
#Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(
private securityStorageService: SecurityStorageService
) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// This method gets a little tricky because the security token is behind a
// promise (which we convert to an observable). So we need to concat the
// observables.
// 1. Get the token then use .map to return a request with the token populated in the header.
// 2. Use .flatMap to concat the tokenObservable and next (httpHandler)
// 3. .do will execute when the request returns
const tokenObservable = this.securityStorageService.getSecurityTokenAsObservable().map(token => {
return request = request.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
});
return tokenObservable.flatMap((req) => {
return next.handle(req).do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// do stuff to the response here
}
}, (err: any) => {
if (err instanceof HttpErrorResponse) {
if (err.status === 401) {
// not authorized error .. do something
}
}
});
})
}
security-storage-service.ts
You technically don't need this service, but you shouldn't have Ionic Storage logic in your interceptor.
#Injectable()
export class SecurityStorageService {
constructor(private storage: Storage) {
}
getSecurityToken() {
return this.storage.get(StorageKeys.SecurityToken)
.then(
data => { return data },
error => console.error(error)
);
}
getSecurityTokenAsObservable() {
return Observable.fromPromise(this.getSecurityToken());
}
}
storage-keys.ts
export class StorageKeys {
public static readonly SecurityToken: string = "SecurityToken";
}
For anyone who comes across this like me and is using rxjs >=5.5.0 then you can just do:
auth-interceptor.ts
#Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return from(this.authService.getToken()).pipe(mergeMap((token) => {
const changedReq = req.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next.handle(changedReq);
}));
}
auth-service.ts
public async getToken() {
return await this.storage.get('ACCESS_TOKEN');
}
At least I thought I was providing correctly. Below are the relevant snippets of my app.module file and the service in which I use AuthHttp. I followed the configuration in the ReadMe for creating the factory method to provide for AuthHttp, but there is a persisting issue with it not being recognized in my service. I've read the literature on nested dependency injections, and I feel as though I'm doing things correctly.
app.module.ts
import { Http, RequestOptions } from '#angular/http';
import { provideAuth, AuthHttp, AuthConfig } from 'angular2-jwt/angular2-jwt';
export function authHttpServiceFactory(http: Http, options: RequestOptions) {
return new AuthHttp(new AuthConfig(), http, options);
}
#NgModule({
declarations: [
AppComponent,
ButtonFormComponent,
...
imports: [
BrowserModule,
FormsModule,
HttpModule,
RouterModule,
AppRoutingModule
],
providers: [
{
provide: LocationStrategy,
useClass: HashLocationStrategy
},
{
provide: AuthHttp,
useFactory: authHttpServiceFactory,
deps: [Http, RequestOptions]
},
employee.service.ts
import { AuthHttp } from 'angular2-jwt/angular2-jwt';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/throw';
import { ApiSettings } from './api-settings';
#Injectable()
export class EmployeeService {
api: String;
auth: String;
constructor(private http: Http, private authHttp: AuthHttp) {
this.api = ApiSettings.API;
this.auth = ApiSettings.Auth;
}
You can get rid of this issue by just using following import in your app.module.ts, here the key import for you is, AUTH_PROVIDERS.
Also, make sure you include AUTH_PROVIDERS in the providers array.
import { AuthHttp, AUTH_PROVIDERS, provideAuth, AuthConfig } from
'angular2-jwt/angular2-jwt';
#NgModule({
providers: [AUTH_PROVIDERS]
})
I used Http Restful API at Angular2, but appear the following warning message.
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
Please tell me how to do that.
http_restful_service.ts
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
#Injectable()
export class HTTPRestfulService {
constructor(private _http: Http) {}
getAllProjectName() {
var headers = new Headers();
headers.append('Content-Type','charset=uft-8');
return
this._http.get('http://localhost/api/database/',
{headers: headers})
.map(res => res.json());
}
}
backstage_view.component.ts
import { Component, OnInit } from '#angular/core';
import { HTTPRestfulService } from './../../../service/http_restful_service';
#Component({
moduleId: module.id,
selector: 'backstage_view',
templateUrl: './backstage_view.component.html',
styleUrls: ['./backstage_view.component.css']
})
export class BackstageViewComponent implements OnInit {
allProjects: string;
constructor(private _restfulapi: HTTPRestfulService) {}
ngOnInit() {
this._restfulapi.getAllProjectName()
.subscribe(
data => this.allProjects = data,
error => console.log(error),
);
}
}
Why can't you pass the content-type as 'application/json' format,
let url= `http://localhost/api/database/`;
let headers = new Headers();
headers.append('Content-Type','application/json');
let params = new URLSearchParams;
params.append('id', id);
params.append('user_id', user_id);
return this.authHttp.post( url, { headers:headers, search:params })
.map(res => res.json());