I have written a authentication service to authenticate user name and password in a Login Page. The code below is the service.
public login(credentials) {
if (credentials.username === null || credentials.password === null) {
return Observable.throw("Please insert credentials");
} else {
let apiURL = 'http://localhost/timeclock/api/login?usercode=' + credentials.username +
'&password=' + credentials.password ;
return Observable.create(observer => {
this.http.get(apiURL).map(res => res.json()).subscribe(data => {
if (data.success === 'true')
{
this.currentUser.name = data.data.user_name;
this.currentUser.email = data.data.user_email;
observer.next(true);
observer.complete();
} else {
observer.next(false);
observer.complete();
}
});
});
}
}
When the user name and password is submitted, the URL is correctly called with the right parameters.
The http call takes very long time to complete. Also, no response is returned.
It takes only two or three seconds to get the response when I call the URL with the same parameters in the browser.
Any idea on how to fix this?
You don't need to create a new Observable you can refactor like this.
public login(credentials) : Observable<boolean> {
if (credentials.username === null || credentials.password === null) {
return Observable.throw("Please insert credentials");
} else {
let apiURL = 'http://localhost/timeclock/api/login?usercode=' + credentials.username +
'&password=' + credentials.password ;
return this.http.get(apiURL).map(res => res.json())
.map(data =>
{
if(data.success){
this.currentUser.name = data.data.user_name;
this.currentUser.email = data.data.user_email;
return true;
}else{
return false;
}
});
}
}
Related
I have an application that was working doing http.get requests on an Ubuntu virtual machine hosting a postgres DB and an API using Hapi/node. The VM disk become corrpupted and following the rebuild, the http.get now throws an XMLHttpRequest error. However, a test programme doing the same request works fine and a test GET using POSTMAN works fine as well. I'm stumped as to why this is the case.
The code that is throwing the error is as follows (the getScores() function):
import 'package:noxo/functions.dart' as func;
import 'dart:convert';
import 'package:http/http.dart' as http;
class DataManager {
Map<dynamic, dynamic> results = {}; // Return values from DB parameter query
double difficulty = 5; // Level of difficulty (1- easiest to 5-hardest)
// Address of API for data requests
final _apiAddress = 'http://192.168.1.201:4044/';
bool _httpAvailable = true; // Assume that http is available
int getHumanScore() {
func.debugPrint('httpAvailable is $_httpAvailable');
if (_httpAvailable && results.isNotEmpty) {
func.debugPrint('Returning HUMAN score');
return results['humanwin'];
} else {
return 0;
}
}
int getDrawScore() {
if (_httpAvailable && results.isNotEmpty) {
return results['draws'];
} else {
return 0;
}
}
int getComputerScore() {
if (_httpAvailable && results.isNotEmpty) {
return results['computerwin'];
} else {
return 0;
}
}
void setDifficulty(double value) {
func.debugPrint('Set difficulty = $value');
difficulty = value;
}
double getDifficulty() {
func.debugPrint('Get difficulty is $difficulty');
return difficulty;
}
void getScores(Function() updateScores) async {
if (_httpAvailable) {
// If we haven't had a previous http error - read the scores
try {
dynamic _parsedAddress = Uri.parse(_apiAddress);
final response = await http.get(_parsedAddress);
func.debugPrint(
'doing getScores. Address = $_apiAddress. statusCode = ${response.statusCode}');
Map decodedResponse = jsonDecode(response.body) as Map;
if (response.statusCode == 200) {
func.debugPrint('getScores response: $decodedResponse');
results = decodedResponse;
updateScores(); // Update scores on main.dart
} else {
throw Exception('Unable to fetch products from the REST API');
}
} catch (e) {
func.debugPrint('getScores. Error is $e.');
_httpAvailable = false; // Disable http checks because we had an error
results =
{}; // Return an empty map if the internet connection is not available
}
}
}
// Put data about scores into the database
Future<void> putScores(String resultPath) async {
// Only try to put the scores if http is available
if (_httpAvailable) {
try {
String address = '$_apiAddress$resultPath';
func.debugPrint('http address: $address');
var response = await http.post(Uri.parse(address));
func.debugPrint('http response: ${response.body.toString()}');
// Check for sucess, throw an error if it didn't work
if (response.statusCode == 200 ||
response.statusCode == 201 ||
response.statusCode == 204) {
return;
} else {
throw Exception(
'Unable to update results from the REST API. Status Code: ' +
response.statusCode.toString());
}
} catch (e) {
_httpAvailable = false; // Disable http requests
}
}
}
}
The output when "getScores()" is called is:
getScores. Error is XMLHttpRequest error..
The Hapi interface code is as follows:
'use strict';
const Hapi = require('#hapi/hapi');
const { options } = require('#hapi/hapi/lib/cors');
const Inert = require('#hapi/inert');
const HapiPostgresConnection = require('hapi-postgres-connection');
const path = require('path');
const debug = true;
const init = async () => {
const server = Hapi.server({
port: 4044,
host: '192.168.1.201',
//host: '0.0.0.0',
routes: {
cors: false
/*
{
origin: ['192.168.*'], // an array of origins or 'ignore'
headers: ['Authorization'], // an array of strings - 'Access-Control-Allow-Headers'
exposedHeaders: ['Accept'], // an array of exposed headers - 'Access-Control-Expose-Headers',
additionalExposedHeaders: ['Accept'], // an array of additional exposed headers
maxAge: 60,
credentials: false // boolean - 'Access-Control-Allow-Credentials'
*/
}
});
await server.register([{
plugin: HapiPostgresConnection
},
{
plugin: Inert
}]);
server.route({
method: 'GET',
path: '/',
handler: async function (request, h) {
let id = '1';
let statement = `SELECT * FROM scores WHERE id = ${id}`;
debugPrint(`Doing GET. Statement = ${statement}`);
try {
const result = await request.pg.client.query(statement);
debugPrint(`After GET. Result = ${result}. Response = ${h.response()}`);
return h.response(result.rows[0]);
} catch (err) {
console.log(err);
}
}
});
server.route({
method: 'GET',
path: '/noxo',
handler: (request, h) => {
return h.file('/home/mike/programming/noxo/index.html');
}
});
server.route({
method: 'GET',
path: '/fwebtest',
handler: (request, h) => {
return h.file('index.html', options [{confine: false}]);
},
options: {
files: {
relativeTo: path.join(__dirname, 'fwebtest')
},
},
});
server.route({
method: 'GET',
path: '/webtest',
handler: (request, h) => {
return h.file('./webtest/index.html', options [{confine: false}])
}
});
server.route({
method: ['PUT', 'POST'],
path: '/',
handler: async function (request, h) {
let statement = 'update scores set';
var jsonData = request.payload;
if (jsonData.hasOwnProperty('id')) {
delete jsonData.id;
}
var first = true
for (var key of Object.keys(jsonData)) {
if (!first) {
statement = statement + ",";
}
statement = statement + ' ' + key + ' = ' + jsonData[key];
first = false;
}
statement = statement + ' where id = 1'
debugPrint(`Doing PUT. Statement = ${statement}`);
try {
const result = await request.pg.client.query(statement);
return h.response(result.rows[0]);
} catch (err) {
console.log(err);
}
}
});
await server.start();
console.log('Server running on %s', server.info.uri);
};
function buildStatement(element, index, array) {
if (index != 'id') {
statement = statement + index + ' = ' + value + ' ';
}
return this;
}
function debugPrint(value){
if (debug == true){
console.log(value);
}
}
process.on('unhandledRejection', (err) => {
console.log(err);
process.exit(1);
});
init();
The test dart programme, which works, is as follows:
import 'dart:convert';
import 'package:http/http.dart' as http;
// Address of API for data requests
final _apiAddress = 'http://192.168.1.201:4044/';
// Global variables
bool _httpAvailable = true; // Has http conect worked? Assume yes.
const bool debug = true; // Global bebug print variable.
void main() async {
// Get the scores from the API
Map scores = await _getScores();
}
// Function to get the scores using http command
Future<Map> _getScores() async {
debugPrint('Doing GET...');
dynamic response;
Map decodedResponse = {};
try {
dynamic _parsedAddress = Uri.parse(_apiAddress);
response = await http.get(_parsedAddress);
decodedResponse = jsonDecode(response.body) as Map;
} catch (e) {
debugPrint('getScores. Error is $e.');
_httpAvailable = false; // Disable http checks because we had an error
decodedResponse =
{}; // Return an empty map if the internet connection is not available
}
if (response.statusCode == 200) {
debugPrint('response.body:');
debugPrint(response.body);
debugPrint('GET successful... code: ' + response.statusCode.toString());
debugPrint(' ');
return decodedResponse;
} else {
throw Exception('Unable to fetch products from the REST API. Error code: ' +
response.statusCode.toString());
}
}
debugPrint(String message) {
if (debug == true) {
print(message);
}
}
The output from this programme is:
D:\Sync\Programming\Flutter\http_get>dart run
Building package executable...
Built http_test:http_test.
Doing GET...
response.body:
{"id":1,"humanwin":3,"draws":0,"computerwin":0}
GET successful... code: 200
The POSTMAN results are:
I assume that this is a CORS issue from what I have read about XMLHttpRequest errors, but believe I have disabled CORS in the Hapi interface. The application class, test programme and POSTMAN test all pre-date the Ubuntu VM rebuild so the only thing that has changed is the VM. The Hapi code was backed up so that shouldn't have changed either, although I can't quite remember when I took the last backup.
Does anyone have any ideas about why the test programme and POSTMAN work, but my DataManager class in my application doesn't?
In the routes definition for Hapi, cors needs to be set to true as below.
const server = Hapi.server({
port: xxxx,
host: 'xxx.xxx.xxx.xxx',
routes: {
cors: true
}
});
I am working in my Ionic Project and my API is getting called 2 times. I am not able to get why my API is getting called 2 times.
This is my productdetails.html:
<ion-col *ngIf="hassizenot && product.out_of_stock == 0" style="padding: 0px;">
<button class="mybtn11" (click)="addtocartnew(product)" ion-button small>
Add to Cart
</button>
</ion-col>
This is my productdetails.ts:
addtocartnew(detailsp)
{
this.storage.get("ID").then((val) =>
{
if(val)
{
if(detailsp.SelectedSize)
{
let usercartnewdetails = {
user_id: val,
product_id: detailsp.id,
size: detailsp.SelectedSize,
};
this.restProvider.usercartproducts(usercartnewdetails, 'user_cart/'+detailsp.id+'/'+val+'/'+detailsp.SelectedSize).subscribe((data) => {
if (data) {
console.log("One");
this.responseEdit = data;
console.log(this.responseEdit.msg);
if (this.responseEdit.status === 'success') {
this.presentToast(detailsp.product_name);
}
else{
this.presentToasterror();
}
}
});
}
else
{
let usercartnewdetails = {
user_id: val,
product_id: detailsp.id,
};
this.restProvider.usercartproducts(usercartnewdetails, 'user_cart/'+detailsp.id+'/'+val).subscribe((data) => {
if (data) {
console.log("Two");
this.responseEdit = data;
console.log(this.responseEdit.msg);
if (this.responseEdit.status === 'success') {
this.presentToast(detailsp.product_name);
}
else{
this.presentToasterror();
}
}
});
}
}
});
}
This is my Service:
usercartproducts(credentials, type) {
var headers = new HttpHeaders();
headers.append('Access-Control-Allow-Origin' , '*');
headers.append('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT');
headers.append('Accept','application/json');
headers.append('Content-Type','application/json');
headers.append('Access-Control-Allow-Credentials','true');
headers.append('Access-Control-Allow-Headers','Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With');
return this.http.post(apiUrl + type, credentials, {headers: headers});
}
In my ts file, I am running the API for adding the products to the cart and it is showing only one response in the console but it is calling 2 times because it is adding the 2 times the product and in the network in the chrome, it is calling 2 times.
Any help is much appreciated.
Just Try This In Your Service:
usercartproducts(credentials, type) {
var headers = new HttpHeaders();
headers.append('Access-Control-Allow-Origin' , '*');
headers.append('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT');
headers.append('Accept','application/json');
headers.append('Content-Type','application/x-www-form-urlencoded');
headers.append('Access-Control-Allow-Credentials','true');
headers.append('Access-Control-Allow-Headers','Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With');
let v = new FormData();
for(var k in credentials)v.append(k,credentials[k]);
return this.http.post(apiUrl + type, v, {headers: headers});
}
This solved my problem.
because you implement yout API twice and your If condition must be wrong
change your ts like this.
addtocartnew(detailsp) {
if (detailsp.SelectedSize) {
this.storage.get("ID").then((val) => {
if (val) {
let usercartnewdetails = {
user_id: val,
product_id: detailsp.id,
size: detailsp.SelectedSize,
};
this.restProvider.usercartproducts(usercartnewdetails, 'user_cart/' +
detailsp.id + '/' + val + '/' + detailsp.SelectedSize).subscribe((data) => {
console.log("One");
this.responseEdit = data;
console.log(this.responseEdit.msg);
if (this.responseEdit.status === 'success') {
this.presentToast(detailsp.product_name);
}
else {
this.presentToasterror();
}
}
});
}
})
}
else {
this.storage.get("ID").then((val) => {
if (val) {
let usercartnewdetails = {
user_id: val,
product_id: detailsp.id,
};
this.restProvider.usercartproducts(usercartnewdetails, 'user_cart/' +
detailsp.id + '/' + val).subscribe((data) => {
if (data) {
console.log("Two");
this.responseEdit = data;
console.log(this.responseEdit.msg);
if (this.responseEdit.status === 'success') {
this.presentToast(detailsp.product_name);
}
else {
this.presentToasterror();
}
}
});
}
})
}
}
change as per your condition and it will work.
I am trying learn nodejs and stumble upon this error
callback(null, removed);
TypeError: callback is not a function
It is a Steam trade bot, so when it send me an offer, I accept it but after that it crashes. What is wrong?
exports.removeOweNoTitle = (user, callback) => {
let file = 'data/users/' + user + '.json';
if(fs.existsSync(file)) {
let read = fs.createReadStream(file);
let data = "";
read.on('data', (chunk) => {
data += chunk;
});
read.on('end', () => {
let json;
try {
json = JSON.parse(data);
} catch(error) {
return callback(error);
}
let owe = {};
if(json.owe)
owe = json.owe;
else {
callback(null, 0);
return;
}
let removed = 0;
for(let game in owe) {
if(owe[game]) {
removed += owe[game];
owe[game] = 0;
}
}
let write = fs.createWriteStream(file, {flags: 'w'});
exports.clearNotifications(user, () => {
write.write(JSON.stringify(json), (error) => {
if(error)
return callback(error);
write.end();
});
return;
});
write.write(JSON.stringify(json), (error) => {
if(error)
return callback(error);
write.end();
});
write.on("finish", (callback, error) => {
callback(null, removed); //tady nebyl deklarován callback chyběl
});
});
} else {
generateUserFile(user);
callback(new Error('User\'s file is not defined!'), null);
}
}
I am using Jwt tokens for authentication and using a interceptor for adding access token to the requests.I have a getToken() method which is checking for token's validity and calling the service for getting new set of tokens. The method is returning promise but the requests are taking the promise before it gets completed and failing to get the updated token.
Below is my code:
export class TokenService {
refresh = false;
constructor(public injector: Injector) {
}
public getToken(): string | Promise<string> {
const jwtHelper = new JwtHelperService();
let token = localStorage.getItem('token');
let refreshToken = localStorage.getItem('refreshToken');
if (!token || !refreshToken) {
return null;
}
if (jwtHelper.isTokenExpired(token)) {
if (jwtHelper.isTokenExpired(refreshToken)) {
return null;
} else {
let tokenPromise;
if (!this.refresh) {
this.refresh = true;
tokenPromise = this.promiseFromObservable(this.getTokenService(localStorage.getItem('refreshToken')));
}
return tokenPromise;
}
} else {
return token;
}
}
getTokenService(refreshToken: string) {
let http = this.injector.get(HttpClient);
const httpOptions = {
headers: new HttpHeaders({
'Authorization': 'Bearer ' + refreshToken
})
};
return http.post<Tokens>(location.origin + '/LiveTime/services/v1/auth/tokens?locale=en', null, httpOptions);
}
promiseFromObservable(o): Promise<string> {
return new Promise((resolve, reject) => o.subscribe((token: Tokens) => resolve(token.token),reject(), err => { console.log(err); return null; }))
.then((token: Tokens) => {
localStorage.setItem('token', token.token);
localStorage.setItem('refreshToken', token.refreshToken);
this.refresh = false;
return token.token;
},
err => { console.log(err); return null; }
)
.catch((error) => { console.log(error);reject();
});
}
}
Can someone tell me what is wrong in this code?
I'm integrating Stripe payments with Angular2 (actually Ionic but the code is the same)
the call to Stripe.card.createToken is successful and returns a token
but in stripeResponseHandler which is an async callback, I cannot access any of the "this" variables. for example I cannot set this.amount = 10 and I cannot call this._http.post
how can I access the "this" variables ? I'm trying to http post the token and the amount to an API to make the payment
constructor(private _navController: NavController,
private _http: Http) { }
submitPayment() {
Stripe.setPublishableKey(this.key);
this.card = new Card();
this.card.number = this.cardNumber;
this.card.cvc = this.cardCVC;
this.card.exp_month = this.cardExpMonth;
this.card.exp_year = this.cardExpYear;
this.card.address_zip = this.cardAddressZip;
try {
Stripe.card.createToken(this.card, this.stripeResponseHandler);
}
catch (e) {
alert(e.message);
}
// Prevent the form from being submitted:
return false;
}
stripeResponseHandler(status, response) {
if (response.error) { // Problem!
alert(response.error);
} else { // Token was created!
// Get the token ID:
alert(response.id);
try {
this.amount = 10;
let payment = new Payment();
payment.token = response.id;
payment.amount = this.amount;
let body = JSON.stringify(payment);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
this._http.post(this.url, body, options)
.map(res => res.json())
.catch(this.handleError);
}
catch (e) {
alert(e.message);
}
}
}
handleError(error: Response) {
// may send the error to some remote logging infrastructure
// instead of just logging it to the console
console.error(error);
alert('error' + error.text + " " + error.statusText);
return Observable.throw(error.json().error || 'Server error');
}
If you just pass the function reference, then JavaScript doesn't keep the this reference. You have to take care of this explicitely:
Instead of
Stripe.card.createToken(this.card, this.stripeResponseHandler);
use
Stripe.card.createToken(this.card, (status, person) => this.stripeResponseHandler(status, person));
See also https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions
or
Stripe.card.createToken(this.card, this.stripeResponseHandler.bind(this));