I am diving into Node.js and have had success installing express and socket. I was able to make the basic chat program easily. This requires these steps:
In app.js (my Node server)
var server = require('http').Server(app);
var io = require('socket.io')(server);
I included minified socket.io.js file in public/javascripts
In public/javascripts/testchat.js simply call IO like this:
var socket = io();
Then do whatever you want with IO stuff.
I've made my own Node.js module but I don't understand how to expose it.
In node_modules/myModule/index.js
module.exports = require('./lib');
In node_modules/myModule/lib/index.js
module.exports = myModule;
function myModule(){
this.name = "hello";
}
myModule.prototype.test = function(){
console.log(this.name);
}
I can call this stuff easily in app.js
var myModule = require('myModule');
var myMod = new myModule.test(); //hello
But I don't want this thing to run every time I start the server. I want to to only run when a user accesses a specific page. How do I get from here to there? I know I am missing something... I was expecting to be able to do this:
In public/javascripts/myModule.js
var myModule = myModule(); //myModule is undefined
myModule.test();
Thank you.
You can request info through socket.io. It tends to be a bit resource intensive to hold the network connection open. Typically, most of the games and apps that we write, either for a mobile app or a web site, call REST APIs that we have written in Express, which is a node.js framework. Essentially you create endpoints that respond to HTTP calls. They send back whatever you want, we normally use JSON to respond with the data. So, you would need to create a RESTful api app, and behind one of the APIs would your module. You call the API with whatever parameters from your web page, and the app responds with your data.
Then of course you need to get into authentication, so only the people you want to have access get it. You've got security and scaling issues. It's a new world.
Related
Our workplace has a shared network drive that everyone in our department has access to without explicitly requiring credentials. The link is something like
myworkplace.com/mydept/archive/etc
Anyone from my department can access this link via file explorer or even their browser. Currently, I use it by calling python scripts that exist on the drive by using
> pushd myworkplace.com/.../python/
> ./python.exe scriptPath/script.py arg1 arg2
The result is that it copies a set of files (arg1) from an SFTP server (arg2) onto this drive for everyone in the department to review via a new link/directory path. Now, I want to create a very basic webpage that others in the department can use to essentially pass arg1 and arg2 as input to this script and by the click of a button run this script themselves.
My research suggests that I should use node.js as client-side webpages cannot interact with the server-side scripts/tools without it. This requires serious network configs which is entirely out of the question as that is not our responsibility and the last thing I would want to do is get an angry email from the networking team. However, if me and others can easily pushd into the drive and run scripts from it, shouldn't there be something just as easy that I can do from a webpage? Maybe I can leverage the network config of the network drive itself?
I also believe that I may be misunderstanding the issue entirely, and that maybe I'm calling the script from the drive but actually running it locally, but my knowledge on networking is very slim so I'm not exactly sure what is really possible here. Any suggestions?
So I was able to solve this rather simply
When I pushd into the network drive I can run the command
ipconfig
which returns the IP address of the drive. I used that as the host name and used port 8080. When running the node.js script I made sure to use those details as below
const express = require("express");
const app = express();
const host = '11.111.111.111';
const port = 8080;
app.get('/Home', (req,res) => {
res.sendFile(<UNC Network path to HTML landing page >)
})
app.listen(port, host, () => console.log(`App listening on port ${port}`))
When my colleagues and I typed '11.111.111.111:8080/Home' into our browser we were able to access the page and it's contents. I think this is the standard protocol for creating a website and I may have simply misunderstood the requirements.
The rendered HTML page contained a button that would call a different function in my node.js script which returned the output from my python script. See below
function myFunc(arg1, arg2){
const spawner = require('child_process');
const path = require('path');
var dataToRead;
//declare path to python executable
const python_exe = path.resolve(<UNC path> + 'python/python.exe');
//declare path to python script
const python_py = path.resolve(<UNC path> + 'script.py');
//create a process on server side calling the python executable to initiate python
//and pass the script and arguments as a list of paramaters
const python_call = spawner(python_exe, [python_py, arg1, arg2]);
//read the output from python script
python_call.stdout.on('data', (data) => {
dataToRead = data.toString();
}
}
And that's how I used a network drive to create a webapp that calls a python script and retrieves the results
P.S. I could not change the website name to be a string as that would require configuring the DNS to point to this IP and port, which is not something folks outside the network team have access to.
I have a Python script that I have written that an utilizes an API to retrieve weather information, its just a simple terminal print script for right now. I am starting to learn more about HTML/JS and am wondering where I could start to learn how to pass information from my web pages to scripts.
Eventually what I am trying to work towards is passing a zip code string input from an HTML form over to my Python script on my local machine, and then have the script return data to my webpage.
The problem is, I have no idea where to start, or where even to start looking for information. For example, I understand that you can pass values to a server side application & that is kinda what I'm simulating here.
If you want to run your python script from your websites, you could use a server for that. Given that you are already into Javascript, I suggest that you create a server using a popular JS framework called Express. Express is designed for NodeJS, a JS runtime.
Once you setup your Express server, you can start creating routes and integrate them into your websites by making asynchronous calls with utilities like fetch or axios. For example, you can create a sample app like this:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.use('/run-script', function (req, res) {
res.send('Script run!');
};
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
If you look closer, app.use() allows you to define routes. When a user or a JS script calls this route, the function gets executed. For example, inside the route run-script you could execute yours:
app.use('/run-script', function(){
const spawn = require("child_process").spawn;
const pythonProcess = spawn('python',["path/to/script.py", arg1, arg2, ...]);
});
As you see, there are numerous possibilities. For more info on calling python scripts from node, see this stackoverflow question.
You could start digging into NodeJS in general. For that, a good place to start is the official guides.
Please let me know if this answer was useful to you.
I'm an html5 developer with mainly JavaScript experience. I'm starting to learn the backend using Node.js. I don't have a particular example of this question/requirements. I'd like to call a back end function with JavaScript, but I'm not sure how. I already researched events and such for Node.js, but I'm still not sure how to use them.
Communicating with node.js is like communicating with any other server side technology.. you would need to set up some form of api. What kind you need would depend on your use case. This would be a different topic but a hint would be if you need persistent connections go with web sockets and if you just need occasional connections go with rest. Here is an example of calling a node function using a rest api and express.
var express = require('express');
var app = express();
app.post('/api/foo', foo);
function foo(req, res){
res.send('hello world');
};
app.listen(3000);
From the frontend you can post to this REST endpoint like so.
$.post("/api/foo", function(data) {
console.log( "Foo function result:", data );
});
If you're just starting with node-js, don't worry about Websockets just yet.
You're going to want to create a REST API (most likely) depending on what you're trying to accomplish. You can put that REST API behind some kind of authentication if desired.
A REST API is going to have endpoints for creating/deleting/updating and getting (finding) a document, like a given user.
My recommendation is to work backwards from something that's already working. Clone this app locally and check out the controllers to see examples of how this application interacts with creating users.
https://github.com/sahat/hackathon-starter
Once you create a controller that returns data when a client hits an endpoint (like http://localhost:3000/user/create ) , you'll want to create some HTML that will interact with endpoint through a form HTML element. Or you can interact with that endpoint with Javascript using a library like jQuery.
Let me know if that makes sense to you. Definitely a good starting point is to clone that app and work backwards from there.
Can I suggest trying api-mount. It basically allows calling API as simple functions without having to think about AJAX requests, fetch, express, etc. Basically in server you do:
const ApiMount = apiMountFactory()
ApiMount.exposeApi(api)
"api" is basically an object of methods/functions that you are willing to call from your web application.
On the web application you then do this:
const api = mountApi({baseUrl: 'http://your-server.com:3000'})
Having done that you can call your API simply like this:
const result = await api.yourApiMethod()
Try it out. Hope it helps.
I've been building a web-socket application in which the client opens a link to a game instance, and then the server attempts to connect the client to the respective Socket.io room on which the game will transmit information. For example, connecting to '/game/abc' would load up the game page and connect the socket on the page to the 'abc' room on the server.
The problem with this is getting the client JavaScript file to emit the game ID and the username of the user connecting. I want it to act in the following way:
Client.js
var socket = io();
socket.emit("newUser", username, gameID);
I have managed to accomplish this by passing both my client.html and client.js page through an Express template renderer:
Server.js
app.get(/^\/game\/([a-zA-Z0-9]*)$/, function(req, res){
var game = req.params[0];
var user = req.session.name; //gets username stored in session
res.render("client.html", {username: user, gameName: game});
});
app.get(/game\/(.*)\/client.js/, function(req,res){
res.render("client.js", {username: req.session.name, gameName: req.params[0]});
});
The second app.get() allows for the gameName to be passed along to client.js through client.html in the form of a parameter in the url.
Client.html
<script src="{{gameName}}/client.js"></script>
Finally after two passes, the game ID and username both are put into client.js by the template engine.
Client.js
var socket = io();
socket.emit("newUser", "{{username}}", "{{gameName}}");
//leads to socket.emit("newUser", "user", "abc"); when passed through renderer
Although this gets the job done, it feels incredibly convoluted and indirect. I've looked up alternatives to this, with the answer at node.js express rendering inside included js files recommending to use AJAX calls. However, I have not been able to figure out how to exactly configure such an AJAX call. Is there a more effective way to overcome this problem?
You can simplify all of this and avoid rendering the templates in Express to pass that variable in this case.
You already have the gave name available to your client-side code in the window.location object. You can either parse it manually with a simple regex (in this case) or you can use something that is called a client-side router which there are a lot to choose from.
There is one simple client-side router inspired by Express.js: Page.js, which would allow you to use a very similar code that you use right now in Express.
Many client-side frameworks have routers build in.
I am writing a web app in node.js. Now every processing on the server is always in the context of a session which is either retrieved or created at the very first stage when the request hits the server. After this the execution flows through multiple modules and callbacks within them. What I am struggling with is in creating a programming pattern so that at any point in the code the session object is available without the programmer requiring it to pass it as an argument in each function call.
If all of the code was in one single file I could have had a closure but if there are function calls to other modules in other files how do I program so that the session object is available in the called function without passing it as an argument. I feel there should be some link between the two functions in the two files but how to arrange that is where I am getting stuck.
In general I would like to say there is always a execution context which could be a session or a network request whose processing is spread across multiple files and the execution context object is to be made available at all points. There can actually be multiple use cases like having one Log object for each network request or one Log object per session. And the plumbing required to make this work should be fitted sideways without the application programmer bothering about it. He just knows that that execution context is available at all places.
I think it should fairly common problem faced by everyone so please give me some ideas.
Following is the problem
MainServer.js
app = require('express').createServer();
app_module1 = require('AppModule1');
var session = get_session();
app.get('/my/page', app_module1.func1);
AppModule1.js
app_module2 = require('AppModule2');
exports.func1 = function(req,res){
// I want to know which the session context this code is running for
app_module2.func2(req,res);
}
AppModule2.js
exports.func2 = function(req,res){
// I want to know where the session context in which this code is running
}
You can achieve this using Domains -- a new node 0.8 feature. The idea is to run each request in it's own domain, providing a space for per-request data. You can get to the current request's domain without having to pass it all over via process.domain.
Here is an example of getting it setup to work with express:
How to use Node.js 0.8.x domains with express?
Note that domains in general are somewhat experimental and process.domain in particular is undocumented (though apparently not going away in 0.8 and there is some discussion on making it permanent). I suggest following their recommendation and adding an app-specific property to process.domain.data.
https://github.com/joyent/node/issues/3733
https://groups.google.com/d/msg/nodejs-dev/gBpJeQr0fWM/-y7fzzRMYBcJ
Since you are using Express, you can get session attached to every request. The implementation is following:
var express = require('express');
var app = express.createServer();
app.configure('development', function() {
app.use(express.cookieParser());
app.use(express.session({secret: 'foo', key: 'express.sid'}));
});
Then upon every request, you can access session like this:
app.get('/your/path', function(req, res) {
console.log(req.session);
});
I assume you want to have some kind of unique identifier for every session so that you can trace its context. SessionID can be found in the 'express.sid' cookie that we are setting for each session.
app.get('/your/path', function(req, res) {
console.log(req.cookies['express.sid']);
});
So basically, you don't have to do anything else but add cookie parser and enable sessions for your express app and then when you pass the request to these functions, you can recognize the session ID. You MUST pass the request though, you cannot build a system where it just knows the session because you are writing a server and session is available upon request.
What express does, and the common practice for building an http stack on node.js is use http middleware to "enhance" or add functionality to the request and response objects coming into the callback from your server. It's very simple and straight-forward.
module.exports = function(req, res, next) {
req.session = require('my-session-lib');
next();
};
req and res are automatically passed into your handler, and from their you'll need to keep them available to the appropriate layers of your architecture. In your example, it's available like so:
AppModule2.js
exports.func2 = function(req,res){
// I want to know where the session context in which this code is running
req.session; // <== right here
}
Nodetime is a profiling tool that does internally what you're trying to do. It provides a function that instruments your code in such a way that calls resulting from a particular HTTP request are associated with that request. For example, it understands how much time a request spent in Mongo, Redis or MySQL. Take a look at the video on the site to see what I mean http://vimeo.com/39524802.
The library adds probes to various modules. However, I have not been able to see how exactly the context (url) is passed between them. Hopefully someone can figure this out and post an explanation.
EDIT: Sorry, I think this was a red-herring. Nodetime is using the stack trace to associate calls with one another. The results it presents are aggregates across potentially many calls to the same URL, so this is not a solution for OP's problem.