I'm completely new to server development and NodeJS, so my apologies if this question sounds stupid or if such a question already exists.
I was following a simple NodeJS tutorial and building a simple "Hello World" server. I noticed that http.createServer took only one function as its argument.
http.createServer(function(req,res) {
res.writeHead(200, {'Content-Type' : 'text/html'});
res.end("Hello World");
}.listen(8080);
I tried passing another function to it like the following:
var http = require('http');
http.createServer(function(req,res) {
res.writeHead(200, {'Content-Type':'text/html'});
res.end("Hello World");
},
function (req, res) {
res.write("Blahblah");
res.end();
}
).listen(8080);
But hitting localhost:8080 returned only Hello World.
So I was wondering if I could pass multiple functions to it and if not, then why.
Thank you for your time
You cannot pass multiple functions. If you want multiple listeners for incoming requests, you can just register another listener for incoming requests:
const server = http.createServer(function(req,res) {
res.writeHead(200, {'Content-Type' : 'text/html'});
res.end("Hello World");
}.listen(8080);
// add additional listener
server.on('request', function(req, res) {
if (req.url === "/goodbye") {
res.writeHead(200, {'Content-Type' : 'text/plain'});
res.end("goodbye");
}
});
Note: right from the doc for http.createServer(), it says this about the function parameter passed to http.createServer():
http.createServer([options][, requestListener])
The requestListener is a function which is automatically added to the 'request' event.
Doc for the request event is here.
As others have said, it is pretty rare to use a plain http server like this because some simple routing is nearly always helpful and a lightweight framework like Express offers very useful features without really getting in the way of anything you might want to do. In the case of Express, you'd use code like this:
const express = require('express');
const app = express();
// define handler for /goodbye URL
app.get('/goodbye', function(req, res) {
res.send("goodbye");
});
// define handler for /hello URL
app.get("/hello", function(req, res) {
res.send("hello");
});
const server = app.listen(8080);
Here express, keeps a list of the URLs that you wish to handle and then listens for each incoming request, compares it against the URLs you wanted to handle and calls the appropriate route handler. It has lots of other features for routing too such as middleware, wildcards, parameterized URLs, etc...
I'd recommend you use something like express if you want multiple routes:
const express = require('express');
const app = express();
app.get('/hello', (req, res) => res.send('Hello World!'));
app.get('/world', (req, res) => res.send('Hello World!'));
app.listen(3000, () => console.log('Example app listening on port 3000!'));
Node.js provides you with the features to create your own webserver from scratch, unless you want to create a whole new framework i would recommend using something like expressjs.
Have a look at this following tutorial if you're a newbie and want to create restful services.
Build a RESTful API Using Node and Express 4 | Scotch.io
Its a fairly simple and straightforward tutorial
Related
I have an example
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('hello world');
});
In the runtime (for example in 10 sec), I want to stop handling my / endpoint, so when I will make a request, the response would be like Cannot GET /
How can I achieve this behaviour?
You need to create a flag that can be set based on when you want to keep preventing the route from providing the data. Instead of showing Cannot GET /, you should send the status code 503 status code i.e service unavailable.
var express = require('express');
var app = express();
app.get('/', function (req, res) {
if (flag) {
res.status(503).send('Service Unavailable');
} else {
res.send('hello world');
}
});
This could be great if you want to make it for a single route. When you want to control many routes, you can create middleware and use flag similar to the above one.
I'm running a NodeJS application and am visiting it at localhost/?product=test. I want to retreive 'test' (or any URL-related information for that matter).
Google shows me 2 options, but I can't get either to work:
Use HttpRequest
const http = require('http');
const url = require('url');
http.createServer(function (req, res) {
const queryObject = url.parse(req.url,true).query;
console.log(queryObject);
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('Feel free to add query parameters to the end of the url');
}).listen(3000);
I'm trying to use this code, or variations on it, but the issue is that I cannot create a server to listen to because the address is already in use. I'm not too familiar with NodeJS, but what I don't understand is how to use a HttpRequest properly to listen to the running application and get its URL.
Use Express
Using express doesn't give an error, but all code snippets that -should- work return undefined for me when retrieving the URL.
What is a simple way to retrieve the URL the user used to visit my NodeJS app, so I can retrieve the parameters?
If you want to access localhost without filling in a port like here localhost/?product=test then you should listen to port 80 and not 3000. Otherwise your request should look like this: localhost:3000/?product=test
You should also create a route method for products. In express it will look like this:
const express = require('express')
const app = express()
const port = 80
app.get('/', (req, res) => res.send('home'))
app.get('/product/:productId', function (req, res) {
res.send(req.params)
})
app.listen(port, () => console.log(`Listening on port ${port}!`))
If you run this example your request url should be http://localhost/product/test and response will look like
{
"productId": "test"
}
All:
I am pretty new to socket.io, when I go thru its Docs( the Express 3/4 part especially ), there is an example:
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(80);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
What I am trying to understand is this line:
var server = require('http').Server(app);
The Doc here: https://nodejs.org/api/http.html#http_class_http_server
makes me even more confused, I wonder could anyone give a little detail how to read those docs(both Node.js and Express.js APIs) and How to find out what that "app" should looks like so that it can be passed into require('http').Server ?
Thanks
It's all a bit confusing but the basic contract of http.Server is it expects a request handler function that accepts 2 arguments: req, res. The app object express creates for you is actually a function and actually designed to be used as an http request handler, so it all works together, but it can be quite confusing because in addition to being a function, of course app instance is a complex object representing an entire express application so it has lots of other properties. But something as simple as function (req, res) { console.log('Request received')} would work just fine as an argument to http.Server.
Another way to connect the dots would be to do this and confirm that things actually still work fine:
var server = require('http').Server(function (req, res) {
app(req, res)
});
Then you realize that your function is just passing arguments through to app unmodified and is thus unnecessary.
I am trying to create a basic web server with express for node.js. I know that the http module has a .on('connection',function(client){}) method that is called whenever a client connects. Is there a similar method for express?
I know this question is quite old, but I had the same one and was able to figure out the answer, so I thought I would post it here for anyone else who may be looking.
According to the Express docs with Express 4.x, the listen method returns an http.Server object, so all methods that can be used on http.Server.listen are also available on the Express listen method.
With this in mind, the answer to your question is yes, and below is an example of how you can achieve it in Express 4.x.
const app = express();
app.use('/', function (req, res, next) {
// Add your code for this route here
});
const server = app.listen(3000, function () {
console.log('Server listening on port 3000');
});
server.on('connection', function (client) {
// Do your thang here
});
You can easily add a route that will be matched against "everything", that is:
app.use('/', function (req, res, next) {
console.log("received request: " + req.originalUrl);
next();
});
This is simply a middleware that, once a client executes any rest api to your server, will log the url and call next() to continue to the next matching route
In my scenario I need forward get request to another end point. In my machine there are two servers php and node.js server. Node.js is like a "man in the middle", PHP server must work in the same way.
Node.js server code
var express = require('express');
var fs = require('fs');
var path = require('path');
var http = require('http');
var https = require('https');
var app = express();
var HTTP_PORT = 3000;
// Create an HTTP service
http.createServer(app).listen(HTTP_PORT,function() {
console.log('Listening HTTP on port ' + HTTP_PORT);
});
//endpoint for tracking
app.get('/track', function(req, res) {
sendRequestToOtherEndPoint(req);
processRequest(req);
res.setHeader('Content-Type', 'application/json');
res.send('Req OK');
});
function processRequest(req){
console.log("request processed");
}
function sendRequestToOtherEndPoint(req){
//magic here :)
}
When this server receive a get request in port 3000, it process request information and it must forward the same requesto to another end point.
For example:
Get localhost:3000/track?param1=1¶m2=2
Server process get request
Server forward get request to localhost/final-endpoint?param1=1¶m2=2
Depending on what you're trying to do, you can create a new request to the end-point:
//endpoint for tracking
app.get('/track', function(req, res) {
req.get({url: 'http://end-point', headers: req.headers});
processRequest(req);
res.setHeader('Content-Type', 'application/json');
res.send('Req OK');
});
More info: https://github.com/request/request
There are a couple of useful libraries that one could use:
http-proxy-middleware:
const proxy = require('http-proxy-middleware')
var apiProxy = proxy('/track', {target: 'http://end-point'});
app.use(apiProxy)
axios-express-proxy
import express from 'express';
import { Proxy } from 'axios-express-proxy';
const app = express();
const port = 3000;
app.get('/track', (req, res) => Proxy('http://end-point', req, res));
In you case res.redirect might help.
app.get('/track', function(req, res) {
// process the request
// then redirect
res.redirect('/final-endpoint');
});
Then catch the redirected request in final endpont.
app.get('/final-endpoint', function(req, res) {
// proceess redirected request here.
});
See the Express docs
If your second endpoint is on a different server, (e.g. PHP) then you're going to need to either redirect the client (as in sohel's answer), or spoof a request from Node to the PHP server and then send the response back to the client. This latter option is definitely non-trivial so I would question whether it's crucial not to use a client redirect.
If you're talking about two express endpoints, then I think the simplest answer might be not to actually forward at all, but just use the endpoint callback directly instead:
app.get('/track', trackCallback);
app.get('/otherendpoint', otherendpointCallback);
function otherendpointCallback(req, res) {
// do your thing
}
function trackCallback(req, res) {
otherendpointCallback(req, res);
processRequest(req);
res.setHeader('Content-Type', 'application/json');
res.send('Req OK');
};
Depending on exactly what you want to do at the other end point, you might need to spoof some of req's fields (e.g. req.url)