node.js what is causing error 400 bad request - node.js

I was adding some code to my node.js web app. I added this one feature, and then it threw an error 400. I removed it by hitting Ctrl-Z, but it still threw error 400. Then, I made a test.js that was the simplest implementation of express, and it is still getting error 400. Here is my code for test.js:
const app = require("express")();
const http = require("http").createServer(app);
const url = require('url');
app.get("/", function(req, res)
{
res.sendFile(__dirname + "/test.html");
});
http.listen(3001, function()
{
console.log("--listening on port 3001");
});
I have checked to make sure I am typing in the correct url, with the correct port. I think something got cached and is screwing it up, since it works if I clear my cache or use curl. Any ideas?

Use process.cwd() instead of __dirname which is causing error and generating 404.
process.cwd() will return the directory where node is intialized. It returns absolute path where you started the node.js process.
const app = require("express")();
const http = require("http").createServer(app);
const url = require('url');
const path = require('path');
app.get("/", function(req, res)
{
// res.sendFile(__dirname + "/test.html");
res.sendFile(process.cwd() + "/test.html");
});
http.listen(3001, function()
{
console.log("--listening on port 3001");
});
or You can also resolve the path of __dirname
const app = require("express")();
const http = require("http").createServer(app);
const url = require('url');
const path = require('path');
app.get("/", function(req, res)
{
__dirname=path.resolve();
res.sendFile(__dirname + "/test.html");
});
http.listen(3001, function()
{
console.log("--listening on port 3001");
});

After some more research (and thanks to comments), I finally found the problem!
I was storing too much stuff in cookies, and it exceeded the maximum amount of 4KB.

Related

Express enable client side caching

I am trying to cache a file client side with NodeJs and Express.
Here an example of what I am trying to do :
const path = require('path');
const express = require('express')
const app = express()
app.get('/', (req:any, res:any)=> res.send('Hello World!') );
app.get('/file', (req:any, res:any)=> {
console.log('Request URL:', req.originalUrl);
res.set('Cache-Control', 'public, max-age=60');
res.sendFile(path.resolve(__dirname+'/../file.pdf'));
});
app.listen(3000, ()=>console.log('Example app listening on port 3000!') );
Then I browse the file twice and I expect to have only one log Request URL: /file. But with this code I got two. It seems that either my Cache-Control headers is ignored by the browser or it get mixed up with default Express behavior like ETag..
Any Idea ?
I'm not sure but first thing that I thought about was the file size.
Maybe it is too big?
what-is-chrome-default-cache-size-limit

NodeJS, Express. Cannot upload static content

I've tried to write node server which would run React app created by create-react-app. Actually, something strange happens and I don't have any clue what I'm doing wrong (run app as node server/index.js):
export default (app, dirname) => {
app.use(favicon(path.join(dirname, '..','build', 'favicon.ico')));
app.use(express.static(path.join(dirname, '..','build')));
// initialize routers
bootRotes(app);
if (process.env.NODE_ENV === AVAILABLE_ENVIROMENTS.DEVELOPMENT) {
expressBootDev(app, dirname);
} else {
app.get('/*', (req, res) => {
res.sendFile(path.join(dirname, '..', 'build', 'index.html'));
});
}
}
build folder contains build react app which created the following command npm run build
Strange things are happening when after uploading index page it tries to upload static content. For example http://localhost:5000/static/js/2.30e86b6e.chunk.js. Browser just adds / after each static content url and it turns to http://localhost:5000/static/js/2.30e86b6e.chunk.js/ and of course this url doesn't match to express.static middleware.
Moreover, I've checked via Postman, that url GET http://localhost:5000/static/js/2.30e86b6e.chunk.js withot / at the end provides content which is expected.
I work with PRODUCTION env, it means that expressBootDev doesn't have any impacts.
Has anybody has the same issue? I've spent whole day and don't know hopw to fix it.
When I'm creating a simple code in a root app folder with almost the same logic and run as node server.js and it works as expected:
//server.js
const express = require('express');
const favicon = require('express-favicon');
const path = require('path');
const port = process.env.PORT || 8080;
const app = express();
app.use(favicon(__dirname + '/build/favicon.ico'));
app.use(express.static(__dirname));
app.use(express.static(path.join(__dirname, 'build')));
app.get('/ping', function (req, res) {
return res.send('pong');
});
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(port);
And I don't see any principal difference
var fs = require('fs');
var express = require('express');
var router = express.Router();
// GET: Sent some basic info for usage
router.get('/', (req, res, next) => {
var fname = __dirname + '/../public/index.html';
var val = fs.readFile( fname, 'utf8', ( err, data) => {
//send can only be called once, write can be called many times,
// in short res.send(msg) == res.write(msg);res.end();
res.writeHeader(200, {"Content-Type": "text/html"});
res.write(data);
res.end();
});
});
module.exports = router;
Here is the example how you can do a static file serving with node.
https://github.com/msatyan/ApiServe1/blob/master/routes/index.js
The full project is
https://github.com/msatyan/ApiServe1
FYI: Node.js with HTTP1 is not an efficient for static file serving by design, I believe HTTP2 support in node has addressed this problem. The reason for inefficiency with HTTP1 is that it has to take the file content read at native layer to JavaScript layer and then send it through HTTP server.

Express req.query always empty

I was using express route like this and I want my urls to contain query strings initially.
app.get('/', function(req, res){
res.render('index', {});
});
app.get('/us01', function(req, res){
console.log('query: '+JSON.stringify(req.query));
res.render('templates/us01', {});
});
app.get('/benchmark', function(req, res){
res.render('templates/benchmark', {});
});
However, I never get my query strings printed no matter what query strings I append after /us01. For example, "localhost:9200/us01?a=1" req.query should get me {a:1}, correct? Is this a common thing? What am I missing here?
My app.js
"use strict";
var express = require('express');
var expApp = express();
var http = require('http').Server(expApp);
var path = require('path');
var bodyParser = require('body-parser');
// all environments
expApp.set('port', process.env.PORT || 5555);
expApp.set('views', __dirname + '/views');
expApp.set('view engine', 'ejs');
expApp.use(bodyParser.urlencoded({ extended: true }));
expApp.use(bodyParser.json());
expApp.use(express.static(path.join(__dirname, 'public')));
//----------------ROUTES--------------------------//
require("./routes/route.js")(expApp);
http.listen(expApp.get('port'), function(){
console.log('Node-Server listening on port ' + expApp.get('port'));
});
My indexController.js has :
$stateProvider
.state('us01', {
url: '/us01',
templateUrl: '/us01'
}).state('benchmark', {
url: '/benchmark',
templateUrl: '/benchmark'
})....
This simple code:
const express = require('express');
const app = express();
app.get('/us01', function(req, res) {
console.log(req.query);
res.send("ok");
});
app.listen(80);
Then, accessed by http://localhost/us01?a=1 produces this output in the console:
{ a: '1' }
Or, if I use:
console.log('query: ' + JSON.stringify(req.query));
Then, I see this in the console:
query: {"a":"1"}
So, clearly something else is wrong in your code.
"localhost:9200/us01?a=1" req.query should get me {a:1}, correct?
It should get you query: {"a":"1"} if the code you show is running on port 9200 on localhost.
Is this a common thing?
No. Something other than the code you show is busted because there's nothing wrong with just that bit of code.
What am I missing here?
Things to examine:
Are you getting any output in the console when you hit any of your expected routes?
Can you prove that your server is running and your browser is hitting your route handlers?
If you just do console.log(req.query), what output do you get?
Are you absolutely sure that you've killed any prior servers and started the server that corresponds to the code you show. People sometimes get fooled by a prior version of the server that is still running and doesn't actually contain the code they think they are running.
Are you 100% sure you are running your server on the desired port that matches the port in the URL you are using.
When all else fails, sometimes a computer reboot will make sure no prior versions of anything are still running.

How to forward a request to other endpoint in node.js

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&param2=2
Server process get request
Server forward get request to localhost/final-endpoint?param1=1&param2=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)

Run NodeJS app on nodejitsu, all i get is "cannot get /"

as part of my learning i wanted to deploy my app to nodejitsu. Its running fine on my local server, but on nodejitsu all i get is
Cannot GET /
I thought it may have something to do with the NODE_ENV set to production on the server, but i never touched this on my local server. I changed it on nodejitsu to development but still i cant get it to work.
After commenting all the code i think the problem is in my index.js which i show below:
var express = require('express');//the framework
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
//var session = require('express-session');
var methodOverride = require('method-override');
var passport = require("passport");//for authentication
var LocalStrategy = require('passport-local').Strategy;//local users for passport
var http = require('http');
var path = require('path');
var db = require('./dataBase');//to connect to the db
var userRoles = require('./routingConfig').userRoles;
var accessLevels = require('./routingConfig').accessLevels;
var debug = false;
var db = new db('inmobiliaria', 'localhost', 3306, debug);
require('./passport')(passport, db, debug)
var app = express();
app.set('port', 1337);
app.use(methodOverride());
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: false }))
//app.use(session({ secret: 'SECRET' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(function (req, res, next) {
var role = userRoles.public;//default role
var username = '';
if (req.user) {
role = req.user.role;
username = req.user.username;
}
res.cookie('user', JSON.stringify({
'username': username,
'role': role
}));
next();
});
app.use('/', express.static(path.join(__dirname + '/../Client/')));
app.use("/lib", express.static(path.join(__dirname + '/../Client/lib/')));
app.use("/ctr", express.static(path.join(__dirname + '/../Client/Controllers/')));
app.use("/media", express.static(path.join(__dirname + '/../Client/media/')));
app.use("/views", express.static(path.join(__dirname + '/../Client/Views/')));
app.use("/srv", express.static(path.join(__dirname + '/../Client/Services/')));
app.use("/dct", express.static(path.join(__dirname + '/../Client/Directives/')));
require('./routes')(app, passport, db);
//require('./emailConfiguration');
http.createServer(app).listen(process.env.PORT || app.get('port'), function (err) {
console.log("Express server listening on port " + app.get('port'));
if (err) {
throw err; // For completeness's sake.
}
});
I investigated about this variable, but im not sure it has something to do with it. This is the url http://horaciotest.jit.su/, in case you want to see it.
Is this configuration? Am i doing something that should not be done?
Thanks for taking your time.
EDIT:
i managed to reduce the error case to a few lines i think. As the guys at nodejitsu suggested, im now trying to use the module node-static to serve static files, but i cant get it to work along express:
this code works on nodejitsu and my local server (or at least doesnt show any errors)
var statik = require('node-static');
var http = require('http');
var path = require('path');
var file = new (statik.Server)(path.join(__dirname + '/../Client/'));//index.html here
http.createServer(function (req, res) {
console.log(path.join(__dirname + '/../Client/'));
file.serve(req, res);
}).listen(8080);
but as soon as i add express, i get the error i mentioned above:
var express = require('express');
var statik = require('node-static');
var http = require('http');
var path = require('path');
var app = express();
var file = new (statik.Server)(path.join(__dirname + '/../Client/'));//index.html here
http.createServer(app, function (req, res) {
console.log(path.join(__dirname + '/../Client/'));
file.serve(req, res);
}).listen(8080);
Can someone tell me why when i add the express app i get the error? it may be what i need to get this to work on nodejitsu, thanks!
I found out what the problem was, hope it helps someone:
My project structure had two folders: one was named Client, where all my html and .js from angular where.
The other folder was WebServer, where i had all my nodejs files.
In order to deploy to nodejitsu, you run a command which is jitsu deploy, this in turn runs another command: npm pack. This command creates a .tgz file with all the data in you nodejs directory excluding the node_modules file and any file that starts with .. Problem is, if you like me have files outside that folder, they wont be included.
The solutions is to move your client folder inside the nodejs one. Everything you need to sent to the server should be in side this folder.

Resources