Angular 6: Custom Header 'Authorisation' not working Angular 6 - json

I am new to Angular 6, and I am having one issue with custom header for Authorisation. I am setting a Oauth2 token in Authorisation header but it is not going along with request. I have done a lot of googling but none of the solution solves my problem. Below I am adding code.
Custom header in request:
getCurrentUser() {
let token = this.cookie.get('token');
return this.http.get<User[]>(serverurl + 'getUser',{
headers: new HttpHeaders().set('Authorization', token),
}) // this.httpOptions
.pipe(
tap(user => this.log(`fetched current user`)),
catchError(this.handleError('currentUser', []))
);
}
As request Interceptor:
import { AuthService } from '../services/auth.service';
import { Injectable } from '#angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpHeaders } from '#angular/common/http';
import { Observable } from 'rxjs';
import { CookieService } from 'ngx-cookie-service';
#Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private auth: AuthService, private cookie: CookieService) { }
intercept(req: HttpRequest<any>, next: HttpHandler) {
let token = this.cookie.get('token');
let changedRequest = req;
// HttpHeader object immutable - copy values
const headerSettings: { [name: string]: string | string[]; } = {};
if (token) {
headerSettings['Authorization'] = 'Bearer ' + token;
}
// headerSettings['Content-Type'] = 'application/json';
const newHeader = new HttpHeaders(headerSettings);
changedRequest = req.clone({
headers: newHeader
});
return next.handle(changedRequest);
}
}
It gives following request:
Authorisation token is added in Access-control-request-Header instead of Authorisation itself. And I don't see Authorisation header in request.
Thanks in Advance...!

After searching a lot for this I found the solution for this:
There is no problem in the code, since you are using Cross Origin request it first sent OPTIONS request to the server. In order to fix this I added following piece of code in my server configuration section:
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
It has nothing to do with Angular 6. Basically you need to Allow OPTIONS method for all URLs from server side. And it will work. :)

Related

Parsing json response from Http Request in Angular

I need to parse a json response containing two keys.
The response looks like
{
status: 0;
message: 'some error 404'
}
In pure nodejs or React you could just simply do: if (response.status===1)console.log('success').
However, I've been having a tough time doing this in angular. Could someone guide me and tell me how could I parse the JSON Response?
I have attached a mock-up of the code.
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Component } from '#angular/core';
#Component({
selector: 'app-create-employee',
templateUrl: './create-employee.component.html',
styleUrls: ['./create-employee.component.css']
})
export class CreateEmployeeComponent {
constructor(private http: HttpClient) { };
onFormSubmit() {
let options = {
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
};
let body = new URLSearchParams();
body.set('data', 'stackoverflow');
this.http.post('http://localhost:8080/createEmployee', body.toString(), options)
.subscribe(response => {
console.log(response.status);
console.log(response.message);
});
}
}
According to the documentation, Angular can parse for you objects from string responses if you tell it how to do it. You can use this as an example.
First define an interface inside your component just below your imports:
export interface Response {
status: number,
message: string
}
This tells angular how to parse the json response from your server. The final bit is to use this interface in your post request like this:
this.http.post<Response>('http://localhost:8080/createEmployee', body.toString(), options)
.subscribe(response => {
console.log(response.status);
console.log(response.message);
});

Impossible to post special character into dialogflow query

I'm working on a dialgflow V1 bot.
I'm really inspired by this repository : https://github.com/mlabouardy/dialogflow-angular5
I have an issue in my dialogflow service.
I can't post query with special characters.
here is my diaogflow service working but when i pass my query it is code to utf-8 which broke dialogflow :
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import 'rxjs/Rx'
import { environment } from '../../environments/environment';
#Injectable()
export class DialogflowService {
private baseURL: string = "https://api.dialogflow.com/v1/query?v=20170712";
private token: string = environment.dialogFlowToken;
constructor(private http: Http){}
public getResponse(query: string){
let data = {
query : query,
lang: 'fr',
sessionId: '12345'
}
return this.http
.post(`${this.baseURL}`, data, {headers: this.getHeaders()})
.map(res => {
return res.json()
})
}
public getHeaders(){
let headers = new Headers();
headers.append('Authorization', `Bearer ${this.token}`);
return headers;
}
}
I tried to use :
encode_utf8(s) {
return unescape(encodeURIComponent(s));
}
decode_utf8(s) {
return decodeURIComponent(escape(s));
}
But it didn't work
Do you have a suggestion ?
Thanks a lot.
Romain
try to force it with additional header and see if that works.
{'Content-Type' : 'application/json; charset=UTF-8'}

How to set header content-type as application/json in angular-oauth2-odic?

I am setting Content-Type header as application/json from fetchTokenUsingPasswordFlow method but it's going as application/x-www-form-urlencoded. Is there any way to set header content-type as application/json?
As per the source code, the Content-Type header has been hardcoded as application/x-www-form-urlencoded.
I am using spring boot rest services for backend and its not allowing application/x-www-form-urlencoded as the Content-Type. Please find the sample Angular 6 code for your reference below:
import { Component, OnInit, Input } from '#angular/core';
import { Router, ActivatedRoute } from '#angular/router';
import { Usermodel } from '../models/usermodel';
import { OAuthService } from 'angular-oauth2-oidc';
import { HttpHeaders } from '#angular/common/http';
#component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
#input() message: any;
#input() apiUrl: any;
#input() params: any;
currentUser: Usermodel;
model: any = {};
loading = false;
returnUrl: string;
headers: HttpHeaders;
constructor(private router: Router,
private route: ActivatedRoute,
private oauthService: OAuthService,
) {
oauthService.tokenEndpoint = "http://localhost:7890/api/login";
oauthService.requireHttps = false;
this.oauthService.setStorage(localStorage);
this.headers = new HttpHeaders().set('Content-Type', 'application/json');
console.log('oauthtoken', this.oauthService.getAccessToken());
}
ngOnInit() {
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
}
public login() {
this.loading = true;
this.apiUrl = 'login'
console.log("Headers::->" + this.headers)
this.oauthService.fetchTokenUsingPasswordFlow(this.model.userName, this.model.password, this.headers).then((resp) => {
console.log('resp', resp);
});
}
}
I saw a similar issue on the angular-oauth2-oidc repo a while ago, I'll repeat my reply here as an answer so it's easy for people to find.
The library hardcodes application/x-www-form-urlencoded, and I think probably rightfully so: RFC 6749 seems to prescribe this:
4.3.2. Access Token Request
The client makes a request to the token endpoint by adding the following parameters using the "application/x-www-form-urlencoded" format...
I'm a little surprised that your spring boot packages don't support changing the possible content types for the Resource Owner Password flow's token request endpoint, you could try to double check?
Alternatively, you could file an issue with the appropriate spring-boot package?
The only final other option I see (other than not using the library, which for that flow is quite possible) at this point is to fork the library and change the internals yourself for your custom build.

Angular doesn't pass HTTP GET params properly

So I figuring out my way around Angular. Just started with a OpenWeather API based application using a simple GET method.
So here is my app.component.ts:
import { Component } from '#angular/core';
import { WeatherService } from './weather.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [WeatherService]
})
export class AppComponent {
title = 'Ng-Weather';
cityName: string;
constructor(private weather: WeatherService) { }
search() {
this.weather.getWeatherbyName(this.cityName);
}
}
As you can guess, the cityName variable is two way binded. The search() function is invoked onclick of a button and the data is passed to the weatherservice. The contents of weather service is:
import { Injectable } from '#angular/core';
import { Http, Response, URLSearchParams } from '#angular/http';
import { Observable } from 'rxjs';
import { Weather } from './weather';
#Injectable()
export class WeatherService {
APIurl = "http://api.openweathermap.org/data/2.5/weather";
Appid = "xxx";
constructor(private Http: Http) { }
getWeatherbyName(name: string): Observable<any> {
let myParams = new URLSearchParams();
myParams.append('q', name);
myParams.append('appid', this.Appid);
// actual http request should look like this: http://api.openweathermap.org/data/2.5/weather?appid=xxx&q=Chennai
return this.Http.get(this.APIurl, { search: myParams})
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
console.log(res.json());
let body = res.json();
return body.data;
}
private handleError(error: Response | any) {
console.error(error.message || error);
return Observable.throw(error.message || error);
}
}
But I get no error in my console or during the compile process. What is being done wrong? Also, how can I map the JSON I get to my class and give back that instance to the app.component?
Following is my class:
export class Weather {
city: String;
max_temp: String;
min_temp: String;
description: String;
}
And this is a sample JSON I receive:
{
"coord":{
"lon":80.28,
"lat":13.09
},
"weather":[
{
"id":803,
"main":"Clouds",
"description":"broken clouds",
"icon":"04n"
}
],
"base":"stations",
"main":{
"temp":304.15,
"pressure":1008,
"humidity":79,
"temp_min":304.15,
"temp_max":304.15
},
"visibility":6000,
"wind":{
"speed":3.1,
"deg":160
},
"clouds":{
"all":75
},
"dt":1504629000,
"sys":{
"type":1,
"id":7834,
"message":0.0029,
"country":"IN",
"sunrise":1504571272,
"sunset":1504615599
},
"id":1264527,
"name":"Chennai",
"cod":200
}
As you can see all I need is some data from the JSON and not the whole thing.
Your main problem here is that you are not subscribing to the observable that is being produced by your getWeatherbyName function. Observables returned by Http are cold:
Cold observables start running upon subscription, i.e., the observable sequence only starts pushing values to the observers when Subscribe is called. (…) This is different from hot observables such as mouse move events or stock tickers which are already producing values even before a subscription is active.
In order to subscribe to this observable, you can simply update your search function to the following:
search() {
this.weather.getWeatherbyName(this.cityName)
.subscribe();
}
This is by no means the complete solution to your problem - You will want to do something in the subscription, such as assign the information received to properties of your component so that they can be rendered in the UI.
You appear to have other issues in your linked project, but I suggest you ask separate questions on Stack Overflow if needed, or even better, your favorite search engine should be able to help.
Try passing a RequestOptions object to the http get instead:
import { RequestOptions } from '#angular/http';
getWeatherbyName(name: string): Observable<any> {
let myParams = new URLSearchParams();
myParams.append('q', name);
myParams.append('appid', this.Appid);
let options = new RequestOptions({ search: myParams}); //<----- NEW
// actual http request should look like this: http://api.openweathermap.org/data/2.5/weather?appid=xxx&q=Chennai
return this.Http.get(this.APIurl, options) //<<----- NEW
.map(this.extractData)
.catch(this.handleError);
}

Cannot GET http requests for Rest api in angular 2

Im trying to get http GET requests in angular 2 frontend using the Rest api created in magento 2.
\var\www\html\Angular2\sample-ng-http-master\web\app\app.component.ts
///<reference path="../node_modules/angular2/typings/browser.d.ts" />
import "rxjs/add/operator/map";
import {Component, Input} from 'angular2/core';
import {Http} from 'angular2/http';
interface Person {
//name: string;
//age: number;
}
#Component({
selector: 'my-app',
template: `<h1>My First Angular 2 App</h1>
<div>{{people | json}}</div>
`
})
export class AppComponent {
#Input() private people: Person[];
constructor(private http: Http) {
}
public ngOnInit() {
this.http.get('http://10.20.1.2:3000/data.json')
.map(response => {
console.log(response.json);
console.log(response.json());
return response.json()
})
.subscribe((items: Person[]) => {
console.log('items: ' + items);
this.people = items;
}, error => console.log(error))
}
}
Here if my try to get the json file (http://10.20.1.2:3000/data.json) as shown, Im able to get the json response.
What i need is i need to pass the API endpoint of the Magento 2 like this:
http://10.20.1.2/Magento2/index.php/rest/V1/customers/1
The above rest endpoint works perfect if i call from Postman client.
If i use the same URL(http://10.20.1.2/Magento2/index.php/rest/V1/customers/1) in app.component.ts file i get:
If I use the URl with port 3000 as:(http://10.20.1.2:3000/Magento2/index.php/rest/V1/customers/1) I get:
Response {_body: "Cannot GET /Mage_ang2/index.php/rest/V1/customers/1↵", status: 404, statusText: "Ok", headers: Headers, type: 2…
Which part am i missing?
You need to set headers:
Access-Control-Allow-Origin: 'your_angular_server_address'
and
Access-Control-Allow-Headers: 'Access-Control-Allow-Origin'
It is CORS problem.
You need to add the headers:
/**
* Interceptor set the headers for the request.
* Params:
* - objectToSetHeadersTo: Request or Arguments that will contain the headers.
**/
private setHeaders(objectToSetHeadersTo: Request | RequestOptionsArgs) {
const headers = objectToSetHeadersTo.headers;
headers.set('Content-Type', 'application/json');
if (this.token) {
headers.set('Authorization', 'Token ' + this.token);
}
}