Angular 2+ http.get() stuck in pending status - node.js

I have a MEAN app.
Angular CLI: 7.1.4
Node: 10.1.0
OS: win32 x64
Angular: 7.1.4
recently the http requests from HttpClientModule have been getting stuck and not posting to the node server:
Img of chrome dev tools xhr pending request
The nodejs server ( running locally and in production (azure web app) does not indicate that it ever received the request. This happens inconsistently. some times it completes other times it just hangs.
Here is a snippet of a testConnection call from Angular to the server:
Angular service
import { Injectable } from '#angular/core';
import { HttpClient, HttpErrorResponse } from '#angular/common/http';
import { throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { environment } from '../../environments/environment';
const Headers: any = { withCredentials: true, responseType: 'json', headers: { 'Content-Type': 'application/json' } };
#Injectable({
providedIn: 'root',
})
export class UserService {
constructor(private _http: HttpClient) {}
loginStatus() {
return this._http.get(`${environment.serverURL}/api/login-status`, Headers).pipe(catchError(this.handleError));
}}
Angular Component:
ngOnInit() {
this._userSvc.loginStatus().subscribe(
(result:any)=>{console.log(result)},
(error:any)=>{console.log(error)})
}
Node/express:
router.get('/login-status', (req, res, next) => {
if (req.isAuthenticated()) {
res.status(200).json(req.user);
} else {
res.status(403).json({
success: false,
error: 'User not Authenticated',
message: "Please return to the login in page and try again."
})
}
})
Node is using passport to authenticate
Don't get tied up with the passport issue because its not always this route that fails. I have simple routes that do no validation and just return some text that fail too.
I tried modifying my CORS options but I've only managed to block myself.
There are times when restarting the server will allow the request to finish but not always.

I found the problem and i'm embarrassed to say it was in the SQL connection string for mssql.
I had ((config,error)=>{}) instead of the correct (config,(err)=>{}); This was in the de-serialize user function of passport. Nothing like looking over thousands of lines of code to spot one little problem.

Related

How to intercept HTTP Calls in AWS Amplify with Angular

Problem Statement:
I have working on project in Angular using AWS Amplify. The project uses cognito and successfully created AWS api for client calls. Now, I need an interceptor to intercept the requests as I need to do perform some action.
What I DID:
I have tried using Angular HTTP Interceptors but they don't work. According to my research that AWS Amplify uses axios interceptors under the hood to intercept the calls. I tried implementing using Axios package
https://www.npmjs.com/package/axios
My Implementation:
MyIntercept.ts
import { Injectable } from '#angular/core';
import axios from 'axios';
#Injectable({providedIn: 'root'})
export class MyInterceptor {
intercept() {
console.log("Hello this is my interceptor")
axios.interceptors.request.use(request => {
console.log("*******************Inside My Interceptor*************");
console.log("Call: ", request);
return request;
});
}
}
export function InterceptorFactory(myIntercept: MyInterceptor): any {
return () => myIntercept.intercept();
}
and in the app Module file
import { InterceptorFactory, MyInterceptor } from './myInterceptor.service';
import { APP_INITIALIZER } from '#angular/core';
providers: [
{
provide: APP_INITIALIZER,
useFactory: InterceptorFactory,
deps: [MyInterceptor],
multi: true
}
]
What I get:
When I run the code, all I see the line outside the console for once only which is:
Hello this is my interceptor
I need to ask you if I am doing something wrong here or is there any other approach to achieve this?

How to check session in angular 8

I have created login form with angular 8 and node js. I have set the session using node js in back end. i couldnt check session set or not in angular for avoid access dashboard without logged in. Kindly suggest the way to use login system using angular 8 and node js. Thanks.....
A very popular method is to use JWT (JSON Web Tokens) npm package to authenticate.
The process would be:
Send credentials to the server
Server generates and sends back JWT or a Bearer Token
FrontEnd would store it in browser cookies or localStorage
localStorage.setItem('TOKEN', tokenReceivedFromServer);
In subsequent Api Calls the token would be sent to the server in a Header (Authorization).
Authorization: `JWT ${localStorage.getItem('TOKEN')}`
FYI: JWT keyword is removed from string on the server before parsing token
The frontend can check if the token is set in storage to show login page / dashboard
First we need to check the login credentials valid or not in application.
In angular application component typescript file, we have send the data service in argument, the service send the values to backend using httpclient. If credentials valid we set the value in localstorage.
submitLogin(data:any)
{
this.LoginService.loginData(data).subscribe(data =>{
if(data.body.status_code == 404)
{
Swal.fire({
icon: 'warning',
title: 'Invalid E-Mail/Password!',
}).then(function(){
});
}else if(data.body.status_code ==200)
{
localStorage.setItem("user_id",data.body.token);
this.router.navigate(['/Dashboard']);
}else
{
Swal.fire({
icon: 'error',
title: 'Process Failed!',
}).then(function(){
});
}
});
}
In service.ts file make sure about those packages import
import { HttpClient } from '#angular/common/http';
import { Observable, throwError } from 'rxjs';
import {Login} from './login';
in loginData function
url = "http://localhost:3000/loginCheck";
loginData(Login:Login):Observable<any>
{
return this.http.post(this.url,Login,{observe: 'response'});
}
in backend i have used node.js
in file app.js
first install jsonwebtoken package and include in the file.
npm install jsonwebtoken
then set the jsonwebtoken when where condition satisfies
let payload = {subject:employee_id}
let token = jwt.sign(payload,'secretKey')
var response = {
'token': token,
"status_code":200,
}
res.send(response);
res.end();
Whenever we use the login in angular we must use the authguard routing its helps to access dashboard without logged in.
ng generate guard auth
in auth.guard.ts file we must include the package and service
import { CanActivate, Router } from '#angular/router';
import {LoginService} from './login.service';
export class AuthGuard implements CanActivate {
constructor(private LoginService:LoginService,private router:Router) {}
canActivate(): boolean
{
if(this.LoginService.loggedIn())
{
return true
}else
{
this.router.navigate(['/login']);
return false;
}
}
}
In this file we just checking the localstorage value set or not in boolean datatype.
in service file
add the following code for get and return in boolean type
loggedIn()
{
return !!localStorage.getItem('user_id')
}
getToken()
{
return localStorage.getItem('user_id')
}
if its returns true we can access the dasboard, else its redirected to login page.
We must use this canActive function in routing otherwise it will not working
In app-routing.module.ts file
import { AuthGuard } from './auth.guard';
const routes: Routes = [
{path:'Dashboard',component:DashboardComponent},
{path:'receipt',component:ReciptComponentComponent,canActivate:[AuthGuard]},
];
It will helpus to access dashboard without loggedin but we need to check the token valid or not in backend, we can do that using angular interceptors
we should create the new service with interceptors name
ng g service token-interceptor
In interceptor file we need to import the following
import { Injectable,Injector } from '#angular/core';
import { HttpInterceptor } from '#angular/common/http';
import { LoginService } from './login.service';
In interceptors services inject in different way compared to component.
export class TokenInterceptorService implements HttpInterceptor{
constructor(private Injector:Injector) { }
intercept(req:any,next:any)
{
let loginService = this.Injector.get(LoginService);
let tokenzedReq = req.clone({
setHeaders:
{
Authorization: `Bearer ${loginService.getToken()}`
}
});
return next.handle(tokenzedReq)
}
}
we need to create a function in interceptors with the name intercept, then we need to inject the service as per injector.
In backend we need to create the helper function to verify the jsonwebtoken
if the authorization not set we can send the response 401 not found and can redirected to login page
function verifyToken(req,res,next)
{
if(!req.headers.authorization)
{
return res.status(401).send('Unauthorized request');
}
var token = req.headers.authorization.split(' ')[1];
if(!token)
{
return res.status(401).send('Unauthorized request');
}
if(token === 'null')
{
return res.status(401).send('Unauthorized request');
}
//let payload = jwt.verify(token,'secretKey');
let payload = jwt.decode(token,'secretKey');
if(!payload)
{
return res.status(401).send('Unauthorized request');
}
req.userId = payload.subject;
next();
}
then we can use this middleware function wherever we need
for example
app.get('/dashboard',verifyToken,function(req,res){
let events = [];
res.json(events);
});
In dashboard component ts file
this.dashboardService.getData().subscribe(data=>this.dashboardData=data,
err=>{
if(err instanceof HttpErrorResponse)
{
if(err.status===401)
{
this.router.navigate(['/login']);
}
}
})
in dashboard service ts file
url = "http://localhost:3000/dashboard";
getData()
{
return this.http.get<any>(this.url);
}
in app.module.ts file
import { AuthGuard } from './auth.guard';
import { ReciptComponentComponent } from './recipt-component/recipt-component.component';
import { HttpClientModule, HTTP_INTERCEPTORS } from '#angular/common/http';
import { TokenInterceptorService } from './token-interceptor.service';
import { DashboardServiceService } from './dashboard-service.service';
in providers
providers: [AuthGuard,{provide:HTTP_INTERCEPTORS,useClass:TokenInterceptorService,multi:true},DashboardServiceService],

Angular 8 - cannot get httpClient POST to do its work maybe in conjunction with Socket.io?

I had a working AngularJS Frontend and a backend written in node.js' express, http and socket.io. Now I want to translate the frontend to Angular 8 and further use the old backend (because it worked well and was a ton of work).
Now I use ngx-socket-io for the chat communication and want to use the HttpClientModule of Angular for the API-requests.
app.module.ts
...
import { HttpClientModule } from '#angular/common/http';
import { SocketIoModule, SocketIoConfig } from 'ngx-socket-io';
...
const apiConfig: SocketIoConfig = { url: 'http://localhost:8000', options: {} };
#NgModule({declarations: [...], imports: [
...
HttpClientModule,
SocketIoModule.forRoot(apiConfig)
]
...
login.component.ts
import { CommunicationService } from '../services/communication.service';
...
constructor(
...
private comm: CommunicationService
) { }
submitForm() {
const formValue = this.loginGroup.value;
this.comm.checkAuthentication(formValue.userName, formValue.password);
}
communication.service.ts
import { Socket } from 'ngx-socket-io';
import { HttpClient, HttpErrorResponse } from '#angular/common/http';
...
#Injectable({
providedIn: 'root'
})
export class CommunicationService {
private api = 'http://localhost:8001/api';
constructor(private socket: Socket, private http: HttpClient) { }
checkAuthentication(username: string, password: string) {
console.log(`send: ${username}, ${password}`);
const test = this.http.post<any>(
`${this.api}/authenticate`,
{ username, password }
).pipe(
catchError(this.errorHandler)
);
console.log(test);
const test2 = this.http.get(
`${this.api}/users`
);
console.log(test2);
}
...
}
I can see the request going out, but on the server side it doesn't arrive. I would see a log entry there. If I use postman I see the request arriving, so the server still works.
I could imagine that angular has a problem with the constantly open connection on port 8000 to the socket.io and then use the same socket to throw a request on. Could that be? And yes, the site uses a chat (works on sockets) and some other features that work by api requests. So I need both options working together.
edit: I changed the port of the api to 8001 and it still gets no response. The console.log shows a nearly complete empty object:
{…}
​_isScalar: false
​operator: Object { selector: errorHandler()
, caught: {…} }
​source: Object { _isScalar: false, source: {…}, operator: {…} }
Http client returns an observable so You have to subscribe on it to catch the data , please check this ref
this.http.post<any>(
`${this.api}/authenticate`,
{ username, password }
).pipe(
catchError(this.errorHandler)
).subscribe((data) => {
console.log(data)
});
Before you can actually send the httpclient request you need to subscribe to the returned observable from the post() and get() methods. Change your checkAuthentication() method as follows:
checkAuthentication(username: string, password: string) {
console.log(`send: ${username}, ${password}`);
this.http.post<any>(
`${this.api}/authenticate`,
{ username, password }
).pipe(
catchError(this.errorHandler)
).subscribe((data) => {
console.log(data)
});
this.http.get(
`${this.api}/users`
).subscribe((data) => {
console.log(data)
});
}

how to send GET request with parameter

I'm building a simple MEAN application, but facing some problem with a GET method.
I inserted some data in my mongo collection, now I want to GET all results passing it's Id as parameter, but angular is returning me the following:
I've searched about headers and httpParams, but can't seem to find a solution.
I tested on postman as well, using Get and passing a body as JSON, and it worked, I'm facing trouble sending it's body from angular
here's my code:
Angular service
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '#angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class WebService {
public api = "http://localhost:3000/";
//NODE API
public getRate(param: any){
console.log(param);
return this.http.get(this.api + "api/rate", {_id: param})
}
}
NodeJs function
module.exports.countVotes = function(req, res) {
console.log(req.body._id);
VoteModel.find({movie_id: req.body._id}, (err, rate) => {
if(err){
console.log('rate not found', err)
return res.status(404).json({
message: 'failed to get movie rate'
})
} else {
res.status(200).json(rate);
console.log(rate);
}
})
}
Node returns me req.body as undefined when called.
What am I missing? please someone help me.
It doesn't work because GET requests don't have request body. You can try use POST request with request body or pass the id to GET request as request param or as path variable.
You must pass an instance of HttpPrams in http.get -
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '#angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class WebService {
public api = "http://localhost:3000/";
//NODE API
public getRate(param: any){
let params = new HttpParams().set('_id', param);
console.log(param);
return this.http.get(this.api + "api/rate", { params: params })
}
}

Cannot get cookie in middleware with node and angular

I am using nodejs, express, cookie-parser and angular 6. Right now angular runs in http://localhost:4200 and node/express in http://localhost:3000. I also put
const cors = require('cors');
app.use(cors());
in my app.js in node, so both angular and node can communicate.
In my login route I create an http-only cookie with the token and then I send back a JSON with some info and the user id
res.cookie("SESSIONID", token, {httpOnly:true, secure:true});
res.json({ success:true, msg:'you are logged in', userid: resolved.id});
I suppose that the SESSIONID cookie is send with every request back to the server , so I dont have to set it myself before every request
In my middleware, I want to get the token from the cookie in order to check it. So, I do
const token = req.cookies.SESSIONID;
console.log('token from validate : ', token);
//check token and expiration, either next(); or redirect back
in my routes I have
router.get('cms/account', myMiddleware.required(), (req, res)=>{
res.json({ msg:'profile data'});
});
My profile service contacts the account route of node
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import { map } from "rxjs/operators";
#Injectable({
providedIn: 'root'
})
export class ProfileService {
constructor(private http:Http) { }
getProfile(){
return this.http.get('http://localhost:3000/cms/account').pipe(map(res => res.json()));
}
}
my profile service should render some profile data
import { Component, OnInit } from '#angular/core';
import { ProfileService } from '../../services/profile.service';
#Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
constructor( private profileService: ProfileService) { }
ngOnInit() {
this.profileService.getProfile().subscribe((data) =>{
console.log('profileService -- ', data);
})
}
}
After I login I go to http://localhost:4200/cms/profile. In the console I see token from validate : undefined
So I am sure that angular successfully reaches until the validation middleware, but cannot get the cookie.
I fail to understand why the cookie is not there. Is it my synatx? Is it not set at the start? Should I include it with every request ? Is it the different ports in localhost ? I gave as much details I could, if you need extra, just tell me. Please help me debug this, because I am lost.
Thanks

Resources