Using Node.js and Express, my first route determines the client's language :
var express = require('express'),
app = module.exports = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server),
ent = require('ent'),
fs = require('fs'),
path = require('path'),
request = require('request');
app.set('view engine', 'ejs');
app.use(express.static(__dirname + '/public'));
app.get('/', function (req, res) {
var ip = req.ip;
request('http://freegeoip.net/json/' + ip, function (error, response, body) {
if (!error && response.statusCode == 200) {
var data = JSON.parse(body);
var code = data.country_code.toLowerCase();
}
});
res.render('index.ejs');
});
Then I need to pass code to index.ejs to display the appropriate language.
Some people suggest to use Angular to share a scope, but Angular isn't defined in my app, only in index.ejs. I'm not sure if I should add it to app.js or not.
Others suggest to use module.exports on the app but require doesn't work on the front end either.
What is a good way to do it ?
Call res.render inside the callback after you've called http://freegeoip.net, and pass any data needed to render the view as an object parameter, to res.render, i.e.
app.get('/', function (req, res) {
var ip = req.ip;
request('http://freegeoip.net/json/' + ip, function (error, response, body) {
if (!error && response.statusCode == 200) {
var data = JSON.parse(body);
var code = data.country_code.toLowerCase();
res.render('index.ejs', {
code: code
});
}
});
});
Related
I just want to know how can we achieve wild card routing in pure http.createServer without using express.
in express we would do something like below
var express = require('express');
var http = require('http');
var app = express();
app.get('/',function(req,red)
{
res.send("I am foo");
});
app.get('/:id',function(req,res)
{
res.send("I am Foo with id " + red.params.id);
});
but I wasn't able to find the equivalent in http.createServer
var http = require('http');
//create a server object:
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
var url = req.url;
if(url ==='/'){
res.write('i am foo');
res.end();
}else if(url ==='/:id'){//
res.write('I am foo with id');
res.end();
}
}).listen(3000, function(){
console.log("server start at port 3000");
});
one way we could achieve this is using pattern matching but I don't think its a feasible solution.
I'm using Express with Pug to practice some stuff. I did a request to a website and got some information; that information is in an array but since that information can change I'm trying to iterate over it with Pug but I'm not sure on how can I get that variable outside of the pug file; I get errors pointing that I'm not declaring the variable in the right way; errors like "... is not defined" etc. If I try to declare it on the express file it doesn't work neither so I don't know if I should declare it on express so the Pug file can have access to it or something. I'm not sure on how to do this.
Pug file
div#information
table
tr
th Health
th Defense
th Speed
tr
each val in // (What goes here?)
td= val
The array in the js file with the Ajax request has the name of statArr
Express
var express = require('express');
var router = express.Router();
var request = require('request');
/* GET home page. */
router.get("/", (req, res) => {
res.render('index');
});
router.post("/", (req, res) => {
res.send(req.body)
})
module.exports = router;
If more information is needed please let me know.
Something like this for the server example.
var express = require('express');
var router = express.Router();
var request = require('request');
router.get("/", (req, res) => {
request('yourURLWhereYouGetData', function (error, res, body) {
if (!error && res.statusCode == 200) {
var statArr = body.statArr;
res.render('index', { statArr });
}
})
});
router.post("/", (req, res) => {
res.send(req.body)
})
module.exports = router;
I have a movie-finding app that makes API calls in the backend. During initialization I need to load some JSON files: one (lang.json) contains a list of languages for searching purposes, the other (stored in the config variable) is used to get a link to the movie poster.
How would I ensure the loading of these files is completed before an HTTP request is made? One solution I can think of involves putting the calls to app.get() and app.listen() inside fs.readfile()'s callback. But is there a better way? Web development is totally new to me.
var express = require('express');
var app = express();
var fs = require('fs');
var request = require('request');
var merge = require('merge');
require('dotenv').config();
var apiKey = process.env.API_KEY;
var config = {};
app.use(express.static('view'));
// TODO load config and lang before below code
app.get('/lang', function(req, res) {
fs.readFile('lang.json', function(err, data) {
if (err) throw err;
res.json(JSON.parse(data));
});
});
app.get('/genres', function(req, res) {
request.get({
url: 'http://api.themoviedb.org/3/genre/movie/list',
qs: {api_key: apiKey}
}, function(error, response, body) {
res.json(JSON.parse(body).genres);
});
});
app.get('/randomMovie', function(req, res) {
request.get({
url: 'https://api.themoviedb.org/3/discover/movie',
qs: merge(req.query, {api_key: apiKey})
}, function(error, response, body) {
body = JSON.parse(body).results;
var len = body.length;
var i = Math.floor(Math.random() * len);
var movie = body[i];
// movie.poster_path = movie.images.base_url + movie.images.poster_sizes[6] + movie.poster_path;
res.json(movie);
});
});
app.listen(3000, function() {
console.log('server started on port 3000');
});
The easiest way is to just use fs.readFileSync() before your call to app.listen(). For example:
var lang = fs.readFileSync('lang.json');
app.get('/lang', function(req, res) {
res.setHeader('Content-Type', 'application/json');
res.send(lang);
});
// ...
Just be aware that the contents of lang will not automatically update if the contents of lang.json change on disk during the lifetime of your node process.
I'm playing with node.js and express. I have a little server which fetch sqlite contents and send everything to a Jade template. It works fine using this code :
var express = require('express');
var app = express();
app.set('view engine', 'jade');
var async = require('async');
var result_title = [];
var result_scope = [];
var result_benefits = [];
var result_technical = [];
app.use(express.static(__dirname + '/views'));
app.get('/product1', function(req, res){
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('products.db');
var check;
db.serialize(function() {
db.each("SELECT title, scope, body, technical_information FROM products", function(err, row) {
result_title.push(row.title);
result_scope.push(row.scope);
result_benefits.push(row.body);
result_technical.push(row.technical_information);
});
});
console.log(result_title[0]);
res.render("index", {title:result_title[0], scope:result_scope[0],benefits:result_benefits[0], technical_information:result_technical[0]});
db.close();
});
app.listen(8080);
My issue is that when I go to page http://localhost/product1:8080 nothing is displayed. A manual refresh of the page is needed to load the content! My research tells me that I need to use Async functions. I edited my code :
var express = require('express');
var app = express();
app.set('view engine', 'jade');
var async = require('async');
var result_title = [];
var result_scope = [];
var result_benefits = [];
var result_technical = [];
app.use(express.static(__dirname + '/views'));
app.get('/product1', function(req, res){
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('products.db');
var check;
async.series([
function(callback) {
db.serialize(function() {
db.each("SELECT title, scope, body, technical_information FROM products", function(err, row) {
result_title.push(row.title);
result_scope.push(row.scope);
result_benefits.push(row.body);
result_technical.push(row.technical_information);
});
});
},
function(callback) {
// console.log(result_title[0]);
res.render("index", {title:result_title[0], scope:result_scope[0],benefits:result_benefits[0], technical_information:result_technical[0]});
db.close();
}
], function(error, results) {
console.log('');
})
});
app.listen(8030);
But the webpage is loading, loading and nothing happens..
I made something wrong, but no idea where for the moment. If someone have an idea it could be great ;-) Thanks!
Your url is wrong also the second code block your port is different.
Give port name after domain or ip address , if not the request will go /product1:8080 and you haven't any router like that , so request goes to error page also it semes you haven't any error handling for 404.
Try : http://localhost:8080/product1 or http://localhost:8030/product1
Also you have an issue in your second code block :
res.render("index", {title:result_title[0], scope:result_scope[0],benefits:result_benefits[0], technical_information:result_technical[0]});
This line should be executed in all series callback, If not you will not get data you want. Because it's still in async function.
], function(error, results) {
res.render("index", {title:result_title[0], scope:result_scope[0],benefits:result_benefits[0], technical_information:result_technical[0]});
})
I have just investigated sqllite3 , you don't need to use async library as an extra in this situation(BTW in async functins you have to call callback with return parameter on it). In sqllite3 documentation db.each.
That latest code should work. Try following.
var express = require('express');
var app = express();
app.set('view engine', 'jade');
var async = require('async');
var result_title = [];
var result_scope = [];
var result_benefits = [];
var result_technical = [];
app.use(express.static(__dirname + '/views'));
app.get('/product1', function(req, res){
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('products.db');
var check;
db.serialize(function() {
db.each("SELECT title, scope, body, technical_information FROM products", function(err, row) {
result_title.push(row.title);
result_scope.push(row.scope);
result_benefits.push(row.body);
result_technical.push(row.technical_information);
},function(err, rows){
if(err){
// handle error
}
res.render("index", {title:result_title[0], scope:result_scope[0],benefits:result_benefits[0], technical_information:result_technical[0]});
});
});
});
app.listen(8080);
I have an index.html page which is present at:
D:\GITProjects\codelab\complete\step1\index.html
I am trying to execute D:\GITProjects\codelab\complete\step1\server.js file via node:
"C:\Program Files\nodejs>node.exe D:\GITProjects\codelab\complete\step1\server.js"
Server.js code:
var static = require('node-static');
var http = require('http');
var file = new (static.Server)("D:\GITProjects\codelab\complete\step1");
var app = http.createServer(function (req, res) {
file.serve(req, res);
}).listen(2011);
When I go to hit:
http://localhost:2011/
I see empty page. Any idea why?
The console shows "http://localhost:2011/ Failed to load resource: the server responded with a status of 404 (Not Found)"
You need to keep file.serve(req,res) within req.addListener()
var static = require('node-static');
var http = require('http');
var file = new (static.Server)("./");
var app = http.createServer(function (req, res) {
req.addListener('end',function(){ // <--
file.serve(req, res);
}).resume() // <--
}).listen(2011);
Also, you have a couple of other options to go with(if you dont want to stick with node-static)
Option-1: Use fs module to read the file and send it on request
var http = require('http'),
fs = require('fs');
fs.readFile('./index.html', function (err, html) {
if (err) {
throw err;
}
http.createServer(function(request, response) {
response.writeHeader(200, {"Content-Type": "text/html"});
response.write(html);
response.end();
}).listen(2011);
});
Option-2:
Use a web app framework like express(). It provides several great features to simplify the power of node. Then you can either define a specific route for '/' to send your index.html
var express= require('express')
var app = express()
app.get('/',function(req,res){
res.sendFile('index.html',{ root:__dirname })
})
app.listen(2011)
or serve your static assets straightaway:
var express= require('express')
var app = express()
app.use(express.static(__dirname)); //this will make index.html available to every request
app.listen(2011)
__dirname is the directory that the currently executing script is in. Since both server.js and index.html are at same level, __dirname will point to *D:\GITProjects\codelab\complete\step1*