browser-sync disable directory browsing for some sub-directories - node.js

I am new to use of browser-sync and gulp but according to usage i am trying to make my http-server accessible via webserver. Additionally i want to exclude some directories to be hidden or not to be browsed by using negation on files attribute but it does not work... My main goal is to define some directories to give 404 as always whatever is requested from them...
Can someone please check; if possible, here is my gulp implementation:
var gulp = require('gulp');
var browserSync = require('browser-sync').create();
var files = ['d2cvib/output/**/*.{xml}','!d2cvib/changed-list/**'];
// Static server
gulp.task('browser-sync', function() {
browserSync.init({files,
port: 8203,
server: {
baseDir: "/mule_local_exchange/d2c/",
middleware: [
function(req, res, next) {
const user = 'd2c';
const pass = 'd2cweb';
let authorized = false;
// See if authorization exist in the request and matches username/password
if (req.headers.authorization) {
const credentials = new Buffer(req.headers.authorization.replace('Basic ', ''), 'base64').toString().split(/:(.*)/)
if (credentials[0] === user && credentials[1] === pass) {
authorized = true;
}
}
if (authorized) {
// Proceed to fulfill the request
next();
} else {
// Authorization doesn't exist / doesn't match, send authorization request in the response header
res.writeHead(401, {'WWW-Authenticate': 'Basic realm="Authenticate"'})
res.end();
}
}
],
directory: true
}
});
});

I could not disable directory listing; but work-aroundly i've disabled response code if some of the directories have been asked by HTTP GET, not %100 clean solution but works for my case:
var gulp = require('gulp');
var browserSync = require('browser-sync').create();
var cache = require('gulp-cache');
//For conditions of rest-uri patterns
function buildSearch(substrings) {
return new RegExp(
substrings
.map(function (s) {return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');})
.join('{1,}|') + '{1,}'
);
}
gulp.task('clear-cache', function() {
// Or, just call this for everything
cache.clearAll();
});
// Static server
gulp.task('browser-sync', function () {
browserSync.init({
port: 8203,
server: {
baseDir: "/mule_local_exchange/d2c/",
middleware: [
function (req, res, next) {
const user = 'd2c';
const pass = 'd2cweb';
var pattern = buildSearch(['changed-list','current', 'changed_list']);
let authorized = false;
// See if authorization exist in the request and matches username/password
if (req.headers.authorization) {
const credentials = new Buffer(req.headers.authorization.replace('Basic ', ''), 'base64').toString().split(/:(.*)/)
if (credentials[0] === user && credentials[1] === pass) {
authorized = true;
}
}
if (authorized) {
if (pattern.test(req.url)) { //400 for not required directories
res.writeHead(400, {'Response':'Bad-request'})
res.end();
} else { // Proceed to fulfill the request
next();
}
} else {
// Authorization doesn't exist / doesn't match, send authorization request in the response header
res.writeHead(401, {
'WWW-Authenticate': 'Basic realm="Authenticate"'
})
//res.send(401,{ 'Authentication' : 'Failed' })
res.end();
}
}
],
directory: true
}
});
});
That part does the job:
if (pattern.test(req.url)) { //400 for not required directories
res.writeHead(400, {'Response':'Bad-request'})
res.end();
}

You can define multiple baseDirs for browsers-sync and the directory listing will only be available for the first one:
baseDir: ["/mule_local_exchange/d2c/PUBLIC", "/mule_local_exchange/d2c/", "/some/other/dir"],
directory: true
In this example, directory listing will only show contents of /mule_local_exchange/d2c/PUBLIC". All files will still be available from all the dirs.

Related

yii-node socket not working on Google Compute Engine

I have configured yii-node socket in Yii 1.1 and everything works fine on localhost. No issues at all.
Now that I am trying to host my project on Google Compute Engine, I was having issues binding external IP to internal IP in order to start NodeJs server which was sending 404 on socket.io.js. I was able to fix it by removing the host from server.listen method so that it can bind to any IP address and socket.io js file is loaded to the client with it's public IP. I have created a reserved static IP for our instance and used the same IP in the below configuration.
Client handshake to server is not working since the uinque url which is generated is still pointing to localhost on GCP when website is loaded. I believe it should be server-ip instead of localhost.
My Node-Socket configuration is
'nodeSocket' => array(
'class' => 'application.extensions.yii-node-socket.lib.php.NodeSocket',
'host' => 'xxx.211.xxx.99', // default is 127.0.0.1, can be ip or domain name, without http
'allowedServerAddresses' => [ "127.0.0.1", "xxx.211.xxx.99", "::ffff:xxx.211.xxx.99" ],
'origin' => '*:*',
'port' => 3001 // default is 3001, should be integer )
Below is the log when I try to fire events from Yii
debug - served static content /socket.io.js
debug - client authorized
info - handshake authorized nvQHUiA9E1dBBKmHv69k
debug - setting request GET /socket.io/1/websocket/nvQHUiA9E1dBBKmHv69k
debug - set heartbeat interval for client nvQHUiA9E1dBBKmHv69k
debug - client authorized for
debug - websocket writing 1::
debug - client authorized for /server
debug - websocket writing 1::/server
info - transport end (undefined)
debug - set close timeout for client nvQHUiA9E1dBBKmHv69k
debug - cleared close timeout for client nvQHUiA9E1dBBKmHv69k
debug - cleared heartbeat interval for client nvQHUiA9E1dBBKmHv69k
debug - discarding transport
server.js code
var express = require('express');
var app = express();
var server = require('http').createServer(app)
var io = require('socket.io').listen(server);
var cookie = require('cookie');
var serverConfiguration = require('./server.config.js');
var storeProvider = express.session.MemoryStore;
var sessionStorage = new storeProvider();
var componentManager = require('./components/component.manager.js');
componentManager.set('config', serverConfiguration);
var eventManager = require('./components/event.manager.js');
var socketPull = require('./components/socket.pull.js');
var db = require('./components/db.js');
db.init(serverConfiguration.dbOptions);
componentManager.set('db', db);
componentManager.set('sp', socketPull);
componentManager.set('io', io);
componentManager.set('eventManager', eventManager);
componentManager.set('sessionStorage', sessionStorage);
server.listen(serverConfiguration.port);
console.log('Listening ' + serverConfiguration.host + ':' + serverConfiguration.port);
// accept all connections from local server
if (serverConfiguration.checkClientOrigin) {
console.log('Set origin: ' + serverConfiguration.origin);
io.set("origins", serverConfiguration.origin);
}
// client
io.of('/client').authorization(function (handshakeData,accept) {
if (!handshakeData.headers.cookie) {
return accept('NO COOKIE TRANSMITTED', false);
}
handshakeData.cookie = cookie.parse(handshakeData.headers.cookie);
var sid = handshakeData.cookie[serverConfiguration.sessionVarName];
if (!sid) {
return accept('Have no session id', false);
}
handshakeData.sid = sid;
handshakeData.uid = null;
// create write method
handshakeData.writeSession = function (fn) {
sessionStorage.set(sid, handshakeData.session, function () {
if (fn) {
fn();
}
});
};
// trying to get session
sessionStorage.get(sid, function (err, session) {
// create session handler
var createSession = function () {
var sessionData = {
sid : sid,
cookie : handshakeData.cookie,
user : {
role : 'guest',
id : null,
isAuthenticated : false
}
};
// store session in session storage
sessionStorage.set(sid, sessionData, function () {
// authenticate and authorise client
handshakeData.session = sessionData;
accept(null, true);
});
};
// check on errors or empty session
if (err || !session) {
if (!session) {
// create new session
createSession();
} else {
// not authorise client if errors occurred
accept('ERROR: ' + err, false);
}
} else {
if (!session) {
createSession();
} else {
// authorize client
handshakeData.session = session;
handshakeData.uid = session.user.id;
accept(null, true);
}
}
});
}).on('connection', function (socket) {
// add socket to pull
socketPull.add(socket);
// connect socket to him channels
componentManager.get('channel').attachToChannels(socket);
// bind events to socket
eventManager.client.bind(socket);
});
// server
io.of('/server').authorization(function (data, accept) {
if (data && data.address) {
if (data.headers['cookie']) {
data.cookie = cookie.parse(data.headers.cookie);
if (data.cookie.PHPSESSID) {
data.sid = data.cookie.PHPSESSID;
var found = false;
for (var i in serverConfiguration.allowedServers) {
if (serverConfiguration.allowedServers[i] == data.address.address) {
found = true;
break;
}
}
if (found) {
var createSession = function () {
var sessionData = {
sid : data.cookie.PHPSESSID,
cookie : data.cookie,
user : {
role : 'guest',
id : null,
isAuthenticated : false
}
};
// store session in session storage
sessionStorage.set(data.cookie.PHPSESSID, sessionData, function () {
// authenticate and authorise client
data.session = sessionData;
accept(null, true);
});
};
data.writeSession = function (fn) {
sessionStorage.set(data.cookie.PHPSESSID, data.session, function () {
if (fn) {
fn();
}
});
};
sessionStorage.get(data.cookie.PHPSESSID, function (err, session) {
if (err || !session) {
if (!session) {
createSession();
} else {
accept('ERROR: ' + err, false);
}
} else {
if (!session) {
createSession();
} else {
// authorize client
data.session = session;
data.uid = session.user.id;
accept(null, true);
}
}
});
} else {
accept('INVALID SERVER: server host ' + data.address.address + ' not allowed');
}
} else {
accept('PHPSESSID is undefined', false);
}
} else {
accept('No cookie', false);
}
} else {
accept('NO ADDRESS TRANSMITTED.', false);
return false;
}
}).on('connection', function (socket) {
// bind events
eventManager.server.bind(socket);
});
componentManager.initCompleted();
I was able to resolve it myself.. :) I missed to look in the cached assets which had old code pointing to localhost and when I cleared the cached from yii assets folder, it worked.
Configuration required just one change to remove the binding of host from server.listen method which I had already mentioned in the question so that it can accept requests from any IP address on Google Compute Engine.

Node.js TypeError: Wit is not a constructor

How to solve "Wit is not a constructor" error coming from Node.js while executing code given by node-wit and wit.ai documentation.
// Setting up our bot
const wit = new Wit(WIT_TOKEN, actions);
I tried all the ways by upgrading and downgrading npm/node versions, but no luck.
Update: Please find the index.js source I used,
Do I need to change anything in this?
module.exports = {
Logger: require('./lib/logger.js').Logger,
logLevels: require('./lib/logger.js').logLevels,
Wit: require('./lib/wit.js').Wit,
}
'use strict';
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
const Logger = require('node-wit').Logger;
const levels = require('node-wit').logLevels;
var app = express();
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.listen((process.env.PORT || 3000));
//const Wit = require('node-wit').Wit;
const WIT_TOKEN = process.env.WIT_TOKEN;
const FB_PAGE_TOKEN = process.env.FB_PAGE_TOKEN;
const Wit = require('node-wit').Wit;
// Server frontpage
app.get('/', function (req, res) {
debugger;
res.send('This is TestBot Server');
});
// Messenger API specific code
// See the Send API reference
// https://developers.facebook.com/docs/messenger-platform/send-api-reference
const fbReq = request.defaults({
uri: 'https://graph.facebook.com/me/messages',
method: 'POST',
json: true,
qs: { access_token: FB_PAGE_TOKEN },
headers: {'Content-Type': 'application/json'},
});
const fbMessage = (recipientId, msg, cb) => {
const opts = {
form: {
recipient: {
id: recipientId,
},
message: {
text: msg,
},
},
};
fbReq(opts, (err, resp, data) => {
if (cb) {
cb(err || data.error && data.error.message, data);
}
});
};
// See the Webhook reference
// https://developers.facebook.com/docs/messenger-platform/webhook-reference
const getFirstMessagingEntry = (body) => {
const val = body.object == 'page' &&
body.entry &&
Array.isArray(body.entry) &&
body.entry.length > 0 &&
body.entry[0] &&
body.entry[0].id === FB_PAGE_ID &&
body.entry[0].messaging &&
Array.isArray(body.entry[0].messaging) &&
body.entry[0].messaging.length > 0 &&
body.entry[0].messaging[0]
;
return val || null;
};
// Wit.ai bot specific code
// This will contain all user sessions.
// Each session has an entry:
// sessionId -> {fbid: facebookUserId, context: sessionState}
const sessions = {};
const findOrCreateSession = (fbid) => {
var sessionId;
// Let's see if we already have a session for the user fbid
Object.keys(sessions).forEach(k => {
if (sessions[k].fbid === fbid) {
// Yep, got it!
sessionId = k;
}
});
if (!sessionId) {
// No session found for user fbid, let's create a new one
sessionId = new Date().toISOString();
sessions[sessionId] = {fbid: fbid, context: {}};
}
return sessionId;
};
// Our bot actions
const actions = {
say(sessionId, context, message, cb) {
// Our bot has something to say!
// Let's retrieve the Facebook user whose session belongs to
const recipientId = sessions[sessionId].fbid;
if (recipientId) {
// Yay, we found our recipient!
// Let's forward our bot response to her.
fbMessage(recipientId, message, (err, data) => {
if (err) {
console.log(
'Oops! An error occurred while forwarding the response to',
recipientId,
':',
err
);
}
// Let's give the wheel back to our bot
cb();
});
} else {
console.log('Oops! Couldn\'t find user for session:', sessionId);
// Giving the wheel back to our bot
cb();
}
},
merge(sessionId, context, entities, message, cb) {
cb(context);
},
error(sessionId, context, error) {
console.log(error.message);
},
// You should implement your custom actions here
// See https://wit.ai/docs/quickstart
};
const wit = new Wit(WIT_TOKEN, actions);
// Message handler
app.post('/webhook', (req, res) => {
// Parsing the Messenger API response
// Setting up our bot
//const wit = new Wit(WIT_TOKEN, actions);
const messaging = getFirstMessagingEntry(req.body);
if (messaging && messaging.message && messaging.message.text) {
// Yay! We got a new message!
// We retrieve the Facebook user ID of the sender
const sender = messaging.sender.id;
// We retrieve the user's current session, or create one if it doesn't exist
// This is needed for our bot to figure out the conversation history
const sessionId = findOrCreateSession(sender);
// We retrieve the message content
const msg = messaging.message.text;
const atts = messaging.message.attachments;
if (atts) {
// We received an attachment
// Let's reply with an automatic message
fbMessage(
sender,
'Sorry I can only process text messages for now.'
);
} else if (msg) {
// We received a text message
// Let's forward the message to the Wit.ai Bot Engine
// This will run all actions until our bot has nothing left to do
wit.runActions(
sessionId, // the user's current session
msg, // the user's message
sessions[sessionId].context, // the user's current session state
(error, context) => {
if (error) {
console.log('Oops! Got an error from Wit:', error);
} else {
// Our bot did everything it has to do.
// Now it's waiting for further messages to proceed.
console.log('Waiting for futher messages.');
// Based on the session state, you might want to reset the session.
// This depends heavily on the business logic of your bot.
// Example:
// if (context['done']) {
// delete sessions[sessionId];
// }
// Updating the user's current session state
sessions[sessionId].context = context;
}
}
);
}
}
res.sendStatus(200);
});
There are two typical causes of your issue, either forgetting to require your module or forgetting to npm install it. Check if you:
Forgot to require('node-wit') and obtain the constructor from the returned object:
const Wit = require('node-wit').Wit
Properly required Wit but forgot to npm install node-wit
For everyone who are using messenger.js as your index.js use this:
const Wit = require('./lib/wit');
const log = require('./lib/log');
Please check your node_modules directory for node-wit package.
If node-wit is present then please require it before trying to create its instance.
const {Wit} = require('node-wit');
witHandler = new Wit({
accessToken: accessToken
});

Stop node-simplecrawler instance when creating a new one (make it behave like a singleton)

Heyllo, everyone!
I am making a scraper which uses node-simplecrawler. Everything runs fine, but what I can't figure out is how to stop one instance when creating a new one (I want to have only one running at a time). I am using express for this and all the scraping logic is in one route. In order to cancel the crawling right now, I need to stop the node process and run the app again.
Here is the part of the code that concerns running the crawler (note: I've simplified the code a little bit, so it's shorter):
module.exports = function(socket) {
var express = require('express');
var router = express.Router();
[... requires continue...]
/* GET scaning page. */
router.post('/', function(req, res, next) {
res.render('scanning'); // Load the socket.io host page
var render = {};
var pages = [];
var timer = new Date();
// Helper func to log the requests.
function log(message) {
var now = new Date();
console.log(now - timer + 'ms', message);
timer = now;
}
// Ensure URL format, parse URL
// Check if URL exist
request(url.href, function (error, response, body) {
if (!error && response.statusCode == 200) {
// URL exists, so let's scan it
// Exclude links to the following extensions:
var exclude = ['gif', 'jpg', 'jpeg', 'png', 'ico', 'bmp', 'ogg', 'webp',
'mp4', 'webm', 'mp3', 'ttf', 'woff', 'json', 'rss', 'atom', 'gz', 'zip',
'rar', '7z', 'css', 'js', 'gzip', 'exe', 'xml', 'svg'];
var exts = exclude.join('|');
var regexReject = new RegExp('\.(' + exts + ')', 'i');
var rootURL = url.protocol + '//' + url.host + '/';
// Crawler configuration
var crawler = new Crawler(url.host);
crawler.initialPort = 80;
crawler.initialPath = url.pathname;
crawler.maxConcurrency = 1;
crawler.ignoreWWWDomain = false; // This is a little suspicious...
crawler.filterByDomain = true; // Only URLs from the current domain
crawler.scanSubdomains = true;
crawler.downloadUnsupported = false;
crawler.parseHTMLComments = false;
crawler.parseScriptTags = false;
crawler.acceptCookies = false;
// crawler.maxDepth = 1 // Debug only!
/*
* Fetch Conditions
*/
// Get only URLs, ignore feeds, only from this host
crawler.addFetchCondition(function (parsedURL) {
return (
!parsedURL.path.match(regexReject) && // Only links
(parsedURL.path.search('/feed') === -1) && // Igrnore feeds
(parsedURL.host === url.host) // Page is from this domain
);
});
// Should we only include subpages?
if(onlySubpages) {
crawler.addFetchCondition(function(parsedURL) {
// return parsedURL.path.search(url.pathname) > -1;
return parsedURL.path.startsWith(url.pathname);
// console.log(url, parsedURL);
});
}
// Exclude urls with fragments?
if(excludeUrls.length >= 1 ) {
crawler.addFetchCondition(function(parsedURL) {
var urlFragmentsOk = true;
excludeUrlFragments.forEach(function(fragment) {
if(parsedURL.path.search('/'+fragment) > -1) {
urlFragmentsOk = false;
}
});
return urlFragmentsOk;
});
}
// Include only URLs with fragments
if(includeOnlyUrls.length >= 1) {
crawler.addFetchCondition(function(parsedURL) {
var urlFragmentsOk = false;
var includeUrlFragments = includeOnlyUrls.replace(/\s/, '').split(',');
includeUrlFragments.forEach(function(fragment) {
if(parsedURL.path.search('/'+fragment) !== -1) {
urlFragmentsOk = true;
}
});
return urlFragmentsOk;
});
}
// Run the crawler
crawler.start();
// Execute for each URL, on fetchcomplete
crawler.on('fetchcomplete', function(item, responseBuffer, response) {
[Do stuff with the scraped page]
});
// Completed crawling. Now let's get to work!
crawler.on('complete', function() {
[Get all scraped pages and do something with them]
});
// Error handling
crawler.on('queueerror', function(errorData, URLData) {
console.log('Queue error:', errorData, URLData);
});
crawler.on('fetchdataerror', function(queueitem, response) {
console.log('Fetch error:', queueitem, response);
});
crawler.on('fetchtimeout', function(queueItem, crawlerTimeoutValue) {
console.log('Fetch timeout:', queueItem, crawlerTimeoutValue);
});
crawler.on('fetchclienterror', function(queueItem, errorData) {
console.log('Fetch local error:', queueItem, errorData);
});
crawler.on('fetchtimeout', function(queueItem, crawlerTimeoutValue) {
console.log('Crawler timeout:', queueItem, crawlerTimeoutValue);
});
} else if(error) {
console.log(error);
}
});
});
return router;
}
Every simplecrawler instance has a stop method that can be called to prevent the crawler from making any further requests (requests won't be stopped in flight, however).
I would probably store the crawler instance in a scope outside of the route handler, check if its defined first thing in the route handler, in that case call the stop method and then construct a new scraper.
I stripped out a lot of the meat of your code, but something like this is what I had in mind:
module.exports = function(socket) {
var express = require('express');
var router = express.Router();
var Crawler = requrie('simplecrawler');
var crawler;
router.post('/', function(req, res, next) {
// Check if URL exist
request(url.href, function (error, response, body) {
if (!error && response.statusCode == 200) {
// Stop any crawler that's already running
if (crawler instanceof Crawler) {
crawler.stop();
}
// Crawler configuration
crawler = new Crawler(url.host);
crawler.initialPort = 80;
crawler.initialPath = url.pathname;
// Run the crawler
crawler.start();
// Execute for each URL, on fetchcomplete
crawler.on('fetchcomplete', function(item, responseBuffer, response) {
// [Do stuff with the scraped page]
});
// Completed crawling. Now let's get to work!
crawler.on('complete', function() {
// [Get all scraped pages and do something with them]
});
} else if(error) {
console.log(error);
}
});
});
return router;
}

Why is PUT request body undefined?

I'm making the following request to my koajs server:
$.ajax({
type : 'PUT', // this.request.body undefined server side
// type : 'POST', // this.request.body all good server side
url : url,
data : body,
dataType : 'json'
})
But on the server side this.request.body is always undefined.
If I change the request type to POST, it works fine.
Any ideas?
EDIT
I'm using koa-route.
EDIT 2
Just realised I'm using koa-body-parser, which is probably more relevant.
Try using the koa-body parser:
const bodyParser = require('koa-bodyparser')
app.use(bodyParser())
I think koa-router will parse typical request stuff, url params, forms etc. If you want to parse the body of a request that contains a JSON object you need to apply a middleware (as alex alluded to).
Also please check to see if you are putting valid JSON.
Take a look at this Koa-bodyparser:
/**
* #param [Object] opts
* - {String} jsonLimit default '1mb'
* - {String} formLimit default '56kb'
* - {string} encoding default 'utf-8'
*/
return function *bodyParser(next) {
if (this.request.body !== undefined) {
return yield* next;
}
if (this.is('json')) {
this.request.body = yield parse.json(this, jsonOpts);
} else if (this.is('urlencoded')) {
this.request.body = yield parse.form(this, formOpts);
} else {
this.request.body = null;
}
yield* next;
};
there looks to be a 1mb limit on the amount of JSON. then to co-body/lib/json.js
module.exports = function(req, opts){
req = req.req || req;
opts = opts || {};
// defaults
var len = req.headers['content-length'];
if (len) opts.length = ~~len;
opts.encoding = opts.encoding || 'utf8';
opts.limit = opts.limit || '1mb';
return function(done){
raw(req, opts, function(err, str){
if (err) return done(err);
try {
done(null, JSON.parse(str));
} catch (err) {
err.status = 400;
err.body = str;
done(err);
}
});
}
};

regarding foodme project in github

hello i have a question regarding the foodme express example over github:
code:
var express = require('express');
var fs = require('fs');
var open = require('open');
var RestaurantRecord = require('./model').Restaurant;
var MemoryStorage = require('./storage').Memory;
var API_URL = '/api/restaurant';
var API_URL_ID = API_URL + '/:id';
var API_URL_ORDER = '/api/order';
var removeMenuItems = function(restaurant) {
var clone = {};
Object.getOwnPropertyNames(restaurant).forEach(function(key) {
if (key !== 'menuItems') {
clone[key] = restaurant[key];
}
});
return clone;
};
exports.start = function(PORT, STATIC_DIR, DATA_FILE, TEST_DIR) {
var app = express();
var storage = new MemoryStorage();
// log requests
app.use(express.logger('dev'));
// serve static files for demo client
app.use(express.static(STATIC_DIR));
// parse body into req.body
app.use(express.bodyParser());
// API
app.get(API_URL, function(req, res, next) {
res.send(200, storage.getAll().map(removeMenuItems));
});
i don't understand where is the api folder. it doesn't exist and i don't understand how information is going in and out from there. i can't find it.
can someone please explain this to me?
another question:
there is a resource for the restaurant
foodMeApp.factory('Restaurant', function($resource) {
return $resource('/api/restaurant/:id', {id: '#id'});
});
and in the restaurant controller there is a query:
var allRestaurants = Restaurant.query(filterAndSortRestaurants);
and the following lines:
$scope.$watch('filter', filterAndSortRestaurants, true);
function filterAndSortRestaurants() {
$scope.restaurants = [];
// filter
angular.forEach(allRestaurants, function(item, key) {
if (filter.price && filter.price !== item.price) {
return;
}
if (filter.rating && filter.rating !== item.rating) {
return;
}
if (filter.cuisine.length && filter.cuisine.indexOf(item.cuisine) === -1) {
return;
}
$scope.restaurants.push(item);
});
// sort
$scope.restaurants.sort(function(a, b) {
if (a[filter.sortBy] > b[filter.sortBy]) {
return filter.sortAsc ? 1 : -1;
}
if (a[filter.sortBy] < b[filter.sortBy]) {
return filter.sortAsc ? -1 : 1;
}
return 0;
});
};
the things that isn't clear to me is:
how is that we are giving the query just a function without even activating it.
as i understand we should have passed the query somthing like:
{id: $routeParams.restaurantId}
but we only passed a reference to a function. that doesn't make any sense.
could someone elaborate on this?
thanks again.
var API_URL = '/api/restaurant';
var API_URL_ID = API_URL + '/:id';
var API_URL_ORDER = '/api/order';
These lines are just defining string constants that are plugged into Express further down. They're not a folder.
app.get(API_URL, function(req, res, next) {
res.send(200, storage.getAll().map(removeMenuItems));
});
So this function call to app.get(API_URL... is telling Express "Look out for GET requests that are pointed at the URL (your app's domain)/api/restaurant, and execute this function to handle such a request."
"api" is not a folder.
Every requests will pass through the app.get method.
This method will respond to the routes /api/restaurant as defined in the API_URL variable.

Resources