Related
I want to save my all response file with their request name. So I am finding a solution where I get the request name. Newman CLI is a command-line tool to run the postman collection but I read out all documentation and not get any solution for the same.
const newman = require('newman'),
fs = require('fs');
var envPath = "./env/POP.postman_environment.json";
var res;
newman.run({
collection: require('./collection/login_HHS.postman_collection.json'),
reporters: 'cli',
environment:require(`${envPath}`),
exportEnvironment: `${envPath}`
}).on('beforeRequest', function (error, args) {
if (error) {
console.error(error);
} else {
fs.writeFile('request.txt', args.request.body.raw, function (error) {
if (error) {
console.error(error);
}
});
}
}).on('request', function (error,args) {
if (error) {
console.error(error);
}
else {
console.log("args ====== "+args.response.stream)
res = args.response.stream;
}
}).on('test', function (error, summary) {
if (error) {
console.error(error);
}
else {
const fileName = Math.random().toString(36).substring(7) + '-foo.txt';
fs.writeFile(fileName, res, function (error) {
if (error) {
console.error(error);
}
});
}
});
I create a ganache cli and initialize my accounts to have ethers using
ganache-cli -h "159.89.119.189" -a 3 -e "1000000000000000000000000000" --secure -u 0 -u 1 -u 2 -s 20
but after a couple of minutes, all accounts on the network are 0.
I'm not able to run any transactions or call contracts again.
A DApp i created connects to this private network
This is my app.js
App = {
web3Provider: null,
contracts: {},
account: 0x0,
coinbase: 0x0,
coinbase_amount: 0,
loading: false,
init: function () {
return App.initWeb3();
},
initWeb3: function () {
// initialize web3
if (typeof web3 !== 'undefined') {
//reuse the provider of the Web3 object injected by Metamask
App.web3Provider = web3.currentProvider;
} else {
//create a new provider and plug it directly into our local node
//App.web3Provider = new Web3.providers.HttpProvider('http://localhost:8545');
App.web3Provider = new Web3.providers.HttpProvider('http://159.89.119.189:8545');
}
web3 = new Web3(App.web3Provider);
App.getCoinbase();
return App.initContract();
},
hostname: function () {
return window.location.origin;
},
setAccount: function (address) {
App.account = address;
},
displayAccountInfo: function () {
// console.log(App);
if (App.account != 0) {
toastr.remove();
toastr.info('Getting Account Info', {timeOut: 300000});
$('#account').text(App.account);
App.getBalance();
}
},
getBalance: function() {
web3.eth.getBalance(App.account, function (err, balance) {
if (err === null) {
if(web3.fromWei(balance, "ether") == 0){
setTimeout(App.getBalance(), 60000);
} else {
console.log(web3.fromWei(balance, "ether"));
toastr.remove();
$('#accountBalance').text(web3.fromWei(balance, "ether") + " ETH");
}
}
})
},
getCoinbase: function () {
web3.eth.getCoinbase(function (err, account) {
if (err === null) {
App.coinbase = account;
// $('#account').text(account);
web3.eth.getBalance(account, function (err, balance) {
if (err === null) {
App.coinbase_amount = web3.fromWei(balance, "ether").toNumber();
console.log(App.coinbase, App.coinbase_amount)
}
})
}
});
},
transfer: function() {
web3.personal.unlockAccount(App.coinbase, "pass12345", 100000, function (err, result) {
console.log(result)
console.log(err)
web3.personal.unlockAccount(App.account, "pass#123", 100000, function (err, result) {
web3.eth.sendTransaction({
from: App.coinbase,
to: App.account,
value: web3.toWei(10, "ether")
}, function (err, result) {
if (err == null) {
console.log("sent money");
console.log(result)
console.log(err)
web3.eth.getBalance(App.account, function (err, balance) {
if (err === null) {
console.log(web3.fromWei(balance, "ether") + " ETH");
}
})
}
else {
console.log(err);
}
})
});
});
},
register: function () {
let email = $('#inputEmail');
let fname = $('#inputFname');
let lname = $('#inputLname');
let password = $('#inputPassword');
let btnRegister = $('#btnRegister');
if (email.val() == "" || fname.val() == "" || lname.val() == "" || password.val() == "") {
toastr.error('Please fill all fields');
return false;
}
btnRegister.attr("disabled", 'disabled');
web3.personal.newAccount("pass#123", function (err, data) {
let address = data;
if (err === null) {
let postData = {
email: email.val(),
fname: fname.val(),
lname: lname.val(),
password: password.val(),
address: data
}
$.ajax({
method: "POST",
url: App.hostname() + "/register",
data: postData,
success: function (data) {
console.log(data)
if (data.status == "success") {
web3.personal.unlockAccount(address, "pass#123", 1000, function (err, result) {
web3.eth.sendTransaction({
from: App.coinbase,
to: address,
value: web3.toWei(10, "ether")
}, function (err, result) {
if (err == null) {
console.log("sent money");
console.log(result)
web3.eth.getBalance(App.coinbase, function (err, balance) {
if (err === null) {
console.log("coinbase "+web3.fromWei(balance, "ether") + " ETH");
}
})
web3.eth.getBalance(address, function (err, balance) {
if (err === null) {
console.log(web3.fromWei(balance, "ether") + " ETH");
}
})
}
else {
console.log(err);
}
toastr.success("Success.");
window.location.href = App.hostname();
})
});
} else {
toastr.error(data.data);
}
btnRegister.attr("disabled", false);
},
error: function (err) {
toastr.error('Error Registering');
btnRegister.attr("disabled", false);
}
});
} else {
toastr.error('Error Registering');
btnRegister.attr("disabled", false);
return false;
}
})
},
login: function () {
let email = $('#inputEmail');
let password = $('#inputPassword');
let btnLogin = $('#btnLogin');
if (email.val() == "" || password.val() == "") {
toastr.error('Please fill all fields');
return false;
}
btnLogin.attr("disabled", 'disabled');
let postData = {
email: email.val(),
password: password.val(),
}
$.ajax({
method: "POST",
url: App.hostname() + "/login",
data: postData,
success: function (data) {
console.log(data)
if (data.status == "success") {
toastr.success("Success.");
window.location.href = App.hostname();
} else {
toastr.error(data.data);
}
btnLogin.attr("disabled", false);
},
error: function (err) {
toastr.error('Error Registering');
btnLogin.attr("disabled", false);
}
});
},
initContract: function () {
$.getJSON('Chainlist.json', function (chainListArtifact) {
// get the contract artifact file and use it to instantiate a truffle contract abstraction
App.contracts.ChainList = TruffleContract(chainListArtifact);
// set the provider for our contracts
App.contracts.ChainList.setProvider(App.web3Provider);
// listen to events
App.listenToEvents();
// retrieve the article from the contract
return App.reloadArticles();
});
},
reloadArticles: function () {
// avoid re-entry
if (App.loading) {
return
}
App.loading = true
// refresh account information because the balance might have changed
App.displayAccountInfo();
var chainListInstance;
App.contracts.ChainList.deployed().then(function (instance) {
chainListInstance = instance;
return chainListInstance.getArticlesForSale();
}).then(function (articleIds) {
$('#articlesRow').empty();
for (var i = 0; i < articleIds.length; i++) {
var articleID = articleIds[i];
chainListInstance.articles(articleID.toNumber())
.then(function (article) {
App.displayArticle(article[0], article[1], article[3], article[4], article[5], article[6])
});
}
App.loading = false;
}).catch(function (err) {
console.error(err.message);
App.loading = false;
});
},
sellArticle: function () {
// retrieve the detail of the article
var _article_name = $('#article_name').val();
var _description = $('#article_description').val();
var _price = web3.toWei(parseFloat($('#article_price').val() || 0), "ether");
const file = $('#article_image').prop('files')[0];
if ((_article_name.trim() == '') || (_price == 0)) {
// nothing to sell
return false;
}
const name = (+new Date()) + '-' + file.name;
const metadata = {
contentType: file.type
};
let ref = firebase.storage().ref();
const task = ref.child(name).put(file, metadata);
toastr.info('Processing.....', {timeOut: 30000});
task.then((snapshot) => {
const _image_url = snapshot.downloadURL;
console.log(_image_url);
web3.personal.unlockAccount(App.account, "pass#123", 1000, function (err, result) {
console.log(result);
console.log(err);
App.contracts.ChainList.deployed().then(function (instance) {
return instance.sellArticle(_article_name, _description, _price, _image_url, {
from: App.account,
gas: 500000
});
}).then(function (result) {
console.log(result);
$('#article_name').val("");
$('#article_description').val("");
$('#article_price').val("");
$('#article_image').val("");
}).catch(function (err) {
console.error(err);
});
});
}).catch((error) => {
console.error(error);
});
},
displayArticle: function (id, seller, name, description, price, image_url) {
var articlesRow = $('#articlesRow');
var etherPrice = web3.fromWei(price, "ether");
// retrieve the article template and fill it
var articleTemplate = $('#articleTemplate');
articleTemplate.find('.panel-title').text(name);
articleTemplate.find('.article-description').text(description);
articleTemplate.find('.article-price').text(etherPrice);
articleTemplate.find('.btn-image-url').attr('href', image_url);
articleTemplate.find('.btn-buy').attr('data-value', etherPrice);
articleTemplate.find('.btn-buy').attr('data-id', id);
if (seller == App.account) {
articleTemplate.find('.article-seller').text("You");
articleTemplate.find('.btn-buy').hide();
} else {
articleTemplate.find('.article-seller').text(seller);
articleTemplate.find('.btn-buy').show();
}
// buyer
// var buyer = article[1];
// if (buyer == App.account) {
// buyer = "You";
// } else if (buyer == 0x0){
// buyer = "None yet"
// }
// articleTemplate.find('.article-buyer').text(buyer);
// add this article
toastr.clear();
$('#articlesRow').append(articleTemplate.html());
},
// listen to events triggered by the contract
listenToEvents: function () {
App.contracts.ChainList.deployed().then(function (instance) {
instance.LogSellArticle({}, {}).watch(function (error, event) {
if (!error) {
$("#events").append('<li class="list-group-item">' + event.args._name + ' is now for sale</li>');
} else {
console.error(error);
}
App.reloadArticles();
});
instance.LogBuyArticle({}, {}).watch(function (error, event) {
if (!error) {
$('#sellBtn').attr("disabled", false);
$("#events").append('<li class="list-group-item">' + event.args._buyer + ' bought ' + event.args._name + '</li>');
} else {
console.error(error);
}
App.reloadArticles();
});
});
},
// retrieve article price from data-value and process buyArticle function
buyArticle: function () {
event.preventDefault();
// retrieve article Price
toastr.info('Processing.....', {timeOut: 30000});
$(event.target).attr("disabled", 'disabled');
$('#sellBtn').attr("disabled", 'disabled');
var price = parseFloat($(event.target).data('value'));
var articleID = parseFloat($(event.target).data('id'));
web3.personal.unlockAccount(App.account, "pass#123", 1000, function (err, result) {
console.log(result);
console.log(err);
App.contracts.ChainList.deployed().then(function (instance) {
return instance.buyArticle(articleID, {
from: App.account,
value: web3.toWei(price, "ether"),
gas: 500000
}).catch(function (error) {
console.error(error);
})
});
});
}
};
$(function() {
$(window).load(function() {
App.init();
// Initialize Firebase
var config = {
apiKey: "AIzaSyAQp34HzZS_3xckuxcVcsUWgCu8_p7UzxA",
authDomain: "comflo-1518513183870.firebaseapp.com",
databaseURL: "https://comflo-1518513183870.firebaseio.com",
projectId: "comflo-1518513183870",
storageBucket: "comflo-1518513183870.appspot.com",
messagingSenderId: "798445619042"
};
firebase.initializeApp(config);
});
});
Same thing happens when i run a geth private server.
I'm using a node app with express.
I read the document, both on github and Facebook developers docs.
There is only sample, nothing more. No API document.
The code to make a Graph API request is
const infoRequest = new GraphRequest(
'/me',
null,
this._responseInfoCallback,
);
And the callback
_responseInfoCallback(error: ?Object, result: ?Object) {
if (error) {
alert('Error fetching data: ' + error.toString());
} else {
alert('Success fetching data: ' + result.toString());
}
}
And here is the function to make a Graph API request
testRequestGraphAPI(){
const infoRequest = new GraphRequest(
'/me',
null,
this._responseInfoCallback,
);
new GraphRequestManager().addRequest(infoRequest).start();
}
However, I can't find any further document. I have no idea what each parameters do.
The result for these codes above is this.
I also don't know how to get the result.
However, when I try to modify '\me' to 'me?fields=id,name', It failed.
Although I have asked for permission
<LoginButton
publishPermissions={["publish_actions,user_birthday, user_religion_politics, user_relationships, user_relationship_details, user_hometown, user_location, user_likes, user_education_history, user_work_history, user_website, user_managed_groups, user_events, user_photos, user_videos, user_friends, user_about_me, user_status, user_games_activity, user_tagged_places, user_posts, user_actions.video, user_actions.news, user_actions.books, user_actions.music, user_actions.fitness, public_profile, basic_info"]}
onLoginFinished={
(error, result) => {
if (error) {
alert("login has error: " + result.error);
} else if (result.isCancelled) {
alert("login is cancelled.");
} else {
AccessToken.getCurrentAccessToken().then(
(data) => {
meow_accesstoken = data.accessToken
alert(meow_accesstoken.toString())
}
)
}
}
}
onLogoutFinished={() => alert("logout.")}/>
But it does not print out what error, just object Object.
So, the problem is that I don't understand the sample code which Facebook provide with no explanation.
Here is my question that I really need you help me:
First at all, please check the javascript code that I currently looking at?
How to use graph API in react-native-fbsdk to retrieve some user information (example: full name) and successfully display it (use alert) ?
What each parameters in GraphRequest() do ?
What is the structure of error object and result object in _responseInfoCallback ?
SOLUTION
Thanks to #Samuel answer, I have updated my code
testRequestGraphAPI: function(){
const infoRequest = new GraphRequest(
'/me',
{
parameters: {
fields: {
string: 'email,name,first_name,middle_name,last_name' // what you want to get
},
access_token: {
string: meow_accesstoken.toString() // put your accessToken here
}
}
},
this._responseInfoCallback // make sure you define _responseInfoCallback in same class
);
new GraphRequestManager().addRequest(infoRequest).start();
}
And the callback
_responseInfoCallback: function(error: ?Object, result: ?Object) {
alert("meow response");
if (error) {
alert('Error fetching data: ' + error.toString());
console.log(Object.keys(error));// print all enumerable
console.log(error.errorMessage); // print error message
// error.toString() will not work correctly in this case
// so let use JSON.stringify()
meow_json = JSON.stringify(error); // error object => json
console.log(meow_json); // print JSON
} else {
alert('Success fetching data: ' + result.toString());
console.log(Object.keys(result));
meow_json = JSON.stringify(result); // result => JSON
console.log(meow_json); // print JSON
}
}
*Note: For console.log(), you need to use "Debug JS remotely" then open Chrome developer tools to see the log.
Unfortunately the react-native-fbsdk documentation is not updated and the examples do not work well.
I got the same problem and I solved it by try and error.
To solve your problem you'll need to change your GraphRequest adding params and fields to it like this:
<LoginButton
onLoginFinished={
(error, result) => {
if (error) {
alert("login has error: " + result.error);
} else if (result.isCancelled) {
alert("login is cancelled.");
} else {
AccessToken.getCurrentAccessToken().then(
(data) => {
let accessToken = data.accessToken
alert(accessToken.toString())
const responseInfoCallback = (error, result) => {
if (error) {
console.log(error)
alert('Error fetching data: ' + error.toString());
} else {
console.log(result)
alert('Success fetching data: ' + result.toString());
}
}
const infoRequest = new GraphRequest(
'/me',
{
accessToken: accessToken,
parameters: {
fields: {
string: 'email,name,first_name,middle_name,last_name'
}
}
},
responseInfoCallback
);
// Start the graph request.
new GraphRequestManager().addRequest(infoRequest).start()
}
)
}
}
}
onLogoutFinished={() => alert("logout.")}/>
You'll need to enable the Remote JS Debug to see the console.log() info.
https://facebook.github.io/react-native/docs/debugging.html
And probably you need to get some permissions to get more info than names and email so it's a good idea to look the Facebook Graph API Documentation: https://developers.facebook.com/docs/graph-api/overview/
Reference:
https://github.com/facebook/react-native-fbsdk/issues/105#issuecomment-206501550
Here is an example of a custom button if you want to make one :)
FbLoginButton() {
LoginManager
.logInWithReadPermissions(['public_profile'])
.then(function (result) {
if (result.isCancelled) {
alert('Login cancelled');
} else {
AccessToken
.getCurrentAccessToken()
.then((data) => {
let accessToken = data.accessToken
alert(accessToken.toString())
const responseInfoCallback = (error, result) => {
if (error) {
console.log(error)
alert('Error fetching data: ' + error.toString());
} else {
console.log(result)
alert('Success fetching data: ' + result.toString());
}
}
const infoRequest = new GraphRequest('/me', {
accessToken: accessToken,
parameters: {
fields: {
string: 'email,name,first_name,middle_name,last_name'
}
}
}, responseInfoCallback);
// Start the graph request.
new GraphRequestManager()
.addRequest(infoRequest)
.start()
})
}
}, function (error) {
alert('Login fail with error: ' + error);
});
}
Thank you #Samuel.
I finally succeed to get user information from Facebook login because of your help!
But I struggled to figure out how can I get username and email literally from the result object cause I am a newbie in React & Javascript.
P.S. result["name"] is the point because it is object!!
So I added some code to yours for other people like me.
If you don't like using your code, just tell me that.
<LoginButton
onLoginFinished={
(error, result) => {
if (error) {
alert("login has error: " + result.error);
} else if (result.isCancelled) {
alert("login is cancelled.");
} else {
AccessToken.getCurrentAccessToken().then(
(data) => {
let accessToken = data.accessToken
alert(accessToken.toString())
const responseInfoCallback = (error, result) => {
if (error) {
console.log(error)
alert('Error fetching data: ' + error.toString());
} else {
console.log(result)
// Here's my code
alert('Success fetching data: ' + result["name"].toString() +
", " + result["email"].toString());
/*
if(your DB already got this email or something unique) {
// SignIn()
}
// when your DB doesn't have this email
else {
// Do signUp() with this infomation and SignIn()
}
*/
}
}
const infoRequest = new GraphRequest(
'/me',
{
accessToken: accessToken,
parameters: {
fields: {
string: 'email,name,first_name,middle_name,last_name'
}
}
},
responseInfoCallback
);
// Start the graph request.
new GraphRequestManager().addRequest(infoRequest).start()
}
)
}
}
}
onLogoutFinished={() => alert("logout.")}/>
My code was not retriving the user email, if you are having the same problem, just put 'email' in parameter's logInWithPermission
Not Working
LoginManager.logInWithPermissions(['public_profile']).then(...)
Working
LoginManager.logInWithPermissions(['public_profile', 'email']).then(...)
All Function
loginWithFacebook = () => {
LoginManager.logInWithPermissions(['public_profile', 'email']).then(
login => {
if (login.isCancelled) {
console.log('Login Cancelado');
} else {
AccessToken.getCurrentAccessToken().then(
(data) => {
const accessToken = data.accessToken.toString()
this.getInfoFromToken(accessToken)
})
}
},
error => {
console.log('Erro no login ', console.error(error)
)
}
)
}
getInfoFromToken = token => {
const PROFILE_REQUEST_PARAMS = {
fields: {
string: 'id, name, first_name, last_name, birthday, email'
},
}
const profileRequest = new GraphRequest('/me', { token, parameters: PROFILE_REQUEST_PARAMS },
(error, result) => {
if (error) {
console.log('Login Info has an error:', error)
} else {
console.log(result)
}
},
)
new GraphRequestManager().addRequest(profileRequest).start()
}
try this
import { GraphRequest, GraphRequestManager } from 'react-native-fbsdk';
export const GetInfoUSer = () => {
return new Promise((resolve, reject) => {
const infoRequest = new GraphRequest('/me', null, ((error, result) => {
if (error) {
reject(error)
} else {
resolve(result)
}
}))
new GraphRequestManager().addRequest(infoRequest).start();
})
}
and then
onLoginConFacebook = () => {
LoginManager.logInWithReadPermissions(['public_profile']).then(result => {
if (result.isCancelled) {
console.log(':(')
} else {
AccessToken.getCurrentAccessToken().then((data) => {
let myAccessToken = data.accessToken.toString();
GetInfoUSer().then(response => {
console.log(response)
}).catch(error => {
console.log(error)
})
}
).catch(error => {
console.log(':(')
})
}
})
}
Okay so I'm trying to create a simple todo list, web api. I have the basic functions implemented and working properly but I'm trying to use a query to search by task_name as declared in my code, but no matter what I can't seem to get it functioning.
app.js
var express = require('express')
, routes = require('./routes')
, http = require('http')
, tasks = require('./routes/tasks')
, mongoose = require('mongoose');
// MongoDB Connection
mongoose.connect('mongodb://localhost/task_tracker');
var app = express();
app.configure(function(){
app.set('port', 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler());
});
app.get('/', routes.index);
app.get('/tasks', tasks.index);
app.get('/tasks/:id', tasks.show);
//app.get('/tasks/tasks?', tasks.search);
app.get('/tasks?', tasks.search);
app.post('/tasks', tasks.create);
app.put('/tasks', tasks.update);
app.del('/tasks', tasks.delete);
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port 3000");
});
tasks.js
var Task = require('../models/task').Task;
/*
* Tasks Routes
*/
exports.index = function(req, res) {
Task.find({}, function(err, docs) {
if(!err) {
res.json(200, { tasks: docs });
} else {
res.json(500, { message: err });
}
});
}
exports.show = function(req, res) {
var id = req.params.id;
Task.findById(id, function(err, doc) {
if(!err && doc) {
res.json(200, doc);
} else if(err) {
res.json(500, { message: "Error loading task." + err});
} else {
res.json(404, { message: "Task not found."});
}
});
}
exports.create = function(req, res) {
var task_name = req.body.task_name; // Name of task.
var description = req.body.task_description; // Description of the task
//Task.findOne({ name: task_name }, function(err, doc) { // This line is case sensitive.
Task.findOne({ name: { $regex: new RegExp(task_name, "i") } }, function(err, doc) { // Using RegEx - search is case insensitive
if(!err && !doc) {
var newTask = new Task();
newTask.name = task_name;
newTask.description = description;
newTask.save(function(err) {
if(!err) {
res.json(201, {message: "Task created with name: " + newTask.name });
} else {
res.json(500, {message: "Could not create task. Error: " + err});
}
});
} else if(!err) {
// User is trying to create a task with a name that already exists.
res.json(403, {message: "Task with that name already exists, please update instead of create or create a new task with a different name."});
} else {
res.json(500, { message: err});
}
});
}
exports.update = function(req, res) {
var id = req.body.id;
var task_name = req.body.task_name;
var task_description = req.body.task_description;
Task.findById(id, function(err, doc) {
if(!err && doc) {
doc.name = task_name;
doc.description = task_description;
doc.save(function(err) {
if(!err) {
res.json(200, {message: "Task updated: " + task_name});
} else {
res.json(500, {message: "Could not update task. " + err});
}
});
} else if(!err) {
res.json(404, { message: "Could not find task."});
} else {
res.json(500, { message: "Could not update task." + err});
}
});
}
exports.delete = function(req, res) {
var id = req.body.id;
Task.findById(id, function(err, doc) {
if(!err && doc) {
doc.remove();
res.json(200, { message: "Task removed."});
} else if(!err) {
res.json(404, { message: "Could not find task."});
} else {
res.json(403, {message: "Could not delete task. " + err });
}
});
}
exports.search = function(req, res) {
var name = req.query.name;
Task.findByName(name, function(err, doc) {
if(!err && doc) {
res.json(200, doc);
} else if(err) {
res.json(500, { message: "Error loading task." + err});
} else {
res.json(404, { message: "Task not found."});
}
});
}
task.js model
var mongoose = require('mongoose')
, Schema = mongoose.Schema;
var taskSchema = new Schema({
name : { type: String, required: true, trim: true, index: { unique: true } }
, description : { type: String, required: true }
, date_created : { type: Date, required: true, default: Date.now }
});
var task = mongoose.model('task', taskSchema);
module.exports = {
Task: task
};
Basically i am just trying to use a similar function to that of my search by id function but i know i can't just use parameters and I can't figure out how to get the query working. Any help would be appreciated. If you can't tell I'm using Node.js, Express and Mongodb.
TL;DR: You need to merge tasks.index and tasks.search route, ie. like this:
tasks.index = function(req, res, next) {
if (req.query.name !== undefined) {
// pass on to next handler
return next();
}
// the rest of your tasks.index.
});
And adjust the Router setup like this:
app.get('/tasks', tasks.index);
app.get('/tasks', tasks.search);
Why? Query string is not part of the route. So '/tasks?' is just a regex for /tasks+1 character, but not for a query string - query string is not a part of the route match.
More specifically, you have in your routes this:
app.get('/', routes.index);
app.get('/tasks', tasks.index);
app.get('/tasks?', tasks.search);
That last, /tasks? route will not get registered like you seem to expect. The question mark isn't representing query string processing, it's a part of the route regex, and basically means that you'd catch anything that adds one character to /tasks route, ie /tasksa, /tasksb, /tasks7 etc.
So, 7 characters, first six of which are known, the last is different, query string not included.
You cannot parse query strings in the router, it's in the individual controllers, kind of like this:
tasks.search = function(req, res) {
if (req.query.name) {
// you have the name query
}
// etc.
}
Additional advice is, what is usually done on a REST API is have the global tasks.index, like you have there, and add two things on it: paging and filter/searching.
If you want just one result
Paging is page=3&limit=10 (3rd page, 10 items per page), and filtering/sorting/searching is what you want. And depending how you want it, that's how you expose it.
Ie. you might want to sort by name:
if (req.query.sort === 'name:desc') {
mongoCursor.sort = {name: -1};
}
Or something of a sort.
So you'd probably have a search, or maybe directly a name query parameter, like this:
GET /tasks?name=<search term>
And the name param is usually optional.
So your req would list all things, and if name query string is set, it would filter by name first.
Your query building process can then look like this:
tasks.index = function(req, res) {
var query = {};
if (req.query.name) {
query.name = req.query.name;
}
Tasks.find(query, ...);
In that case, you don't need helpers on the Task model.
I found this method also works.
/**
* Module dependencies.
*/
var express = require('express'),
cors = require('cors'),
routes = require('./routes'),
http = require('http'),
tasks = require('./routes/tasks'),
mongoose = require('mongoose'),
search = require('./routes/search');
var Task = require('./models/task').Task;
// MongoDB Connection
mongoose.connect('mongodb://localhost/task_tracker');
var app = express();
app.configure(function() {
app.set('port', 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.urlencoded());
app.use(express.json());
app.use(cors());
});
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
var corsOptions = {
origin: 'http://localhost:3000'
};
app.get('/', routes.index);
app.get('/tasks', tasks.index);
//app.get('/search', tasks.FindByQuery);
//app.get('/tasks/:task.:name?', task.FindByQuery);
app.get('/search', function(req, res, next) {
var query = req.query
//res.send(query['name']);
Task.findOne({name: query['name']}, function(err, doc) {
if(!err && doc) {
res.json(200, doc);
} else if(err) {
res.json(500, { message: "Error loading task." + err});
} else {
res.json(404, { message: "Task not found."});
}
});
//res.end(JSON.stringify(query));
});
app.get('/tasks/:id', tasks.show);
app.post('/tasks', tasks.create);
app.put('/tasks', tasks.update);
app.del('/tasks', tasks.delete);
http.createServer(app).listen(app.get('port'), function() {
console.log("Express server listening on port 3000");
});
I want to retrieve data from a model provider, but all I am getting got is 'undefined' in my controller.
Here is the code:
Controller:
pdmAtWeb.controller('SearchCtrl', function($scope, ItemModel){
$scope.updateTableFromSearch = function(){
$scope.myData = ItemModel.findAllItems();
console.log($scope.myData);
};});
Provider
pdmAtWeb.provider('ItemModel', function () {
this.defaultEndpoint = '/item';
this.defaultServiceUrl = 'http://localhost:8080/webservice';
this.setDefaultEndpoint = function (newEndpoint) {
this.defaultEndpoint = newEndpoint;
};
this.setDefaultServiceUrl = function (newServiceUrl) {
this.defaultServiceUrl = newServiceUrl;
}
this.$get = function ($http) {
var endpoint = this.endpoint;
var serviceUrl = this.serviceUrl;
var refreshConnection = function () {
// reconnect
}
return{
findAllItems: function () {
$http({method: 'GET', url: serviceUrl + endpoint}).
success(function (data, status, headers, config) {
console.log(data);
return data;
}).
error(function (data, status, headers, config) {
});
}
}
}});
The provider "ItemModel" receives the correct data from the web service. Perhaps this is an async problem, but I'm not sure.
UPDATE
After adding a deferred/promise implementation it works as expected. Here is the final code:
Controller:
pdmAtWeb.controller('SearchCtrl', function($scope, ItemModel){
$scope.updateTableFromSearch = function(){
ItemModel.findAllItems().then(function(data){
console.log(data);
$scope.myData = data;
});
};
});
Provider
pdmAtWeb.provider('ItemModel', function () {
this.defaultEndpoint = '/item';
this.defaultServiceUrl = 'http://localhost:8080/webservice';
this.setDefaultEndpoint = function (newEndpoint) {
this.defaultEndpoint = newEndpoint;
};
this.setDefaultServiceUrl = function (newServiceUrl) {
this.defaultServiceUrl = newServiceUrl;
}
this.$get = function ($http, $q) {
var endpoint = this.defaultEndpoint;
var serviceUrl = this.defaultServiceUrl;
var refreshConnection = function () {
// reconnect
}
return{
findAllItems: function () {
var deferred = $q.defer();
$http({method: 'GET', url: serviceUrl + endpoint}).
success(function (data, status, headers, config) {
deferred.resolve(data);
}).
error(function (data, status, headers, config) {
deferred.reject();
});
return deferred.promise;
}
}
}
});
You dont need a deferred to accomplish this. Your $http already returns a promise. In your first example, the reason you are getting an undefined is because you are not returning anything. Check your findAllItems . It is not returning anything.
If you do return $http.get(.....) everything should work without using deferred explicitly.
Here is the corrected version :
pdmAtWeb.provider('ItemModel', function () {
this.defaultEndpoint = '/item';
this.defaultServiceUrl = 'http://localhost:8080/webservice';
this.setDefaultEndpoint = function (newEndpoint) {
this.defaultEndpoint = newEndpoint;
};
this.setDefaultServiceUrl = function (newServiceUrl) {
this.defaultServiceUrl = newServiceUrl;
}
this.$get = function ($http) {
var endpoint = this.endpoint;
var serviceUrl = this.serviceUrl;
var refreshConnection = function () {
// reconnect
}
return{
findAllItems: function () {
//NOTE addition of return below.
return $http({method: 'GET', url: serviceUrl + endpoint}).
success(function (data, status, headers, config) {
console.log(data);
//NOTE: YOU SHOULD ALSO return data here for it to work.
return data;
}).
error(function (data, status, headers, config) {
});
}
}
}});