Node.js HTTP Server Routing - node.js

below node.js code is using express to route to different urls, how can I do the same with http instead of express?
var express = require('express');
var app = express();
app.use(express.static('public'));
app.get('/', function (req, res) {
res.send('Welcome Home');
});
app.get('/tcs', function (req, res) {
res.send('HI RCSer');
});
// Handle 404 - Keep this as a last route
app.use(function(req, res, next) {
res.status(404);
res.send('404: File Not Found');
});
app.listen(8080, function () {
console.log('Example app listening on port 8080!');
});

Here's a quick example. Obviously, there are many ways of doing this, and this is probably not the most scalable and efficient way, but it will hopefully give you an idea.
const http = require('http');
const fs = require('fs');
const server = http.createServer((req, res) => {
req.on('error', err => {
console.error(err);
// Handle error...
res.statusCode = 400;
res.end('400: Bad Request');
return;
});
res.on('error', err => {
console.error(err);
// Handle error...
});
fs.readFile('./public' + req.url, (err, data) => {
if (err) {
if (req.url === '/' && req.method === 'GET') {
res.end('Welcome Home');
} else if (req.url === '/tcs' && req.method === 'GET') {
res.end('HI RCSer');
} else {
res.statusCode = 404;
res.end('404: File Not Found');
}
} else {
// NOTE: The file name could be parsed to determine the
// appropriate data type to return. This is just a quick
// example.
res.setHeader('Content-Type', 'application/octet-stream');
res.end(data);
}
});
});
server.listen(8080, () => {
console.log('Example app listening on port 8080!');
});

Try the code below . It is a pretty basic example
var http = require('http');
//create a server object:
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'}); // http header
var url = req.url;
if(url ==='/about'){
res.write('<h1>about us page<h1>'); //write a response
res.end(); //end the response
}else if(url ==='/contact'){
res.write('<h1>contact us page<h1>'); //write a response
res.end(); //end the response
}else{
res.write('<h1>Hello World!<h1>'); //write a response
res.end(); //end the response
}
}).listen(3000, function(){
console.log("server start at port 3000"); //the server object listens on port 3000
});

express can also be used by http directly.
From: https://expressjs.com/en/4x/api.html#app.listen
The app returned by express() is in fact a JavaScript Function, designed to be passed to Node’s HTTP servers as a callback to handle requests.
var http = require('http')
var express = require('express')
var app = express()
http.createServer(app).listen(80)
With this, you can still make use of express for routing, while keeping native http support.

Related

How serve client javascript modules in node.js

I'm new programmer to node.js. I trying to create vanilla server in node.js. In my client, I used ES6 modules. when I start my server and search for http://localhost:3000/ in my browser, HTML and CSS loaded but for javascript have this error:
I have four javascript modules for client side and in HTML I use this code for load javascript moduls:
<script type="module" src="js/controller.js" async></script>
My server code :
const http = require('http');
const fs = require('fs');
const path = require('path');
const PORT = 3000;
const server = http.createServer();
server.on('request', (req, res) => {
let routes = {
'GET': {
'/': indexHtml,
}
}
console.log(req.url)
let handler = routes[req.method][req.url];
handler = handler || readFile;
handler(req, res);
})
server.listen(PORT, () => {
console.log(`Listening on port ${PORT}...`)
});
function indexHtml(req, res) {
readFile({ url: '/index.html' }, res);
}
function readFile(req, res) {
var filePath = path.join(__dirname, '../client/', req.url);
// console.log(filePath)
fs.readFile(filePath, (error, data) => {
if (error) {
res.writeHead(404);
res.write('Not found error 404');
res.end()
} else {
res.writeHead(200);
res.write(data);
res.end();
}
})
}
How can I solve this error and serve javascript modules, Thanks a lot for your help.
With comment #derpirscher, I change my reader function with this code :
function readFile(req, res) {
var filePath = path.join(__dirname, '../client/', req.url);
fs.readFile(filePath, (error, data) => {
if (error) {
res.setHeader('Content-Type', 'text/html');
res.writeHead(404);
res.write('Not found error 404');
res.end()
} else {
const url = req.url === '/' ? '/index.html' : req.url;
if (req.url.includes('js')) res.setHeader('Content-Type', 'application/javascript');
if (req.url.includes('css')) res.setHeader('Content-Type', 'text/css');
if (req.url.includes('html')) res.setHeader('Content-Type', 'text/html');
res.writeHead(200);
res.write(data);
res.end();
}
})
}

ERR_HTTP_HEADERS_SENT node js socket connection

I am building an API that uses socket connection to interact with a server backend built in C#. This is what I have so far
const request = require('request');
const express = require('express');
const app = express();
var server = require('http').createServer(app);
var cors = require("cors");
app.use(cors());
const net = require('net');
const client = new net.Socket();
const stringToJson=require('./stringToJson')
const port = process.env.PORT;
const host = process.env.HOST;
client.keepAlive=true
client.on('close', function() {
console.log('Connection closed');
});
app.get('/getScores',function (req,res) {
let dataSend=''
client.on('data', function (data) {
console.log('Server Says : ' + data);
if(data!='ANALYSIS-ERROR'){
dataSend=stringToJson.stringToJson(data)
}
else{
dataSend=stringToJson.stringToJson('0:0.0:0.0:0.0:0:0:0.0:0.0:0.0:0.0:0.0:0:0.0:0.0:0.0:0.0:0.0:0:0.0:0.0:0.0:0.0:0.0:0:0.0:0.0:0.0:0.0:0.0')
}
client.destroy()
return res.send(dataSend)
});
client.connect(port, host, function () {
client.write(`GENERAL-ANALYSIS|${req.query.id}|${req.query.website}|`)
return
});
return
})
app.get('/getPlace',function (req,res) {
console.log(req.query)
request(
{ url: `https://maps.googleapis.com/maps/api/place/textsearch/json?query=${req.query.name}+in+${req.query.city}&key=${process.env.API_KEY}` },
(error, response, body) => {
if (error || response.statusCode !== 200) {
return res.status(500).json({ type: 'error', message: error.message });
}
return res.json(JSON.parse(body));
}
)
})
//TODO ADD 404 500 PAGES
app.use((req, res, next) => {
res.status(404).send("Sorry can't find that!");
});
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
server.listen(9000, () => {
console.log(`App running at http://localhost:9000`);
});
Basically it creates a connection with the server and listens for some data to be sent back. Then processes the string and sends it to the React frontend. The api calls are made by the frontend using axios
It works but if you refresh the page it throws this error Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
How do I fix this?
Try setting the headers as found in the documentation request.setHeader(name, value)
request.setHeader('Content-Type', 'application/json');

Node: Is it possible that http server on request return the content from a request module?

What I want to do is to make a request using the "request" module when server receives a request, and return the content of that "request" back to the client. Is it possible?
const http = require("http");
const request = require("request");
const URL = "???";
const server = http.createServer();
server.on('request', (req, res) => {
// called once for every HTTP request
out_res = res;
make_request((err, res, body) => {
out_res.writeHead(200, {res});
out_res.write(body);
out_res.end();
});
});
function make_request(callback) {
request(URL, (err, res, body) => {
callback(err, res, body);
});
}
module.exports = () => {
server.listen(8080);
console.log('server start');
};
I got an error: ERR_STREAM_WRITE_AFTER_END, I've been a long time without node.js, but my friend asked me about some code and I just rewrite as above.
Ofcourse you can do that
server.on('request', (req, res) => {
request({uri: URL}).pipe(res);
});
Just pipe the response of API call to your router response object.
Here is how I would advise you to write your server code
var server = http.createServer(function(req,res){
if(req.url === '/' || req.url === '/index'){
request({uri: URL}).pipe(res);
}
.... //other conditions
});
server.listen(3000,'127.0.0.1')
Moreover, you can/should consider using express, it's really cool and easy to use to define routes etc

Express: Can't set headers after they are sent

Following is my server file. I am making 2 calls, one post and one get. It works fine at times. But gives an error of : Can't set headers after they are sent. Does this have anything to do with my client side code?
server.js
var express = require('express')
var mongoose = require('mongoose')
var path = require('path')
var bodyParser = require("body-parser")
var cors = require("cors")
var app = express()
var port = process.env.PORT || 3000
var Url = require("./data/url-schema");
//Express request pipeline
app.use(express.static(path.join(__dirname,"../client")))
app.use(bodyParser.json())
app.use(cors());
/*
Your server must be ready to handle real URLs. When the app first loads at / it will probably work, but as the user navigates around and then hits refresh at /dashboard your web server will get a request to /dashboard. You will need it to handle that URL and include your JavaScript application in the response.
*/
app.get('*', function (request, response, next){
response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
next()
})
app.get('/:code', function(req, res) {
console.log("reg", req.params.code)
Url.findOne({code:req.params.code}, function(err, data){
console.log("data", data)
if(data)
res.redirect(302, data.longUrl)
else
res.end()
})
})
app.post('/addUrl', function (req, res, next) {
console.log("on create");
Url.findOne({longUrl:req.body.longUrl}, function(err, data) {
if (err)
res.send(err);
else if(data) {
console.log("already exists",data)
res.send("http://localhost:3000/"+data.code);
} else {
var url = new Url({
code : Utility.randomString(6,"abcdefghijklm"),
longUrl : req.body.longUrl
});
console.log("in last else data created",url)
url.save(function (err, data) {
console.log(data)
if (err)
res.send(err);
else
res.send("http://localhost:3000/"+data.code);
});
}
});
})
app.listen(port, function () {
console.log('Example app listening on port 3000!')
});
// Connect to our mongo database
mongoose.connect('mongodb://localhost/shortUrl');
I get the Following error
error
_http_outgoing.js:335
throw new Error('Can\'t set headers after they are sent.');
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)
at ServerResponse.header (/opt/lampp/htdocs/url-shortener/node_modules/express/lib/response.js:718:10)
at ServerResponse.location (/opt/lampp/htdocs/url-shortener/node_modules/express/lib/response.js:835:8)
at ServerResponse.redirect (/opt/lampp/htdocs/url-shortener/node_modules/express/lib/response.js:874:8)
at Query.<anonymous> (/opt/lampp/htdocs/url-shortener/server/server.js:30:8)
at /opt/lampp/htdocs/url-shortener/node_modules/mongoose/node_modules/kareem/index.js:177:19
at /opt/lampp/htdocs/url-shortener/node_modules/mongoose/node_modules/kareem/index.js:109:16
at process._tickCallback (node.js:355:11)
From the execution order, in * route handler, the body is being assigned to the response and then in /:code, the response code 302 is being added, where Location header is also added, hence the error. Any header must be added before the body to the response.
To solve this problem, simply change the order of the two GET statements.
Finally found the solution:
var express = require('express')
var mongoose = require('mongoose')
var path = require('path')
var bodyParser = require("body-parser")
var app = express()
var port = process.env.PORT || 3000
var Url = require("./data/url-schema")
var Utility = require("./utility")
//Express request pipeline
app.use(express.static(path.join(__dirname,"../client")))
app.use(bodyParser.json())
/*
Your server must be ready to handle real URLs. When the app first loads at / it will probably work, but as the user navigates around and then hits refresh at /dashboard your web server will get a request to /dashboard. You will need it to handle that URL and include your JavaScript application in the response.
*/
app.get('/dashboard', function (request, response, next){
response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
next()
})
app.get('/about', function (request, response, next){
response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
next()
})
app.get('/:code', function(req, res) {
Url.findOne({code:req.params.code}, function(err, data){
if(data){
res.redirect(302, data.longUrl)
}
})
})
app.post('/addUrl', function (req, res, next) {
Url.findOne({longUrl:req.body.longUrl}, function(err, data) {
if (err){
res.send(err)
}
else if(data) {
res.send("http://localhost:3000/"+data.code);
} else {
var newCode = getCode()
checkCode(newCode)
.then(function(data){
var url = new Url({
code : data,
longUrl : req.body.longUrl
});
url.save(function (err, data) {
if (err)
res.send(err);
else
res.send("http://localhost:3000/"+data.code);
});
})
}
});
})
app.listen(port, function () {
console.log('Example app listening on port 3000!')
});
// Connect to our mongo database
mongoose.connect('mongodb://localhost/shortUrl');
//Generate a random code
function getCode() {
return Utility.randomString(6,"abcdefghijklmnopqrstuvwxyz")
}
//Check if the code is unique
function checkCode(code) {
return new Promise(function (resolve, reject){
Url.findOne({code:code}, function(err, data) {
if(err === null){
resolve(code)
}else if(data){
saveUrlCode(getCode())
}
})
})
}
My earlier route which was :
app.get('*', function (request, response, next){
response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
next()
})
The get route was getting executed twice on account of the above call and the
app.get(":/code") call.
So I had to handle the routes properly which I have done by handling the dashboard and about routes separately instead of using the "*" route.

httpdispatcher returning no or blank response

I have the following simple code for a nodejs server....
var http = require('http');
var port = 1337;
var dispatcher = require('httpdispatcher');
dispatcher.setStaticDirname(__dirname);
dispatcher.setStatic('');
dispatcher.onGet("/page1", function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Page One');
});
var server = http.createServer().listen(port);
server.on('request', function (req, res) {
console.log('GOT');
dispatcher.dispatch(req, res);
});
console.log('Listening on port %s', port);
when I goto http://localhost:1337/index.html it is showing up correctly but when I do http://localhost:1337/page1 nothing happens...how can I get it to function properly...
You need to define your custom dispatcher events, in this case "/page1", before setting the static dispatcher. Otherwise static hogs every possible path remaining to check against the file system.
dispatcher.onGet("/page1", function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Page One');
});
dispatcher.setStaticDirname(__dirname);
dispatcher.setStatic('');
Your revised code will look like this:
var http = require('http');
var port = 1337;
var dispatcher = require('httpdispatcher');
dispatcher.onGet("/page1", function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Page One');
});
dispatcher.setStaticDirname(__dirname);
dispatcher.setStatic('');
var server = http.createServer().listen(port);
server.on('request', function (req, res) {
console.log('GOT');
dispatcher.dispatch(req, res);
});
console.log('Listening on port %s', port);
Tested and works

Resources