I've been looking over this basic example in order to set up a simple server in Node, however I am really struggling to understand where the 'request' and 'response' parameters are coming from. Where do they point to and how?
// Load the http module to create an http server.
var http = require('http');
function onRequest(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("Hello World\n");
}
// Configure our HTTP server to respond with Hello World to all requests.
var server = http.createServer(onRequest);
// Listen on port 8000, IP defaults to 127.0.0.1
server.listen(8000);
Usually when passing paramaters into a function I pass something I can see, like a variable equal to 5, or 'Hello', but in this case I'm not...
Sorry if this is not explained very well!
When you call createServer, you are passing the function onRequest to it:
var server = http.createServer(onRequest);
This pattern is known as a callback: you pass a function to someone else, with the expectation that they will call your function if something interesting has happened.
In essence, you are saying to Node,
Hey, please create an HTTP server for me. Whenever you receive a request, call my function onRequest with the request and response objects passed as parameters.
Another way to do this is to listen to the request event, which takes the same parameters in its callback.
The parameters are documented as being http.IncomingMessage and http.ServerResponse. You can call them whatever you want, but request and response are the idiomatic parameter names. (Some people use req and res because they are shorter to type.)
Create server and send response :
1).Create server
var http = require('http');
var server = http.createServer ( function(request,response){
response.writeHead(200,{"Content-Type":"text\plain"});
response.end("Hello");
});
server.listen(8000);
console.log("Server running on port 8000");
2).Save above code and run in cmd .
3).Open browser and go to http://localhost:8000/
Now you see the "Hello"
Related
I'm using Express (v4.17.3), Socket.io, and Node.Js's http module. I'm adding a middleware for express to capture all incoming requests but that's failing.
I'll first show the code I'm using and the output then explain my understanding/expectation of the output (I'm new to Node and all the mentioned libraries so perhaps I'm missing something)
First of all, below is the code I'm referring to. Using Express's middleware I'm trying to capture all the incoming requests and log them, and doing the same for the http on("request"). However, requests going to socket.io aren't captured by the middleware.
// Express
const express = require("express");
const app = express()
// Socket
const server = require('http').createServer(app);
const {Server} = require("socket.io");
const io = new Server(server)
// Want to listen to all incoming requests using the middleware (this doesn't work)
app.use((req,res,next)=>{
console.log(`Express request = ${req.url}`)
next()
})
// Listening to all incoming requests (this works)
server.on("request", (req, res)=>{
console.log(`Http request = ${req.url}`)
})
server.listen(8080, () => {
console.log(`Listening on port 8080`)
})
output when I GET /
Express request = /
Http request = /
Http request = /socket.io/socket.io.js
Http request = /socket.io/?EIO=4&transport=polling&t=O0va...
Http request = /socket.io/?EIO=4&transport=polling&t=O0va24A&sid=c...
Http request = /socket.io/?EIO=4&transport=polling&t=O0va24F&sid=c...
Http request = /socket.io/?EIO=4&transport=polling&t=O0va27x&sid=c...
My expected output is to have equal logs for the middleware app.use() and on("request") ("Express request = " & "Http request = ")
My understanding:
1- When I add a middleware for express as in the code below, any incoming requests should be captured here first before going anywhere else. (correct?)
app.use((req,res,next)=>{...})
2- When I'm passing the express app as an argument to http'screateServer, that the express app will be treated as a listener and any request events will be passed to it. (correct?)
const server = require('http').createServer(app);
So if my understanding is correct, why aren't all the requests captured by the request event passed to the middleware as well?
This is normal. Socket.io puts itself in front of express (or any other listener for incoming requests on the http server) so that it takes the request before Express sees it. Thus, Express (or it's middleware) never see any socket.io connection requests.
Socket.io has its own middleware layer that you can use to participate in the initialization of socket.io requests.
Or, you can register for incoming socket.io connections (to be called after they are already connected) with the io.on('connection', ...) event handler.
When I add a middleware for express as in the code below, any incoming requests should be captured here first before going anywhere else. (correct?)
That is true except for code that registers directly request handlers right on the http server and inserts itself before Express in the listener chain, thus preventing Express from seeing any requests that are destined for socket.io.
When I'm passing the express app as an argument to http'screateServer, that the express app will be treated as a listener and any request events will be passed to it. (correct?)
That is true. But socket.io jumps in front of Express and takes/hides any requests it wants so that Express never sees them.
If you're curious, here's the socket.io code that jumps in line to the front of all listeners for the http server thus bypassing the express listener:
attachServe(srv) {
debug("attaching client serving req handler");
const evs = srv.listeners("request").slice(0);
srv.removeAllListeners("request");
srv.on("request", (req, res) => {
if (this.clientPathRegex.test(req.url)) {
this.serve(req, res);
}
else {
for (let i = 0; i < evs.length; i++) {
evs[i].call(srv, req, res);
}
}
});
}
It grabs all the existing listeners into an array. Then, it removes them all. Then, it registers for the request event itself and, if it is a socket.io request, then it does not call the prior listeners. If it is not a socket.io prefix, then it manually calls the prior listeners.
I believe you need to log the messages sent on socket.
io.on('connection', (socket) => { socket.on('chat message', (msg) => { console.log('message: ' + msg); }); });
Situation
I have a html page which calls multiple javascript files. Everything works on client-side right now.
Because I need to execute a jar within javascript, I am switching to Node.js. (applets are deprecated)
However, I am new to node.js and confused about how to link everything.
I have :
index.html which calls various .js scripts (files.js,objects.js,etc.)
webServer.js which makes the node.js server
var http = require('http');
var fs = require('fs');
http.createServer(function (req, res) {
fs.readFile('index.html', function(err, data) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(data);
res.end();
});
}).listen(8080);
javaApp.js which executes a jar
var exec = require('child_process').exec;
var child = exec('java -jar E:/JavaApp.jar',
function (error, stdout, stderr){
console.log('Output -> ' + stdout);
if(error !== null){
console.log("Error -> "+error);
}
});
module.exports = child;
The question
I would like, when clicking on a button in my html, to call javaApp.js on the server side.
I know Express can be used to link index.html to webServer.js, but I don't understand how to link index.html to the code used by the server.
i.e. How can I call javaApp.js from index.html if there's no function name in it?
Is this answer relevant ? How to call node.js server side method from javascript?
If you want to call the jar on the server you have to create a route for it(maybe using express).
router.get('/call-java-app', function (req, res, next){
//call you function in here
//respond with any data you want
res.send('Your data here');
});
Your button would have to make a get request at /call-java-app and optionally wait for any response from the server.
var url = '/call-java-app';
console.log(url);
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState === 4) {
//handle server response here if you want to
}
}
xmlHttp.open("GET", url, true); // false for synchronous request
xmlHttp.send(null);
How can I call javaApp.js from index.html if there's no function name in it?
You can't. At least not sensibly.
Change it so it exports a function you can call if you want to call it multiple times.
Since it is asynchronous, you should make that function return a Promise.
In your webserver, require the module you write to get access to the function it exports.
Write a route which calls that function and returns a suitable HTTP response.
Then cause the browser to make an HTTP request to that route by clicking a link, submitting a form, using fetch, or whatever other method you like.
Your webserver is now as simple as it (almost) can be. Just sending index.html when the ip+port 8080 is called with http (get).
Before you can use your jar-module you have to make a requiere in your webserver:
var child = require('javaApp')
This will give you access to "child" wrappet with a error-function. What "child" actual is doing and can do, you probably know (i hope). If you skip the index.html you can send some response from your "child" to see how it works.
Say I have this code in node.js:
app.post('/stuff', function(req, res){
res.send('hello world');
});
app.route('*').all(function(req,res,next){
res.write('Hello World');
});
There are 2 routes here - one is a catch-all for any request to the server and the other is what to do if a post request with a route of /stuff is sent.
Is it possible to pass a value local to the post request into route?
Intended Program flow: initial request to the server goes through route (which has controls not illustrated to ignore post requests) and the connection is left open, then a post request is sent from the initial request and is dealt with by app.post - can a value found within the closure of post be passed to the initial request that is still open?
I am trying to avoid using Global variables, and res.local only has a local scope. Also trying to keep clean so if I can use native express or node.js all the better. Much obliged for any help.
then a post request is sent from the initial request
Why don't you simply pull out the POST function and call it from both handlers, that way you don't need to send a seperate request from inside your app.
var postHandler = function(req, res) {
res.send('hello world');
// Just return whatever you want back to the calling function
return someValue;
};
// Set it as the handler for post.
app.post('/stuff', postHandler);
app.route('*').all(function(req,res,next){
// Call function.
var returnValue = postHandler(req, res);
res.write('Hello World');
});
app.route('*').all(function(req,res,next){
if (req.originalUrl === '/stuff') {
req.variable = 'some value';
return next();
};
res.write('Hello World');
});
app.post('/stuff', function(req, res){
var value = req.variable;
res.send('hello world');
});
You can try this code. Please take the order of app.all and app.post.
The second way, your can try app.locals http://www.expressjs.com.cn/4x/api.html#app.locals
The app.locals object is a JavaScript object, and its properties are
local variables within the application.
Inspired by How to share sessions with Socket.IO 1.x and Express 4.x? i implemented socket authentication in some "clean" way where is no need to use cookie-parser and to read cookies from headers, but few items remain unclear to me. Example use last stable socket.io version 1.3.6.
var express = require('express'),
session = require('express-session'),
RedisStore = require('connect-redis')(session),
sessionStore = new RedisStore(),
io = require('socket.io').listen(server);
var sessionMiddleware = session({
store : sessionStore,
secret : "blabla",
cookie : { ... }
});
function socketAuthentication(socket, next) {
var sessionID = socket.request.sessionID;
sessionStore.get(sessionID, function(err, session) {
if(err) { return next(err); }
if(typeof session === "undefined") {
return next( new Error('Session cannot be found') );
}
console.log('Socket authenticated successfully');
next();
});
}
io.of('/abc').use(socketAuthentication).on('connection', function(socket) {
// setup events and stuff
});
io.use(function(socket, next) {
sessionMiddleware(socket.request, socket.request.res, next);
});
app.use(sessionMiddleware);
app.get('/', function(req, res) { res.render('index'); });
server.listen(8080);
index.html
<body>
...
<script src="socket.io/socket.io.js"></script>
<script>
var socket = io('http://localhost:8080/abc');
</script>
</body>
So io('http://localhost:8080/abc'); from client-side will send initial HTTP handshake request to server, from where server can gather cookies and many others request informations. So server has access to that initial request via socket.request.
My first question is why handshake request is not in scope of express-session middleware?(More generally in scope of app.use middlewares?) In some way i expected this app.use(sessionMiddleware); to fire before that initial request, and then to access easily to socket.request.session
Second, what are the scenarios in which middlewares defined with io.use() will fire? Only for initial HTTP handshake request? It seems like io.use() is used for socket related stuff(question is: what stuff), while app.use for standard requests.
I'm not quite sure why in the above example io.use() is fired before io.of('/abc').use(). Intentionally i wrote that order putting io.of('/abc').use() first to see will it work and it work.
Should have been written conversely.
Lastly, socket.request.res like pointed also from some people in linked question, sometimes is undefined causing app to broke, problem can be solved by providing empty object instead of socket.request.res, like: sessionMiddleware(socket.request, {}, next); which seems to me like a dirty hack. For what reasons socket.request.res yield to undefined?
Despite #oLeduc is kind of correct, there are a few more things to explain..
Why the handshake's request is not in scope of express-session middleware?
The biggest reason here is that the middleware in express is designed to handle request specific tasks. Not all, but most of the handlers use the standard req, res, next syntax. And sockets are "request-less" if I can say. The fact that you have socket.request is due to the way the handshake is made, and that it is using HTTP for that. So the guys at socket.io hacked that first request into your socket class so that you can use it. It was not designed by the express team to ever work with sockets and TCP.
What are the scenarios in which middlewares defined with io.use() will fire?
io.use is a close representation of the express use middleware way. In express, the middleware is executed on each request, right? But sockets do not have requests and it will be awkward to use middleware on each socket emit, so they've made it to be executed on each connection. But as well as the express middleware is stacked and used before the actual request is handled (and responded), Socket.IO uses the middleware on connection and even before the actual handshake! You can intercept the handshake if you want to, using that kind of middleware, which is very handy (in order to protect your server from spamming). More on this can be found in the code of passport-socketio
Why io.use() fires before io.of('/abc').use()?
The real explanation on this can be found here, which is this code:
Server.prototype.of = function(name, fn){
if (String(name)[0] !== '/') name = '/' + name;
if (!this.nsps[name]) {
debug('initializing namespace %s', name);
var nsp = new Namespace(this, name);
this.nsps[name] = nsp;
}
if (fn) this.nsps[name].on('connect', fn);
return this.nsps[name];
};
And in the beginning of the code, there is this line of code:
this.sockets = this.of('/');
So, there is a default namespace created at the very beginning. And right there, you can see that it has immediately a connect listener attached to it. Later on, each namespace gets the very same connect listener, but because Namespace is EventEmitter, the listeners are added one after another, so they fire one after another. In other words, the default namespace has it's listener at first place, so it fires first.
I don't think this is designed on purpose, but it just happened to be this way :)
Why is socket.request.res undefined?
To be honest, I'm not pretty sure about that. It's because of how engine.io is implemented - you can read a bit more here. It attaches to the regular server, and sends requests in order to make a handshake. I can only imagine that sometimes on errors the headers are separated from the response and that's why you won't get any. Anyways, still just guessing.
Hope information helps.
Why the handshake's request is not in scope of express-session middleware?
Because socket.io will attach to a http.Server which is the layer under express. It is mentioned in a comment in the source of socket.io.
The reason for this is because the first request is a regular http request used to upgrade the reqular stateless http connection into a state-full websocket connection. So it wouldn't make much sense for it to have to go through all the logic that applies to regular http requests.
What are the scenarios in which middlewares defined with io.use() will fire?
Whenever a new socket connection is created.
So every time a client connects it will call the middlewares registed using io.use(). Once the client is connected however, it is not called when a packet is received from the client. It doesn't matter if the connection is initiated on a custom namespace or on the main namespace, it will always be called.
Why io.use() fires before io.of('/abc').use()?
Namespaces are a detail of socket.io's implementation, in reality, websockets will always hit the main namespace first.
To illustrate the situation, look at this snippet and the output it produces:
var customeNamespace = io.of('/abc');
customeNamespace.use(function(socket, next){
console.log('Use -> /abc');
return next();
});
io.of('/abc').on('connection', function (socket) {
console.log('Connected to namespace!')
});
io.use(function(socket, next){
console.log('Use -> /');
return next();
});
io.on('connection', function (socket) {
console.log('Connected to namespace!')
});
Output:
Use -> /
Main namespace
Use -> /abc
Connected to namespace!
See the warning that the socket.io team added to their documentation:
Important note: The namespace is an implementation detail of the Socket.IO protocol, and is not related to the actual URL of the underlying transport, which defaults to /socket.io/….
Why is socket.request.res undefined?
As far as I know it should never be undefined. It might be related to your specific implementation.
I am working on the node js project and in which I have to forward request from one port to another port using proxy server, code available on net is not working or might be I am going wrong some where so please help me. with the working code which i can customize as per my requirement.
I have used code from Node.js - forward all traffic from port A to port B
also tried for the code :
var util=require('util');
var net=require('net');
var input=net.createServer(function(inputStream){
inputStream.on('data', function(data) {
util.puts(data);
});
var output=net.createServer(function(outputStream) {
outputStream.pipe(inputStream, {end: false});
outputStream.on('data',function(dta){
util.puts(dta);
});
});output.listen(7000, 'localhost');
});input.listen(6999, 'localhost');
This code which i have used in my application actually i have take requst from one port identify request according to param and forward to another port.
Try this, in the function handle request, function(req, res):
var request = require('request');
//forward the request
request({
uri : 'http://localhost:anotherPort'+req.url,
method : req.method
}).pipe(res);