Is exporting nodejs module correct? - node.js

My goal is to display a website which gives users a menu, then from there they click on what functionality they want to run, and then node runs a command on the back end on a ubuntu server using "exec" then displaying the results to the webpage.
So far I have two files, a nodejs file and an html page
var http = require('http'),
exec = require('child_process').exec,
fs = require('fs') ;
function onRequest(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
fs.readFile('form.html', function(err, data){
if(err)
{
res.write("err.message");
}
else
{
res.write(data);
res.end();
}
});
}
var server = http.createServer(onRequest);
server.listen(80, '0.0.0.0');
console.log("Server Running");
then the form.html
<!DOCTYPE html>
<html>
<body>
<form>
Please select from the following options:
<select id="mySelect">
<option value="apps">Insert all Apps belonging to a group</option>
<option value="groups">Insert groups in databse</option>
<option value="database">Refresh database group table</option>
<option value="another">Add all app from one group to another</option>
<option value="id">Get Group ID</option>
<option value="user">Get User ID</option>
<option value="list">Get list of all apps</option>
</select>
</form>
<p>Click the button to change the selected fruit to banana.</p>
<button type="button" onclick="myFunction()">Try it</button>
<script>
function myFunction() {
if(document.getElementById("mySelect").value = "apps")
{
//do something and display results to webpage
}
else
{
//display error
}
}
</script>
</body>
</html>
My question is, is this the right way of carrying out this task? and if so,should I export the onRequest function which would then allow me to display what I want to the webpage with res.write ?

Related

How do I serve html,css and js as a post response while using CORS?

Trying to understand the best method to send html,css, js files back to the client via a Post request.
I'm running express,react.
What I have so far is a basic post route, that returns the compiled component with data (using handlebars) as a response. However the event handlers, css and js are absent. I'm not sure how to serve these along with the HTML as a response to an AJAX POST request on another domain.
I'm using webpack for SSR and figured this would work much the same but it doesn't.
Here is what i have so far...this just returns the html from my react component.
app.post("/", async (req, res) => {
const theHtml = `
<html>
<head><title>My First SSR</title>
<link href='http://localhost:8080/app.css'></link>
<script src="http://localhost:8080/app.js" charset="utf-8"></script>
<script src="http://localhost:8080/vendor.js" charset="utf-8"></script>
</head>
<body>
<h1>My First Server Side Render</h1>
<div id="reactele">{{{reactele}}}</div>
</body>
</html>
`;
const hbsTemplate = hbs.compile(theHtml);
const reactComp = renderToString(<App />);
const htmlToSend = hbsTemplate({ reactele: reactComp });
res.send(htmlToSend);
});
The above works and is returned just without js,css event handlers etc..
here is the App component
class App extends React.Component {
constructor() {
super();
this.handleButtonClick = this.handleButtonClick.bind(this);
this.handleTextChange = this.handleTextChange.bind(this);
this.handleReset = this.handleReset.bind(this);
this.state = {
name: "",
msg: ""
};
}
//Handlers
handleButtonClick = e => {
const nameLen = this.state.name.length;
if (nameLen > 0) {
this.setState({
msg: `You name has ${nameLen} characters including space`
});
}
};
handleTextChange = e => {
this.setState({ name: e.target.value });
};
handleReset = () => {
this.setState({ name: "", msg: "" });
};
//End Handlers
render() {
let msg;
if (this.state.msg !== "") {
msg = <p>{this.state.msg}</p>;
} else {
msg = "I have a state of none";
}
return (
//do something here where there is a button that will replace the text
<div>
<header className="App-header">
{/* <img src={logo} className="App-logo" alt="logo" /> */}
{/* <img src={logo} className="App-logo" alt="logo" /> */}
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
<label>Your name </label>
<input
type="text"
id="txtName"
name="txtName"
value={this.state.name}
onChange={this.handleTextChange}
/>
<button id="btnSubmit" onClick={this.handleButtonClick}>
Calculate Name Length
</button>
<button id="btnReset" onClick={this.handleReset}>
Reset All
</button>
<hr />
{msg}
</div>
);
}
}
export default App;
On the client side i'm just appending the html to a blank page.
A few questions,
How do I maintain the eventhandlers on the requested html?
How do send the .css and .js along as well?
For some context, I'd like to avoid having to place and maintain 'client' code on my front-end server? My hope was something like webpack would handle this for me?
Thanks for any tips/suggestions.
EDIT:: To clarify this works if I access the route directly. I get the correlating js and css. Just not via a post request from another domain. I assume I'm missing some fundamental udnerstanding how the dom is maintained and scripts run.
You just need a static directory and a view renderer.
In your app.js or where ever you have initialized your express instance, add the following
var hbs = require('hbs');
var path = require('path');
var express = require('express');
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
Now you can just put your html in a hbs file in a folder called 'views' and just return it like
app.post("/", (req, res) => {
res.render('index.hbs', {variable: 'value'});
});
For the static assets add the following lines
app.use(express.static(path.join(__dirname, 'public')));
and put your js and css or images or whatever static files you want in a folder named 'public' in your project root. These will be accessible at http://localhost:8080/app.js
So my issue was on client end (my second domain). It was how i was loading the html into the DOM, my old method was inneHTML on the body. Simple answer is this doesnt work.
I had to load it in another way, I chose to use jquery's .html(), this triggers the dom to evaluate the scripts etc.
#RohithBalaji your comment helped me find my issue.
Most AJAX APIs use the browser's .innerHTML to set the content. And
that will strip the and tags, but the scripts
will execute. But, since the head is stripped I am guessing they
aren't loading?

How can i access a nodeJS variable in ejs views in a sails project?

My LoginController.js looks like this:
module.exports = {
getAuthorizationLink: function (req, res) {
res.send({
authorization_link: sails.config.FACEBOOK_LOGIN_URL
})
}
}
I need to redirect to the authorization_link when a button is clicked
<div class="col-md-4 text-center">
<button id="authenticate" class="btn btn-primary">Authenticate Page</button>
<script type="text/javascript">
document.getElementById("authenticate").onclick = function () {
...
};
</script>
</div>
Here you are looking to mix server-side (EJS) & client-side JS code.
It is possible, makes sense to do sometimes but it is not clean.
Once you understand you are doing this. Variable can be passed and accessed.
Using EJS, write JS code for client side e.g.
var auth_link = '<%= authorization_link %>';
this line will become something like below for client-side JS
var auth_link = 'https://fb.com/login';
Now you can use auth_link in client-side JS as required
Also, check res.view for responding with HTML page

What am i missing for the file upload using multipart form data ?

Hi for whatever reason i cannot use packages e.g. multer to upload file to node server. So i found example online, if just upload file in the form, it works fine.
Now i want to send another field "password" together with the file during submit, just cannot make it a work.
I do know there're plenty modules out there, for now just want to this example to work.
<form style="height: 100%;padding-bottom:63px;">
<p>
<input type="file" class="FirmwareFile"
name="myUpload" file-model="upload.newFwFile">
</p>
<p>
<input type="password" name="password" id="password"
placeholder="Password"
ng-model="upload.controllerPassword"
class="formInput">
</p>
</form>
httpSvc.uploadToUrl(myFile, myPd, myServerIPAddress, myRoute) {...}
factory.uploadToUrl = function (fwFile, pd, myServerIp, myRoute) {
var fd = new FormData();
//fd.append('passwd', pd); // cannot pass password to server side ?
fd.append('file', fwFile); // only this works
var deferred = $q.defer();
var completeUrl = ......
$http.post(completeUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).success(function (data) {
deferred.resolve(data);
}).error(function () {
deferred.reject();
});
return deferred.promise;
}
in server side, where to extract the password info please ?
var UploadImage = function(req, res, callback){
var destFile = fs.createWriteStream(uploadDest + "mytest");
var fileSize = req.headers['content-length'];
req.pipe(destFile); //why not sth. like req.body.file.pipe() ?
...
};
Your form does not have
<form enctype="multipart/form-data" action="..." method="...">
...
</form>
You will be better off using node-formidable. The example works straight out of the box. You might also want to look into angularJS specific form upload directives that have been made. No sense in reinventing the wheel.
Cheers

How do I make socket.io + ejs + mongoose work properly?

My goal is whenever someone press accept button it will, automatically increment the notifications on the navbar.
The logic
1) An admin press an accept button
2) User's navbar will listen to notify event and will increment the number of the count and append the message to the li element.
Here's the picture of the notification that Im hoping socket.io will update
However I don't see any real-time updates
Here's the code
the socket.io client side
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
<script>
var socket = io.connect('http://localhost:3000');
$('form').submit(function(){
var companyName = $("#companyName").val();
var notification = "Accepted by " + companyName;
var user_id = $('#candidate_id').val();
var notificationCount = parseInt($('#notification').html());
noticationCount += 1;
socket.emit('notify', {notification: notification, userId: user_id, count: notificationCount});
});
socket.on('notify', function(msg){
$('#notification').html(msg.count);
$('#addNotification').append($('<li>').text(msg.notification));
});
</script>
The HTML (EJS) codes -- this is where it supposed to update.
<li class="dropdown notifications-menu">
<span id='notification' class="label label-warning"><%= user.notifications.length %></span>
</a>
<ul class="dropdown-menu">
<li>
<ul class="menu" id="addNotification">
<% for(var i=0; i < user.notifications.length; i++) { %>
<li><!-- start notification -->
<a href="#">
<i class="fa fa-users text-aqua"></i> <%= user.notifications[i] %>
</a>
</li>
<% } %>
</ul>
</li>
</ul>
</li>
Serverside
io.on('connection', function(socket){
socket.on('notify', function(msg){
User.findById({ _id: msg.userId}, function(err, found) {
if (typeof found === 'undefined') {
// Do something but what should I do?s
} else {
found.notifications.push(msg.notification);
found.save(function(err) {
console.log(msg.notification); // Doesnt even console.log the data.
});
}
});
});
});
Again my goal is
1) Someone submit a button and it will emit all the hidden input values according to its tag's id like id="user_id".
2) socket.on('notify') --> Will listen and update it in real time via id of the targeted html tags
3) Save the data in the database.
However the above implementation, I have to refresh it then I can see the result.
But if I add this line to socket.io clientside code
var notificationCount = parseInt($('#notification').html());
noticationCount += 1;
It won't even save it to the database, where else to update it in real-time. I
Please lend me your real-time knowledge :)
1) You should not include socket.js file from cdn, it is should be loaded like
<script src="http://localhost:3000/socket.io/socket.io.js"></script>
you don't need to save socket.io.js file anywhere in the project folder, this is handled by socket.io module
2) I see code to receive client message to server, not from there back to clients. It will look like this (for broadcast)
io.on('connection', function(socket){
socket.on('notify', function(msg){
// pass notification & count to client
io.emit('notify', {notification:msg.notification, count:your_msg_count});
....
I am not going deeper into your code, hope this will fix your issues.

Can't find path for socket.io.js

I have my node.js and socket.io setup and running perfectly on my local machine, but now I am trying to transfer it to my live server.
I have installed node.js and socket.io and they're working, but I can't seem to link to the socket.io/socket.io.js file through my client. It keeps coming back with "500 Internal Server Error"
I have tried using both these paths:
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
and
<script type="text/javascript" src="https://localhost:8080/socket.io/socket.io.js"></script>
Why isn't it being found?
"500 Internal Server Error" usually means "server crash" or at least "server encountered an exception". So the problem might not a missing socket.io.js.
Regardless, when I have a discrepancy between local working and remote not working, it's sometimes due to a difference in the environment variables. Where are you deploying your node.js? Heroku, EC2, Joyent?
Have you changed the connection-string? Have you checked with the browser inspector, if the javascript-file is loaded?
var sio = io.connect('http://yourdomain.com:80');
sio.socket.on('error', function (reason){
console.error('Unable to connect Socket.IO', reason);
});
Here i post two files one is chat.js and other is chat.html . This has the path for socket.io.js in html.this works.
1) chat.js :
var io = require("socket.io");
var socket = io.listen(1223);
socket.set("log level", 1);
var people = {};
socket.on("connection", function (client) {
client.on("join", function(name){
people[client.id] = name;
client.emit("update", "You have connected to the server.");
socket.sockets.emit("update", name + " has joined the server.")
socket.sockets.emit("update-people", people);
});
client.on("send", function(msg){
socket.sockets.emit("chat", people[client.id], msg);
});
client.on("disconnect", function(){
socket.sockets.emit("update", people[client.id] + " has left the server.");
delete people[client.id];
socket.sockets.emit("update-people", people);
});
});
2) chat.html :
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://localhost:1223/socket.io/socket.io.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"> </script>
<script>
$(document).ready(function(){
var socket = io.connect("127.0.0.1:1223");
$("#chat").hide();
$("#name").focus();
$("form").submit(function(event){
event.preventDefault();
});
$("#join").click(function(){
var name = $("#name").val();
if (name != "") {
socket.emit("join", name);
$("#login").detach();
$("#chat").show();
$("#msg").focus();
ready = true;
}
});
$("#name").keypress(function(e){
if(e.which == 13) {
var name = $("#name").val();
if (name != "") {
socket.emit("join", name);
ready = true;
$("#login").detach();
$("#chat").show();
$("#msg").focus();
}
}
});
socket.on("update", function(msg) {
if(ready)
$("#msgs").append("<li>" + msg + "</li>");
})
socket.on("update-people", function(people){
if(ready) {
$("#people").empty();
$.each(people, function(clientid, name) {
$('#people').append("<li>" + name + "</li>");
});
}
});
socket.on("chat", function(who, msg){
if(ready) {
$("#msgs").append("<li><strong><span class='text-success'>" + who + "</span></strong> says: " + msg + "</li>");
}
});
socket.on("disconnect", function(){
$("#msgs").append("<li><strong><span class='text-warning'>The server is not available</span></strong></li>");
$("#msg").attr("disabled", "disabled");
$("#send").attr("disabled", "disabled");
});
$("#send").click(function(){
var msg = $("#msg").val();
socket.emit("send", msg);
$("#msg").val("");
});
$("#msg").keypress(function(e){
if(e.which == 13) {
var msg = $("#msg").val();
socket.emit("send", msg);
$("#msg").val("");
}
});
});
</script>
</head>
<body>
<div class="row">
<div class="span2">
<ul id="people" class="unstyled"></ul>
</div>
<div class="span4">
<ul id="msgs" class="unstyled"></ul>
</div>
</div>
<div class="row">
<div class="span5 offset2" id="login">
<form class="form-inline">
<input type="text" class="input-small" placeholder="Your name" id="name">
<input type="button" name="join" id="join" value="Join" class="btn btn-primary">
</form>
</div>
<div class="span5 offset2" id="chat">
<form id="2" class="form-inline">
<input type="text" class="input" placeholder="Your message" id="msg">
<input type="button" name="send" id="send" value="Send" class="btn btn-success">
</form>
</div>
</div>
</body>
</html>
Run chat.js using command - node chat.js
and run chat.html in browser.
I know it's been 8 years old but I faced the same error, maybe my explanation could help someone.
By "trying to transfer to my live server" I did deploying it to virtual shared hosting that is running Node through Passenger module of Apache. Then I contacted the tech support and they said the script is starting to listen some ports and crashes and it is simply not possible on this type of hosting plan, I should apply for VPS/VDS instead.
It sounds strange because the app did not even start to listen, it's just about accessing static files. But probably the way Express is delivering static files is not working. Logs say:
[pid 66771] 19:33:18 listen(12, 511) = -1 EPERM (Operation not permitted)
events.js:183
throw er; // Unhandled 'error' event
^
I was able to read Express is using "stream" (nodejs.org/api/stream.html) to deliver static files and I have a suggestion it is simply not working on that type of hosting. The other static files are existing physically so they are delivered with Nginx and they do not fail. This makes some surprise as some files are loaded and some give error 500, not even 4xx when the resource can't be located.
Basically response 500 tells us the output unexpectedly ended. The logs say "end of script before headers". It is unpleasant when you can't access any log messages and just receive response 500 and have to contact support to see the logs.

Resources