I'm new to Nodejs and here I have a piece of code in app.js :
var config = require('./config')
, express = require('express')
, db = require('./app/lib/db')
, utils = require('./app/lib/utils')(config, db)
var app = express()
http = require('http').createServer(app)
require('./config/express')(app, config)
require('./config/routes')(app, utils, model_list)
http.listen(config.port, function () {
console.log("API running at http://" + config.hostname)
})
And a list of router api are set up in the file config/routes, for example:
app.get('/api/' + name + '/:limit([0-9]+)/:page([0-9]+)', ctrls[name].list); // get list with page
app.get('/api/' + name, ctrls[name].list); // get list with default page = 1
app.post('/api/' + name + '/search', ctrls[name].search); // search
app.get('/api/' + name + '/:id([0-9a-f]+)', ctrls[name].get); // get by id
After the server is created and starts to listen to the config port, what is the execution flow of a new request when it hits the server? How can the server catch a request in app.js and then move to routes.js to route it to a function to handle it?
It does not move to routes.js... routes.js is required inside app.js and it applies the routes to the app object which is the express server. That is done once, before the server starts listening to port.
How express routes the request when it receives one is completely done internally. Basically it will check the request method (GET, POST, etc) then will check the requested URI and try to match a route, if the route matches, the function is executed.
you should check the anatomy of http in nodejs.
https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/
Related
I am creating rest web service using express nodejs framework. I want to navigate to second.js page from first.js and need to send data and header to it.
first.js
const express = require("express");
const http = require("http");
var router = express.Router();
var options = {
host: "localhost",
port: "3000",
path: "/second",
method: "POST"
};
router.get("/", function(req, res, next) {
http.request(options);
});
module.exports = router;
second.js
var express = require("express");
var router = express.Router();
router.get("/", function(req, res, next) {
res.send("Hello");
});
module.exports = router;
app.js
app.use("/first", first);
app.use("/second", second);
I tried like above but it doesn't navigate to second.js web service. Does anyone know what I am doing wrong ?
Your code is not performing a redirection. You are actually making a call from within the first endpoint to a second endpoint and acting more like a proxy.
A redirection is performed by calling res.redirect as defined in the express documentation at http://expressjs.com/en/api.html (Search for res.redirect). A redirection returns a HTTP redirect response that the users browser will follow to a new URL. Unfortunately, redirections do not allow headers to be passed and it will be executed as a GET call(This is what redirections are designed for.). You can include whatever query params you want in the URL though and set cookies (refer to How to forward headers on HTTP redirect)
I think you are using POST in your request
But only set up GET on your second endpoint
have a server that uses socket.io. When a user connects it will assign them the user id thats made on the server then increment it by 1 so the next user with have a different id.
I want to use cookies for this, to check if they have previously logged in, if so, use that id, if not, use the one on the server.
the way to create a cookie is by using
res.cookie('cookie', 'monster')
but im not where i would put it, i tried putting it in the connect function but res wouldnt exist. and if i put it outside the function, how would i call it? Here is my code. This is the start of my server:
//Require npm modules
var express = require('express');
var http = require('http');
var events = require('events');
var io = require('socket.io');
var ejs = require('ejs');
var app = express();
//Set the default user Id to 1 and the default username to Guest
exports.Server = Server = function()
{
this.userId = 1;
this.userName = "Guest";
};
app.set('view engine', 'ejs');
app.get('/game/:id', function (req, res)
{
res.render('game', {game: req.params.id});
});
Server.prototype.initialise = function(port)
{
//Create the server using the express module
this.server = http.createServer(app);
//Declare the 'public' folder and its contents public
app.use(express.static('public'));
//Listen to any incoming connections on the declared port and start using websockets
this.server.listen(port);
this.startSockets();
this.em = new events();
consoleLog('SERVER', 'Running on port: ' + port);
};
Server.prototype.startSockets = function()
{
//When a user connects to the server on the 'game' socket
this.socket = io.listen(this.server);
this.socket.of('game').on('connection', function(user)
{
res.cookie('cookie', 'monster')
//Set their usedId and username
user.userId = this.userId;
user.userName = this.userName + " " + this.userId;
//Increment the user id by 1 so each user with get a unique id
this.userId++;
//Send a response back to the client with the assigned username and user id and initialise them
user.emit('connected', user.userId, user.userName);
this.em.emit('initialiseUser', user.userId, user.userName);
So where i have the res.cookie is where i want to be able to read and write cookies, any help is appriciated
I think what you are looking for is the middleware pattern employed by express. You can define as many of these middleware calls as you wish, and they are the perfect scope for calling any other functions which may need the res instance (or the req instance for that matter).
app.use(function (req, res, next) {
// call function, passing in res here
next();
})
Reference: https://expressjs.com/en/guide/using-middleware.html
EDIT:
This answer is not correct for your situation. In a node/express server not using socket connections, then yes, you could easily use the above pattern anywhere you need the request and response objects in scope.
However, once you setup the socket io server, the game changes. During the socket communications, there are no express request and response objects in scope anymore, everything is handled directly between your socket handling code and the client. So the answer is you need to handle the situation in a socket io way, not in an express way.
Please see: Adding a cookie value on Socket.IO
So the client makes a get request using a button on the index page. This sends some information to a route which has been set up as follows:
app.js
var route = require('./routes/index');
var button = require('./routes/button');
app.use('/', index);
app.use('/button', button);
The request is sent from a client-side directory to the node framework whenever someone presses the button. If the request is sent to 'localhost:port/button', then the button.js file mentioned above will receive the request. So in the button.js file we have something like the following:
var express = require('express');
var router = express.Router();
var someData = '';
router.get('/', function (req, res, next) {
//make a get request here such that someData
//receives whatever the request returns from another
//set up framework(i.e. Spring...)
someData = getRequest('some other URL');
res.send(someData);
};
module.exports = router;
The problem here is that the getRequest('some other URL') within the router get request never receives any information.
Also (as a side-note), I cannot seem to find in the express API as to why we have
router.get('/')...
instead of
router.get('/button')...
to access and make requests to the button page.
Any help would be very much appreciated!
You want to make a request to some other REST API running somewhere else right?
You can use node-rest-client for that.
I guess you are confusing what is server code and client code or do I´m missing something?
I´ll try to explain the way it works:
Server code:
var express = require('express');
var router = express.Router();
var someData = '';
router.get('/yearStations/:id', function (req, res, next) {
//make a get request here such that someData
//receives whatever -the id parameter- the request returns from another
//This is express.js
someData = getYourDataFromDataBase(req.params.id);
res.send(someData);
};
module.exports = router;
Client code:
JS (angular.js)
$scope.getInfo = function() { //here you make the GET call to the server
$http.get("http://localhost:XXXX/yearStations/Spring").then(
function(success){
alert(success.data);//this should be your data
});
};
HTML
<button ng-click="getInfo()">getInfo</button>
I'm attempting to validate that my client can post info to it's server. I've set up this 'route' in my Express server.
// server.js this is the server for the PvdEnroll application.
//
var express = require("express"),
http = require("http"),
mongoose = require( "mongoose" ),
app = express();
// static file directory for default routing
app.use(express.static(__dirname + "/client"));
app.use(express.urlencoded());
// create Express-powered HTTP server
http.createServer(app).listen(3000);
console.log("Server listening at http://127.0.0.1:3000/");
// set up a post route in the server
app.post("/selections", function (req, res) {
console.log("data has been posted to the server!");
});
app.post("/selections", function (req, res) {
console.log("Some data has been posted to the server from app.js");
})
The client uses this file:
var main = function () {
"use strict";
$.getJSON("../data/checkBoxesA.json", function(checkBoxTxt) {
checkBoxTxt.forEach(function (data) {
var $checkbox = "<input type ='checkbox' name = "
+ data.label + "id = 0 UNCHECKED/>";
$(".enroll_actions").append($checkbox);
$(".enroll_actions").append(' ' + data.label + "<br/>");
$(".enroll_actions").append(' ' + data.note + "<br/>");
$(".enroll_actions").append(' '+ "<br/>");
});
});
$(".comment-input").on("click", function (event) {
console.log("Hello World!");
// here we'll do a post to our selections route
$.post("selections", {}, function (response) {
console.log("Client says - We posted and the server responded!");
console.log("Response from server :", response);
console.log("STUBB1");
});
});
console.log("STUBB2");
};
$(document).ready(main);
In the Chrome console I'm getting:
POST file:///Users/*******/Projects/r_PE/app/PvdEnroll/client/html/selections net::ERR_FILE_NOT_FOUND
A path is being sought but a tutorial's example (which works!) and is structurally identical to mine(?) uses a name i.e. "selections" to establish a route between client and server.
I'm running the server on my Mac using Virtual Box and Vagrant.
Thanks for any clarification.
On restarting the server the log message is now "POST 127.0.0.1:3000/html/selections 404 (Not Found).
Okay. This is some helpful information!
Basically, your file structure is more or less this (some file names will be different, just look at the general structure):
Node.js code (including main .js file and the module.json)
client: a folder for your static content
html: a folder
index.html: the file you are currently using
Anyway, jQuery.post() is fed a relative path (as apposed to an absolute path). That means that, based on the location of where the code was, it will "guess" the location of the file.
That means that it was trying to find a route at [locahost:port]/html/selections when your server is listening at [localhost:port]/selections! You'll need to have jQuery post to /selections instead of just selections.
For more information, this blog post is helpful (relative paths work the same in Javascript/CSS). The helpful snippet:
Here is all you need to know about relative file paths:
Starting with "/" returns to the root directory and starts there
Starting with "../" moves one directory backwards and starts there
Starting with "../../" moves two directories backwards and starts there (and so on...)
To move forward, just start with the first subdirectory and keep moving forward
I am building a webservice, for which i am using nodejs, phantomjs and expressjs. I am learning all the three.
I want to serve a delayed response to the clients after processing their query. Like for example,
I am processing certain inputs from my client, then, i want to process the data at the backend which will take approx 10 sec on an avg. Then i wanted to serve this page to the client.
Is it possible in node to send multiple responses to the same request or delayed responses so that the template will automatically update the contents.
Or , should i use the same method , like store the json in a file in the server , then serve the page with ajax which will query the page.
please help me. here is the code which i wrote ,
app-server.js(the main file):
// import express module
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
// define all required template files to be served and also define the template engine
app.engine('.html', require('ejs').__express);
app.set('views', __dirname + '/views');
app.set('view engine', 'html');
// Useful modules
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
// import the routes
require('./router')(app);
app.listen(8080);
router.js:
var crypto = require('crypto');
var express = require('express');
module.exports = function (app) {
// define the static routes.
app.use('/static', express.static('./static'));
app.use('/media', express.static('./media'));
//defining the controller.
var parserlib = require('./controller.js')
// Define the home root path
app.get('/', function (req, res) {
// shows the home search page.
res.render('index', {content:'template success'});
});
app.get('/search', function(req, res){
res.redirect('/');
});
app.post('/search', parserlib.parserlib);
}
controller.js:
var crypto = require('crypto');
var path = require('path')
var childProcess = require('child_process')
exports.parserlib= function(req, res){
var output = '';
var url = req.body.search_url;
var childArgs = [
path.join(__dirname, 'external-script.js'),
url,
]
// execute the script in a separate thread.
childProcess.execFile(binPath, childArgs, function(err, stdout, stderr) {
// handle results
console.log(stdout);
output = stdout;
//console.log(err);
//res.send(output);
});
//res.send(output);
};
so , what i want to see is, first send a response to client stating that its loading, then i want to update the with processed data. In other languages its not possible to send multiple responses. Not sure about nodejs.
Also, do i have to store the json output from the processed lib to a file and then use ajax to query ? or is it possible to directly update the json object to the client ?
Thanks
This is just not how HTTP works. The clients won't expect it. This has nothing to do with Node or any other framework. The way to do what you're attempting is to actually send a response that the thing is loading, and then have some other mechanism for reporting state.
As an example, you might design a RESTful API. In that RESTful API you might define a endpoint for creating new things:
POST /api/things
The client would post data to that to create a new thing. The response should be something that provides a location of the newly created resource, for example an HTTP 301 to /api/things/1.
If the user goes to /api/things/1 and the thing isn't done getting made yet, then you can either do a temporary redirect (303) to /api/things/1/status which provides some helpful status information, or just issue a 404.
If you actually want to send back server-side pushes of status information, then you should be looking at WebSockets or a pure Socket API of some kind, neither of which is provided by Express, but both of which are available in Node (checkout the socket.io library and the net core library)