Using express and sockets to create a chat client. However I get a 404 when trying to connect to static files.
Server.js
var jade = require('jade');
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
io.on('connection', function() {
'use strict';
socket.on('setPseudo', function(data) {
socket.set('pseudo', data);
});
socket.on('message', function(message) {
socket.get('pseudo', function(error, name) {
var data = {
'message': message,
pseudo: name
};
socket.broadcast.emit('message', data);
console.log("user " + name + " send this : " + message);
});
});
});
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.set("view options", {
layout: false
});
app.use(express.static(__dirname + '/public'));
app.get('/', function(req, res) {
'use strict';
res.render('home.jade');
});
server.listen(4000);
In order for my application to work I need to connect to a script.js file in my /public folder. However the server seem to be unable to find it.
Update with jade file:
doctype html
html
head
title le Chat
script(src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js')
script(src="/socket.io/socket.io.js")
script(src="public/script.js")
body
div.container
header
h1 le Chat Meow
input(type='text')#pseudoInput
button#pseudoSet Set Pseudo
div#chatEntries
div#chatControls
input(type='text')#messageInput
button#submit Send
and also the folder structure:
-public > script.js
-views > home.jade
-server.js
Change script(src="public/script.js") to script(src="script.js") because your public folder is the root of static files so you dont need to put it in the paths in the html files
Since somebody marked your other newest question about the console.readLine as a dublicate eventhough it obviously wasnt i'l answer to it here instead.
Apparently console.readLine does not work inside an IDE, eclipse for example.
You will have to run the program inside the actual console for that code to work.
A suggestion would be to use a buffered reader instead.
Related
I'm having trouble with Node JS.
With the Apache/php model, I'm able to make a standalone save.php file (takes a post request, saves to a txt file) without fooling around with the Apache server.
<?php file_put_contents ( 'content.txt' , $_POST['myData']);?>
In Node, I have server.js started to serve up whatever files I have in /public :
var express = require('express');
var app = express();
app.use(express.static('public'));
app.use(express.static(__dirname + '/public'));
app.use(function(req,res, next){
if(req.accepts('html')){
res.status(404).sendFile(__dirname+'/public/404.html');
}
});
app.listen(process.env.PORT || 80);
How can I make a save.js file, e.g. /public/test_project1/save.js, that can be executed on an HTML form submission?
var fs = require('fs');
fs.writeFile("content.txt", ???post data???)
Is there any way to avoid explicitly defining the app.post()... in server.js every time I make a new js file in /public? I'm looking for an architecture that allows me to create one node server to host various separate project files in /public
First you need to create a endpoint for your post request, then parse form data, a option could be body-parser middleware , finally save the content.
Something like:
var express = require('express');
var app = express();
var bodyparser = require("body-parser");
app.use(bodyparser.urlenconded({extended:true}); // middleware for parse form data
app.use(express.static('public'));
app.use(express.static(__dirname + '/public'));
app.post("/endpoint",function(req,res){
//myData is input name
var content = req.body.myData;
fs.writeFile("content.txt", content,function(err){
res.end("done");
})
})
app.use(function(req,res, next){
if(req.accepts('html')){
res.status(404).sendFile(__dirname+'/public/404.html');
}
});
app.listen(process.env.PORT || 80);
Then you make a POST request to /endpoint with myData as input.
Here's what I came up with - modifying server.js to handle any POST requests within that folder. Is this dangerous?
app.post('/:folder/:file',function(req, res){
filepath=__dirname+'/public/'+req.params.folder+'/'+req.params.file;
fs.stat(filepath, function(err, stat) {
if(err == null) {
console.log('File exists');
var anyFile=require(filepath)(req.body);
res.redirect(anyFile);
} else if(err.code == 'ENOENT') {
res.send('File does not exist.');
} else {
res.send('Error: '+ err.code);
}
});
});
im new to node and after a few weeks practicing it, i found the express framework and i started to used it because it handle the tools i need more easy, but theres something i dont get to understand, its quite different from how do make the app without express. i dont quite get the express api well (its a bit confusing). im trying to make the request url to be found in specific url (./views). so when logi is requested, then it will do (./views/login.html)when url is(hostname/login), and so on if it contains folder. this is my code
/*
Chat application for #node.js
express version.
*/
//Load modules.
var express = require('express'),
socket = require('socket.io'),
swig = require('swig'),
fs = require('fs');
//Load config.
console.log('Loading configuration.');
var config = fs.readFileSync('config.json');
var config = JSON.parse(config);
var port = config.port;
var views = config.views;
console.log('Configuration loaded.');
//Initiate express module in app.
var app = express();
// app.get('/', function(request, response)
// {
// fs.readFile('./views/index.html', function(error, data)
// {
// if(error)
// {
// response.send('View cannot be rendered.');
// }
// response.type('html');
// response.send(data);
// });
// });
var test = "Hello";
app.engine('html', swig.renderFile);
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
swig.setDefaults(
{
cache: false
});
app.get('/', function(request, response)
{
response.render('index',
{
//Var to be named in the render : value;
'test': test,
'Title': 'Testing page',
});
});
//logger.
app.use(function(request, response, next)
{
console.log('%s %s', request.method, request.url);
next();
});
//Set directory for static files (css, js, img);
app.use(express.static(__dirname + '/public'));
//Run the app.
app.listen(port);
im using swig module for dynamic data in html, im also comenting my tests, used app.use() for static files in ./public folder (as found in the api). so what i want to achieve is, if the url file exist, then render it with its static files(css, js). if not, return a custom html file..
im using app.get() to recieve the expecific request.(which totally i dont get).
PD: PLEASE, NEED EXPRESS TUTORIALS (better than express homepage itself.), atleast for newbies.
Since views is not in the public directory, any url with views in it will not go to the app.use() function anyway (because it can't find it there). This is good. What you need to do now is create a routing function for that specific view. Something like this above your app.use():
app.get('/views/login', function(req, res){
res.render(__dirname + 'views/login');
});
usually, rendering engines will allow you to do a shortcut though, and just do res.render('login'); and it will find it in views by itself.
Also, some renderers allow you to specify a directory to look for when requests come in. I don't know if swig offers this though.
I facing a problem that my Angularjs is not rendering or load in my Jade layout. Somehow the stylus is working perfectly with. I counldn't find out the reason why. I'm still the beginner in learing jade, stylus and angularjs
Below are my codes:
index.jade
!!! 5
html(ng-app='ng-app')
head
script(src='https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js')
script(src='https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular-resource.min.js')
script(src='https://cdn.firebase.com/v0/firebase.js')
script(src='http://firebase.github.io/angularFire/angularFire.js')
script(type='text/javascript', src='angular.js')
link(rel='stylesheet', href='style.css')
body
.addressBook(ng-controller='addressBook')
h1 Address Book
table(width='710px', border='0', cellspacing='0', cellpadding='0')
tr.title(height='35px', align='left')
td(width='130') Name
td(width='180') Email
td(width='210') Address
td(width='80') Mobile
tr.details(ng-repeat='contact in contacts')
td {{contact.name}}
td {{contact.email}}
td(style='padding-bottom: 30px;') {{contact.address}}
td {{contact.mobile}}
angular.js
function addressBook($scope)
{
$scope.contacts =
[
{name:'Peter', email:'john_peter#asd.co', address:'No.123, Road 12/20, Street Army, 58200 KL, Malaysia', mobile:'601231231234' },
{name:'Lim', email:'Amy#asd.co', address:'54, 13/15, Happy Garden, 58200 KL, Malaysia', mobile:'60123473534' }
];
}
app.js
var jade = require('jade')
, express = require('express')
, http = require('http')
, app = express();
var stylus = require('stylus');
require('./angular.js');
app.configure(function(){
console.log('Configuring views....');
app.set('port', 1234);
app.set('views', './');
app.use(express.bodyParser());
app.use(express.static( __dirname + '/'));
app.set('view engine', 'jade');
});
app.get('/test', function(req,res){
res.render('index.jade');
});
server = http.createServer(app);
server.listen(app.get('port'), function(){
}).on('error', function(err) {
throw err;
});
thank you in advanced for everyone who helps
I suspect the issue you are having is that the path to your views that you have specified is wrong and you are serving them up statically.
For example, if you have your views in a sub-directory of the base directory, and you have set the base directory to be served up as static content, it will serve up the jade as static content.
What you should do is put your views in a different folder to the static content so that is a sibling not a child and this should work. If you want to post your directory structure I can have a look.
As my username implies, I'm new to node.js. I'm trying to learn it. As part of this process, I'm working to setup a basic web site. This web site will show a couple of basic web pages and expose a single REST endpoint. The structure of my project is:
config.js
home.html
start.js
routes.js
server.js
resources
css
style.css
images
up.png
down.png
javascript
home.html.js
start.js has my main server code. That file gets executed via command line using 'node start.js'. Once started, my server begins listening on port 3000. The code in start.js looks like this:
var express = require('express');
var app = express();
var UserProfileHandler = require('./app/handlers/UserProfileHandler');
app.configure(function () {
app.engine('html', require('ejs').renderFile);
app.set('views', __dirname + '/');
app.use(express.logger({ stream: expressLogFile }));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
var routes = {
userProfiles: new UserProfileHandler()
};
function start() {
routeConfig.setup(app, routes);
var port = process.env.PORT || 3000;
app.listen(port);
console.log("SUCCESS: Server listening on port %d in %s mode", port, app.settings.env);
}
exports.start = start;
exports.app = app;
My routes.js file has the following:
function setup(app, routes) {
viewSetup(app);
apiSetup(app, routes);
}
function viewSetup(app) {
app.get('/', function (req, res) {
res.render("/home.html");
});
app.get('/home.html', function (req, res) {
res.render("/home.html");
});
}
function apiSetup(app, routes) {
app.get('/api/userProfiles/:username', routes.userProfiles.getUserProfiles);
}
I am trying to load home.html in a browser window. I attempt this by visiting http://localhost:3000 and http://localhost:3000/ and http://localhost:3000/home.html. Unfortunately, none of these work. In fact, I receive an error that says:
Express 500 Error: Failed to lookup view "/home.html"
I know that I'm close. If I visit http://localhost:3000/api/userProfiles/me I receive a JSON response back like I'm expecting. For some reason, i can't seem to return HTML though. My home.html file looks like the following.
<html>
<head>
<script type='text/javascript' src='/resources/javascript/home.html.js'></script>
</head>
<body>
We're up and running! <img src='/resources/images/up.png' />
</body>
</html>
Its a pretty basic HTML file. Even if the HTML comes back though, I'm concerned the JavaScript file and Image it references won't be accessible. I'm concerned of this because I'm not really sure how paths and such work in Node.
How do I get home.html to work in my Node setup?
Thank you!
as your view file is in same folder as your main file, below changes should make it work
1.change the view folder configuration line
from
app.set('views', __dirname + '/');//wont work
to
app.set('views', __dirname);//will work
2.change view render lines
from
res.render("/home.html");//wont work
to
res.render("home.html");//will work
with both the changes, the view should be working fine
update to below comments.
the issue you mentioned regarding the images,css and js is due to the static folder configuration which should be changed from
app.use(express.static(__dirname + '/public'));
to
app.use(express.static(__dirname + '/resources'));
as your static folder is named resources.
but make sure in your view you are refering the css/js/image files like
eg:
/css/style.css
/images/up.png
/images/down.png
/javascript/home.html.js
from your view file
Also if the above dint work, check if you have given the path correctly and also you can try by taking the
app.use(express.static(__dirname + '/resources'));
before the
app.use(express.methodOverride());
app.use(app.router);
lines like
app.configure(function () {
app.engine('html', require('ejs').renderFile);
app.set('views', __dirname + '/');
app.use(express.static(__dirname + '/public'));
//try changing the position of above line in app.configure and resatrt node app
app.use(express.logger({ stream: expressLogFile }));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
});
had similar problem in my case is
app.set('./views');
look for the dot, dont know why but the dot will mess it up.
I had it like this
app.set('/views') and no matter what i did couldt find the folder until added the dot.
I'm using the handlebars.js hbs wrapper in express.js. I have templates working fine, but I'm needing to add in partials to be rendered with my views.
I'd like to do something like this:
hbs.registerPartial('headPartial', 'header');
// where "header" is an .hbs file in my views folder
However, it's throwing a "header partial can not be found".
I can make the registerPartial work if I pass a string of html to the second param, but I'd like to use separate view files for my partials.
I haven't found any documentation on this, but hoping I may just be missing something easy.
Does anyone know how to use view files in the registerPartial method? If so, how do I implement this?
UPDATE
To give more context, let me add more code.
Here is my "server" file - app.js
var express = require('express')
, routes = require('./routes')
, hbs = require('hbs');
var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'hbs');
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({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// this is the line that generates the error
hbs.registerPartial('headPartial', 'header');
// What I'm expecting is for "headPartial" to be a compiled template partial
// of the template within views/header.hbs, but it is not loading this way.
// If I do something like hbs.registerPartial('headPartial', '<p>test</p>');
// then it does work. I need to know how to pass an .hbs file to the
// registerPartial method.
// Routes
app.get('/', routes.index);
app.listen(3000);
And here is my routes.index file:
exports.index = function(req, res){
res.render('index', { title: 'Express' })
};
In my views folder, I have three templates:
views/
header.hbs (this is my partial)
index.hbs
layout.hbs
In my index.hbs file, I'm calling the 'headPartial' partial with:
{{> headPartial}}
Any help is greatly appreciated.
For convenience, registerPartials provides a quick way to load all partials from a specific directory:
var hbs = require('hbs');
hbs.registerPartials(__dirname + '/views/partials');
Partials that are loaded from a directory are named based on their filename, where spaces and hyphens are replaced with an underscore character:
template.html -> {{> template}}
template 2.html -> {{> template_2}}
login view.hbs -> {{> login_view}}
template-file.html -> {{> template_file}}
Cheers!
This code loads all the partial templates in a directory and makes them available by filename:
var hbs = require('hbs');
var fs = require('fs');
var partialsDir = __dirname + '/../views/partials';
var filenames = fs.readdirSync(partialsDir);
filenames.forEach(function (filename) {
var matches = /^([^.]+).hbs$/.exec(filename);
if (!matches) {
return;
}
var name = matches[1];
var template = fs.readFileSync(partialsDir + '/' + filename, 'utf8');
hbs.registerPartial(name, template);
});
Looks like creating a variable and pulling in the template code manually works:
var hbs = require('hbs')
, fs = require('fs')
, headerTemplate = fs.readFileSync(__dirname + '/views/_header.hbs', 'utf8');
and later:
hbs.registerPartial('headPartial', headerTemplate);
For me I had template file my-partial.hbs
Then I tried to access them via:
{{> my-partial }}
But the partial was stored in hbs as my_partial regardless of the filename.
This is thanks to hbs version 3.1.0 line 218
.slice(0, -(ext.length)).replace(/[ -]/g, '_').replace('\\', '/');
This is in the readme
For me, I have a function like:
var hbs = require('hbs');
var fs = require('fs');
var statupfunc = {
registerHbsPartials : function(){
//this is run when app start
hbs.registerPartials(__dirname + "/" + resource.src.views + '/partials');
},
registerOneHbsPartials : function(event){
//this is run for gulp watch
if(event.type == 'deleted')
{
return;
}
var filename = event.path;
var matches = /^.*\\(.+?)\.hbs$/.exec(filename);
if (!matches) {
return;
}
var name = matches[1];
var template = fs.readFileSync(filename, 'utf8');
hbs.registerPartial(name, template);
}
};
Run statupfunc.registerHbsPartials at app startup and then register gulp watch with statupfunc.registerOneHbsPartials to register partials on new creation
gulp.task('watch', function() {
gulp.watch(resource.src.views + '/partials/*.*', statupfunc.registerOneHbsPartials);
});
My app structure (using ExpressJS & HBS-NPM) is:
APP FOLDER
-src
app.js
- routers
- views
-- partials
header.hbs
const hbs = require('hbs')
hbs.registerPartials(path.join(__dirname,'views','partials'))
The above does the job of loading all partials in a single shot. Use this as long as you believe it doesn't impact your performance (loading all partials, even if not required).
And then, use this partial in any HBS file as follows:
{{> partial_file_name_without_hbs_extension}}
Example
{{> header}