Angular 5 http response different with server response - node.js

I found some bug in angular (that what i think), i am create web app with angular and rest api server with nodejs.
my angular request login to the server, if success set-cookie header will be sent to client (automatically save to browser) and the page redirect to home page. if not success, it will display error message.
in home page, my page will request active profile to the server (request with saved cookie as header).
picture above is cookie that requested to server, and response i got from server. the problem is, that not exactly response sent from server.
picture above, exact response i captured from response, it still development, and just have one response i captured.
can anyone tell me about this error, what this is a bug of angular 5 or my code.
===== update =====
import { trigger, state, style, transition, animate } from '#angular/animations';
import { Component, OnInit, OnDestroy } from '#angular/core';
import { Profile } from './profile';
import { MessageService, ApiService } from '../../../helper/index';
import { CookieService } from 'ngx-cookie-service';
#Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.css'],
providers: [CookieService],
animations: [
trigger('sidebar', [
state('inactive',
style({
transform: 'scale(1)'
})
),
state('active',
style({
left: '0em'
})
),
transition('inactive => active', animate('400ms ease-in')),
transition('active => inactive', animate('400ms ease-out'))
]),
trigger('buttonIcon', [
state('inactive',
style({
transform: 'scale(1)'
})
),
state('active',
style({
left: '18em'
})
),
transition('inactive => active', animate('400ms ease-in')),
transition('active => inactive', animate('400ms ease-out'))
])
]
})
export class SidebarComponent implements OnInit, OnDestroy {
state: string;
profile: Profile;
constructor(private msg: MessageService, private api: ApiService, private cookie: CookieService) {
}
ngOnInit() {
this.reset();
this._getProfile();
}
ngOnDestroy() {
this.reset();
}
toggleState() {
this.state = this.state === 'active' ? 'inactive' : 'active';
}
_getProfile() {
console.log('get profile ===========');
console.log(this.cookie.getAll());
this.api.get('/utility/profile')
.then((data: any) => {
console.log(data);
this.profile = data;
})
.catch(err => {
console.log(err);
this.msg.error(err);
});
}
reset() {
this.state = 'inactive';
this.profile = {
img: '', nama: '', email: '', user_id: ''
};
}
}
code above, show my code request profile to server.
import { environment } from '../environments/environment';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Injectable } from '#angular/core';
#Injectable()
export class ApiService {
constructor(private http: HttpClient) {
}
get(path) {
const uri = environment.apiUrl + path;
const headers = {
headers: new HttpHeaders().set('Content-type', 'application/json')
};
return new Promise((res, rej) => {
const req = this.http.get(uri, headers);
req.subscribe(
(response: any) => {
if (response.s) {
res(response.d);
} else {
rej(response.e);
}
},
(err) => {
rej(err.message);
}
);
});
}
post(path, body) {
const uri = environment.apiUrl + path;
const opt = {
};
return this.http.post(
uri, body,
{
headers: new HttpHeaders({'Content-type': 'application/json'})
}
)
.toPromise()
.then((response: any) => {
if (response.s) {
if (response.d) {
return Promise.resolve(response.d);
} else {
return Promise.resolve();
}
} else {
if (response.e) {
return Promise.reject(response.e);
} else {
return Promise.reject('');
}
}
});
}
}
code above, service bridge request that handled request to server.

Related

Solved POST request in Angular unexpected end of input

Solution I've discovered that the problems comes from my html code where register is triggered.
I'm stuck on this for a while.
I'm trying to make http POST request to my server, but can't handle the result back.
register.component.ts
export class RegisterComponent implements OnInit {
constructor(private router: Router, private userService: UserService) { }
ngOnInit() {}
register(username: string, password: string, email: string) {
const user = new User(username, password, email);
this.userService.create(user);
}
user.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
#Injectable()
export class UserService {
constructor(private http: HttpClient) { }
create(user: User) {
return this.http.post('http://localhost:3000/register', user)
.subscribe( res =>
console.log(res)
);
}
}
Edit the res is Syntax Error Unexpected end of input
I'm always getting a new user created in the database, though.
Here is my server logic implemented with Node and Express written in typescript
register(req: Request, res: Response, next: NextFunction) {
const user = new User(req.body);
User.findOne({ username: user.username }, (err, result: IUserModel) => {
if (err) { next(); }
if(result === null) {
//success to register
user.save( );
res.sendStatus(201);
next();
} else {
res.status(401).send('username is taken');
}
});
}
I think that the problem is in the server side. I tried sending different responses in json format, but still nothing. Any ideas?

MEAN - Angular routes over-riding NodeJS routes

I'm trying to restrict access to the Client side Angular app via PassportJS.
Basically i'm trying to route anyone trying to access the app to redirect to the authentication provider to login. But it appears the angular routes override the NodeJS Express routes.
So if i go to '/' it'll just load the angular app and not redirect them. This is the same case for every route that uses the same route as the angular routes.
server.js snippet:
The following code should redirect everyone to log into facebook. but instead it just loads the angular index page.
function checkAuthentication(req,res,next){
if(req.isAuthenticated()){
//if user is looged in, req.isAuthenticated() will return true
console.log("/ " + true);
res.sendFile(path.join(__dirname, 'dist/index.html'));
} else{
console.log("/ " + false);
res.redirect("/api/passport/login/facebook");
}
}
app.get('/*', checkAuthentication ,(req, res) => {
});
Angular index.html snippet:
The index.html page uses the same route as displayed in the express router.
<base href="/">
Let's say i change the index.html base href to use '/app/' like so:
<base href="/app/">
and set up routing in express to redirect logged in users to '/app/' like so:
angular.route example:
app.use("/app", express.static(path.join(__dirname, 'dist')));
function checkAuthentication(req,res,next){
if(req.isAuthenticated()){
//if user is looged in, req.isAuthenticated() will return true
console.log("/app" + true);
res.sendFile(path.join(__dirname, '../../dist/index.html'));
} else{
console.log("/app" + false);
res.redirect("/api/passport/login/facebook");
}
}
router.get('/app', checkAuthentication, (req, res) => {
console.log("approuter hit");
});
module.exports = router;
and go to '/app' directly. It'll still load the angular index.html page and not redirect you to log in. But if you go to '/' it will redirect you to log in.
How do i stop angular over-riding my NodeJS express routes?
UPDATE:
app.route.js snippet:
import { Routes } from '#angular/router';
import { HomeComponent } from './home';
export const ROUTES: Routes = [
{ path: '', component: HomeComponent },
];
You have to implement the AuthGuard and a Authentication service at client side( i.e. Angular) which will act as a communicator between client and server. Also keep a variable like isAuthenticated to track the login status.
AuthGuard :
import { Injectable } from '#angular/core';
import { CanActivate, CanActivateChild, Router } from '#angular/router';
import { AuthenticationService } from './auth.service';
#Injectable()
export class AuthGuard implements CanActivate, CanActivateChild {
constructor(private authService: AuthenticationService, private router: Router) {}
canActivate() : boolean {
console.log('AuthGuard#canActivate called ' + this.authService.isAuthenticated );
return this.checkLoggedIn("random");
}
canActivateChild() : boolean {
return this.canActivate();
}
checkLoggedIn(url: string): boolean {
if (this.authService.isLoggedIn()) {
return true;
}
this.authService.redirectUrl = url;
this.router.navigate(['/login']);
return false;
}
}
AuthenticationService:
import { Injectable } from '#angular/core';
import { Router } from '#angular/router';
import { Http, Response, Headers, RequestOptions } from '#angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { Observable } from 'rxjs/Rx';
import { NgForm } from "#angular/forms";
import { AuthenticationApi } from "../../modules/authentication/authentication-api";
import { IUser } from "app/modules/authentication/user";
var headers = new Headers({ 'Content-Type': 'application/json' });
var options = new RequestOptions({ headers: headers });
#Injectable()
export class AuthenticationService implements AuthenticationApi {
currentUser: IUser;
redirectUrl: string;
changePassoword: () => Observable<any>;
forgotPassowrd: () => Observable<any>;
isAuthenticated = false;
constructor(private router: Router, private http: Http) {
this.currentUser = null
}
isLoggedIn(): boolean {
return !!this.currentUser;
}
logIn(logInUser:any): Observable<any> {
console.log('UserService.signIn: ' + logInUser.userName + ' ' + logInUser.password + ' ' + logInUser.rememberMe);
this.isAuthenticated = true;
this.currentUser = {
userName: logInUser.userName
}
return this.http.post('http://localhost:3000/auth/login',
JSON.stringify(logInUser),
options
)
.map((resp: Response) => resp.json())
.catch(this.handleError);
//return Observable.of({}).delay(2000);
// return Observable.of({}).delay(2000).flatMap(x=>Observable.throw('Invalid User Name and/or Password'));
}
register(registerUser:any): Observable<any> {
this.isAuthenticated = true;
console.log(registerUser);
return this.http.post('http://localhost:3000/auth/register',
JSON.stringify(registerUser),
options
)
.map((resp: Response) => resp.json())
.catch(this.handleError);
//this.router.navigate(['/signin']);
//return Observable.of({}).delay(2000);
}
connectWithFacebook() :Observable<any> {
this.isAuthenticated = true;
//return Observable.of({}).delay(2000);
return this.http.get('http://localhost:3000/auth/facebook')
.map((resp: Response) => resp.json())
.catch(this.handleError);
}
connectWithGoogle() :Observable<any> {
this.isAuthenticated = true;
//return Observable.of({}).delay(2000);
return this.http.get('http://localhost:3000/auth/google')
.map((resp: Response) => resp.json())
.catch(this.handleError);
}
handleError(error: any) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
logOut(): Observable<any>{
this.isAuthenticated = false;
this.currentUser = null;
this.router.navigate(['/login']);
return Observable.of({})
}
}
AuthenticationApi: Common method to communicate
import { Observable } from 'rxjs';
export abstract class AuthenticationApi {
logIn : (loginUser:any) => Observable<any>;
logOut : () => Observable<any>;
register : (registerUser:any) => Observable<any>;
connectWithFacebook : () => Observable<any>;
connectWithGoogle : () => Observable<any>;
changePassoword : () => Observable<any>;
forgotPassowrd : () => Observable<any>;
}

Vue-router beforeRouteEnter Vue-Resource request

I have used this link as a reference to make a request before entering a route:
https://router.vuejs.org/en/advanced/data-fetching.html
import Vue from 'vue'
import VueResource from 'vue-resource'
Vue.use(VueResource)
function getCities () {
return Vue.http({
method: 'GET',
url: process.env.base_url + 'cities'
})
}
export default {
data () {
return {
cities: []
}
},
beforeRouteEnter (to, from, next) {
getCities((err, cities) => {
if (err) {
next(false)
} else {
next(vm => {
vm.cities = cities.data
})
}
})
},
watch: {
$route () {
this.cities = []
getCities((err, cities) => {
if (err) {
this.error = err.toString()
} else {
this.cities = cities.data
}
})
}
}
However it doesn't seem to be working for me. I have tested this code and the request is successfully being made. However the result is not being returned. Currently, the request itself is being returned from the function, but I cannot show it in the beforeRouteEnter callback where it supposedly should assign it to vm.cities neither in the watch $route section.
Any help/opinion is appreciated.
The Vue.http method returns a promise, so the code should read:
beforeRouteEnter (to, from, next) {
getCities().then(response => {
next(vm => vm.cities = response.body)
}
}

Call server-side function from ReactJS component

I'm trying to implement a payments system in my ReactJS app that requires server-side code.
I have several questions:
How do you connect a ReactJS app so it can communicate with server-side code?
How would you set up a function in the server-side code?
How would you call that function from a component in a ReactJS app?
For reference, I'm trying to integrate Stripe subscriptions. They give server-side code examples for Node, PHP, etc.
FYI: I am not trying to set up server-side rendering. When you search for server-side code in reference to ReactJS, that's just about all that comes up.
EDIT: I'm particularly interested in a NodeJS solution. I'm also using Webpack.
Just in case, it is helpful to you... I have a React UI that triggers video processing on a Django backend (I mainly use GraphQL through Apollo Client to trigger my server side functions and REST framework when file transfers are involved).
Is REST an option for you?
The middleware I use for file transfers for example:
const SERVER_URL = process.env.SERVER_URL;
const fileTransferApi = (payload) => {
const { authenticated, token, endpoint, body, contentType, method } = payload;
let config = {};
if (authenticated) {
if (token) {
config = {
method,
headers: {
'Content-Type': contentType,
Authorization: `Bearer ${token}`
},
body
};
} else {
throw new Error('No token saved!');
}
}
return fetch(`${SERVER_URL}/api/rest/v1/${endpoint}`, config)
.then((response) =>
response.text().then((text) => ({ text, response }))
).then(({ text, response }) => {
if (!response.ok) {
return Promise.reject(text);
}
return text;
}).catch((err) => console.log(err));
};
export const FILE_TRANSFER_API = Symbol('FILE_TRANSFER_API');
export default () => (next) => (action) => {
const fileTransferApiAction = action[FILE_TRANSFER_API];
if (typeof fileTransferApiAction === 'undefined') {
return next(action);
}
const { payload, types } = fileTransferApiAction;
const [, successType, errorType] = types;
return fileTransferApi(payload).then(
(response) =>
next({
type: successType,
payload: {
text: response,
message: 'ok'
}
}),
(error) => next({
type: errorType,
payload: {
error: error.message || 'There was an error.'
}
})
);
};
My store (I use Redux):
import { createStore, compose, applyMiddleware } from 'redux';
import { routerMiddleware } from 'react-router-redux';
import ReduxThunk from 'redux-thunk';
import ApolloClientSingleton from '../network/apollo-client-singleton';
import fileTransferApi from '../middlewares/fileTransferApi';
import reducer from './reducers';
export default class Store {
constructor(history, initialState = {}) {
this.data = createStore(
reducer,
initialState,
compose(
applyMiddleware(
fileTransferApi,
ReduxThunk.withExtraArgument(ApolloClientSingleton),
routerMiddleware(history),
ApolloClientSingleton.middleware()
),
typeof window === 'object' && typeof window.devToolsExtension !== 'undefined'
? window.devToolsExtension() : (f) => f
)
);
}
}
In my actions:
export const windowsDownload = (authenticated, token) => ({
[FILE_TRANSFER_API]: {
types: [WINDOW_DOWNLOAD_REQUEST, WINDOW_DOWNLOAD_SUCCESS, WINDOW_DOWNLOAD_FAILURE],
payload: {
endpoint: 'file_transfer/download/windows',
contentType: 'text/csv',
method: 'get',
body: null,
authenticated,
token
}
}
});
This REST setup enables me to send requests (POST video, GET csv...) from my React UI to my Django server. Can't you set up some REST calls between your app and your server?

Cannot read property 'messages' of undefined

I am getting the following error when returning from a http service and attempting to push to response onto an array :
Cannot read property 'messages' of undefined
This is my chat.component.ts file :
import { Component, OnInit, OnDestroy } from '#angular/core';
import { ChatService } from './chat.service';
#Component({
selector: 'chat-component',
template: `
<div *ngIf="messages">
<div *ngFor="let message of messages">
{{message.text}}
</div>
</div>
<input [(ngModel)]="message" /><button (click)="sendMessage()">Send</button>
`,
providers: [ChatService]
})
export class ChatComponent implements OnInit, OnDestroy {
messages = [];
connection;
message;
loading;
constructor(private chatService: ChatService) { }
sendMessage() {
this.chatService.sendMessage(this.message);
this.message = '';
}
ngOnInit() {
this.chatService.initPlaylist().subscribe(tracks => {
tracks.forEach(function(item) {
this.messages.push({
message: item.trackID,
type: "new-message"
});
});
})
this.connection = this.chatService.getMessages().subscribe(message => {
this.messages.push(message);
})
}
ngOnDestroy() {
this.connection.unsubscribe();
}
}
This is my chat.service.ts
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Rx';
import * as io from 'socket.io-client';
#Injectable()
export class ChatService {
private url = 'http://localhost:1337';
private socket;
constructor(private http: Http) {
}
sendMessage(message) {
this.socket.emit('add-message', message);
}
initPlaylist() {
return this.http.get(this.url + '/playlist')
.map(this.extratData)
.catch(this.handleError);
}
getMessages() {
let observable = new Observable(observer => {
this.socket = io(this.url);
this.socket.on('message', (data) => {
observer.next(data);
});
return () => {
this.socket.disconnect();
};
})
return observable;
}
private extratData(res: Response) {
let body = res.json();
return body || {};
}
private handleError(error: Response | any) {
// In a real world app, we might use a remote logging infrastructure
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
}
I currently have a form on the front end, in which users can add a message, this is then pushed onto this.messages and through socket.io sent out to all connected sockets.
What I am now doing is storing messages in a mongodb via an express app using mongoose.
On page load, I would like to retrieve these messages from the document store, and push them onto this.messages - so the view is updated with previous messages, then socket.io should take over on new messages, adding them to the array.
As this is an initial call, once on load, I am not using socket.io to grab these, instead I have an api route setup through express, returning json that looks as follows :
[
{
"_id": "58109b3e868f7a1dc8346105",
"trackID": "This is my message...",
"__v": 0,
"status": 0,
"meta": {
"played": null,
"requested": "2016-10-26T12:02:06.979Z"
}
}
]
However when I get to this section of code within chat.component.ts, everything breaks down with the previously mentioned error..
this.chatService.initPlaylist().subscribe(tracks => {
tracks.forEach(function(item) {
this.messages.push({
message: item.trackID,
type: "new-message"
});
});
})
I using Angular 2, Socket.io, ExpressJS and MongoDB.
don't use function () use instead () => (arrow function) for this.... to keep pointing to the local class instance
tracks.forEach((item) => {
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Resources