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);
}
}
Related
I am using JWT Authentication in my project and it is working well.
The issue I am facing is that before using HTTP INTERCEPTOR I was able to get a normal JSON response from the backend (Spring Boot REST API).
But, after using HTTP INTERCEPTOR (for adding AUTHENTICATION header in all HTTP requests) I am not getting JSON response, instead I am getting response as [Object object].
Most important, the backend is giving response in JSON format, I checked it using postman.
auth.interceptor.ts file
intercept(
request: HttpRequest<unknown>,
next: HttpHandler
): Observable<HttpEvent<unknown>> {
//get token from auth service
let token: any = this.authService.getToken();
//check if guest user is a first time visitor
if (!token) {
alert('no token present');
return next.handle(request.clone());
}
//add token and header to the request
request = this.addTokenAndHeader(request, token);
//return
return next.handle(request).pipe(
catchError((err: HttpErrorResponse) => {
alert('inside catch and pipe');
//redirect to login page if error code 401 or 403
if (err.status === 401 || err.status === 403) {
alert(err.status);
this.authService.clear();
this.router.navigateByUrl('/access/login');
}
return throwError('Something went wrong.');
})
);
}
//add token to http request
private addTokenAndHeader(request: HttpRequest<any>, token: string) {
alert('inside add token and header method');
return request.clone({
setHeaders: {
Authorization: `Bearer ${token}`,
},
});
}
loader.interceptor.ts
intercept(
request: HttpRequest<unknown>,
next: HttpHandler
): Observable<HttpEvent<unknown>> {
this.loaderService.isLoading.next(true);
return next.handle(request).pipe(
finalize(() => {
this.loaderService.isLoading.next(false);
})
);
}
app.module.ts file
#NgModule({
declarations: [AppComponent, NoInternetComponent],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
MaterialModule,
BrowserAnimationsModule,
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: LoaderInterceptor,
multi: true,
},
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true,
},
],
bootstrap: [AppComponent],
})
export class AppModule {}
user.service.ts - where I am calling API URL. Here I was able to get normal JSON response. But, not getting after using HTTP INTERCEPTOR. Most important, the backend is giving response in JSON format, I checked it using postman.
getUserByPhone(phone: any) {
return new Promise((resolve) => {
this.http
.get(this.constants.apiURL + '/user/get/phone/' + phone)
.subscribe((data: any) => {
alert('inside getuserbyphone method');
alert(data);
resolve(data);
});
});
}
Your help will be highly appreciated. Please come forward to help me in this case, if you have any information reagrding the same. Thanks in advance for solving my problem. Really appreciate it.
There are two ways to handle this , and one of those you already tried i.e using 'JSON.stringify'.Although this may not be a bad option considering interceptors will remain in place. But if you can't/don't want to update your application code already written and just wanted to achieve this via interceptor then in that case I believe you need to update your interceptor code to format response data to a JSON format before consuming it in the application.
You should create a separate interceptor ( best practice and is completely optional if you want to do this in same interceptor) just to format the response. Since you have not share it , do you mind checking the typeof the [Object object] in the response, I assume it should be obviously HTTPResponse type.
By default , you should see response data in the 'body' key of the returned data. I have created a quick example and below are the snippet for the interceptor.
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from "#angular/common/http";
import { Injectable } from "#angular/core";
import { Observable } from "rxjs";
import { filter, map } from "rxjs/operators";
#Injectable({
providedIn: 'root',
})
export class FormatResponseInterceptor implements HttpInterceptor {
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
filter(event => event instanceof HttpResponse),
map((event: HttpResponse<any>) => event.clone({ body: event.body }))
);
}
}
so as you see the response if event.body and you can directly consume it in your application , as below :
import { SampleService } from './service/sample.service';
export interface CatInterface {
fact: string | '',
length: number | 0;
}
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
name = 'Angular ' + VERSION.major;
apiData: CatInterface;
constructor(private sampleService: SampleService){}
ngOnInit(){
this.invokeAPI();
}
private invokeAPI(){
this.sampleService.readData().subscribe({
next: (res)=>{
this.apiData = {...res};
},
error: (err)=>{},
complete:()=>{console.log('Service Subscription Completed!');
}
})
}
}
in the above code , I just deconstructed the response object.
So you should first need to check the response object structure and consume it accordingly.
For additional notes, here is my app.component.html code :
<hello name="{{ name }}"></hello>
<p><span style="background-color: yellow"> FACT from the API is : </span> <b> {{apiData?.fact}}</b></p>
<p> <span style="background-color: yellow">LENGTH from the API is : </span><b> {{apiData?.length}}</b></p>
and below is the screen shot for the output :
Hopefully this will help you to solve your problem. Please let me know by providing your feedback so that it will help others as well in future.
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);
});
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.
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. :)
I am using Angular 2 beta.18, and trying to use google map geocode.
I am doing the same as all tutorial describe, but I receive a strange response.
My component:
import { Injectable } from '#angular/core';
import { Http, Response} from '#angular/http';
import {Observable} from 'rxjs/Observable';
#Injectable()
export class GoogleMapService {
constructor(private http: Http) { }
convertAddressToCooredinate(address: string){
if(address != null){
var address ="1334 Emerson St, NE Washington DC";
return this.http.get('https://maps.googleapis.com/maps/api/geocode/json?address='+encodeURIComponent(address))
.map(response => response.json());
}
}
}
The response should contain a JSON with results, however I recieve the following:
Observable {_isScalar: false, source: Observable, operator: MapOperator}
I tried directing the request to other URLs and receive the same response.
Your convertAddressToCooredinate function returns an observable. If you don't subscribe to this observable in your code, you won't make a rest call to your backend. Hence you log only your observable.
Example:
Some Component
constructor(private gms: GoogleMapService ) {
this.gms.convertAddressToCooredinate('some address')
.subscribe((response)=>{
console.log(response);
});
}