I am using express web framework and trying to make an $http request from angularjs. I am passing data to request from client but server is not receiving request for some unknown reasons. Please help.
server.js
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io')(server);
var path = require('path');
var fs = require('fs');
app.use(express.static(path.join(__dirname, 'public')));
app.post('/readTfile',function (req,res) {
console.log('i received a request');
console.log(req.body);
});
server.listen(3000);
And angular html
<html>
<head>
<title>File tream 2</title>
<script type="text/javascript" src="javascripts/angular.js"></script>
</head>
<body>
<h2>File tream 2 AngularJS</h2>
<div ng-app = "mainApp">
<div id="readfile" ng-controller = "Ctrl1">
<div>{{myfiledata}}</div> </br></br>
</div>
</div>
</body>
<script>
var mainApp = angular.module("mainApp",[])
mainApp.controller('Ctrl1', function ($scope, $http) {
var filename = 'D:\\myapp\\public\\test.txt';
var obj = {"filename" : filename};
$scope.myfiledata = 'result';
$http({
url: '/readTfile',
method: "POST",
data: JSON.stringify(obj),
//timeout: canceller.promise,
headers: {'Content-Type': 'application/json','charset' : 'utf-8'}
}).success(function(result) {
console.log(result);
$scope.myfiledata = 'result';
}).error(function(data, status) {
console.log(data);
});
});
</script>
</html>
On console i am getting undefined for req.body
i received a request
undefined
Please help to solve me this problem.
You will need middleware to read the body of the POST request from the incoming stream and to parse it from JSON to a Javascript object and put that into req.body. It does not just end up in req.body automatically. The usual middleware for a simple JSON body would be to use the body-parser middleware that is built into Express.
// other stuff here
// read and parse application/json
app.use(express.json());
app.post('/readTfile',function (req,res) {
console.log('i received a request');
console.log(req.body);
res.send("something");
});
And, for this middleware to work and automatically recognize that you sent JSON, you will have to make sure the post has set the right content type.
Note, there is different middleware for different content types. The code above is for application/json. If you are doing a vanilla form post, that would typically have a content-type of application/x-www-form-urlencoded and you would use:
app.use(express.urlencoded());
The middleware shown here will automatically detect which content-type is available only operate on a content-type that matches their functionality so you can even have both of these middleware present.
Related
I know the basics of coding but I'm trying to understand API's, at the moment I'm trying to make an API that authorizes a user so I can see their information in a game.
Essentially I need to send data to my client from my server which is running Node.js and Express. I have managed to get the user authenticated but I then need to save that information as a cookie for later use.
The webapp starts on index.html and the API redirects the user back to auth.html.
Server Side Code
require('dotenv').config();
const express = require('express');
const {
addAsync
} = require('#awaitjs/express');
const app = addAsync(express());
const path = require('path');
const url = require('url');
const fetch = require("node-fetch");
const base64 = require('base-64');
const http = require('http');
// config libraries
const client_secret = process.env.CLIENT_SECRET;
// get env variables
function getCode(req) {
var ru = url.format({
protocol: req.protocol,
host: req.get('host'),
pathname: req.originalUrl
});
return ru.split("code=")[1];
}; // parse url to get auth code
const port = process.env.PORT || 4645;
app.listen(port, () => {
console.log(`listening on port ${port}`);
}); // set http server
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'index.html'));
}); // set '/' as index.html
app.getAsync('/auth', async (req, res) => {
res.sendFile(path.join(__dirname, 'auth.html'));
const code = getCode(req);
const options = {
method: 'POST',
headers: {
'Authorization': `Basic ${base64.encode(`35544:${client_secret}`)}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `grant_type=authorization_code&code=${code}`
}
const obj = await fetch('https://www.bungie.net/platform/app/oauth/token/', options); // response
const data = await obj.json(); // json response = data
console.log(data);
// send json to client
res.json(data);
res.end();
});
app.get('/logout', async (req, res) => {
res.redirect('/');
});
Client Side Code (index.html)
<head>
<script>
// code
</script>
</head>
<body>
index.html <br>
<a href='https://www.bungie.net/en/OAuth/Authorize?client_id=35544&response_type=code'>log in</a> <br>
</body>
Client Side Code (auth.html)
<head>
<script>
// catch json from server
const options = {
url: '/auth',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
fetch(options).then(response => {
console.log(response);
})
</script>
</head>
<body>
auth.html <br>
<a href='/logout'>log out</a>
</body>
I know it's a lot but I hope someone can help me on this...
Thanks.
Edit:
I forgot to say that currently the client does not recieve the information at any point, and if it did i am unsure how to catch the response at the right time...
Thanks to everyone who already responded.
Without bothering to puzzle-out your code ... "never trust the client."
Never try to send the client any meaningful data as the content of a cookie. The cookie's value should always be a perfectly-meaningless value – a "nonce" – which you can then refer to in order to look up anything you need to know from your server-side database. "You can never trust the client-side."
I know there are a lot of questions like this, but none I've seen have fixed my issue. I've used at least 3 microframeworks already. All of them fail at doing a simple POST, which should return the data back:
The angularJS client:
var app = angular.module('client', []);
app.config(function ($httpProvider) {
//uncommenting the following line makes GET requests fail as well
//$httpProvider.defaults.headers.common['Access-Control-Allow-Headers'] = '*';
delete $httpProvider.defaults.headers.common['X-Requested-With'];
});
app.controller('MainCtrl', function($scope, $http) {
var baseUrl = 'http://localhost:8080/server.php'
$scope.response = 'Response goes here';
$scope.sendRequest = function() {
$http({
method: 'GET',
url: baseUrl + '/get'
}).then(function successCallback(response) {
$scope.response = response.data.response;
}, function errorCallback(response) { });
};
$scope.sendPost = function() {
$http.post(baseUrl + '/post', {post: 'data from client', withCredentials: true })
.success(function(data, status, headers, config) {
console.log(status);
})
.error(function(data, status, headers, config) {
console.log('FAILED');
});
}
});
The SlimPHP server:
<?php
require 'vendor/autoload.php';
$app = new \Slim\Slim();
$app->response()->headers->set('Access-Control-Allow-Headers', 'Content-Type');
$app->response()->headers->set('Content-Type', 'application/json');
$app->response()->headers->set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
$app->response()->headers->set('Access-Control-Allow-Origin', '*');
$array = ["response" => "Hello World!"];
$app->get('/get', function() use($array) {
$app = \Slim\Slim::getInstance();
$app->response->setStatus(200);
echo json_encode($array);
});
$app->post('/post', function() {
$app = \Slim\Slim::getInstance();
$allPostVars = $app->request->post();
$dataFromClient = $allPostVars['post'];
$app->response->setStatus(200);
echo json_encode($dataFromClient);
});
$app->run();
I have enabled CORS, and GET requests work. The html updates with the JSON content sent by the server. However I get a
XMLHttpRequest cannot load http://localhost:8080/server.php/post. Response for preflight has invalid HTTP status code 404
Everytime I try to use POST. Why?
EDIT: The req/res as requested by Pointy
EDIT:
It's been years, but I feel obliged to comment on this further. Now I actually am a developer. Requests to your back-end are usually authenticated with a token which your frameworks will pick up and handle; and this is what was missing. I'm actually not sure how this solution worked at all.
ORIGINAL:
Ok so here's how I figured this out.
It all has to do with CORS policy. Before the POST request, Chrome was doing a preflight OPTIONS request, which should be handled and acknowledged by the server prior to the actual request. Now this is really not what I wanted for such a simple server. Hence, resetting the headers client side prevents the preflight:
app.config(function ($httpProvider) {
$httpProvider.defaults.headers.common = {};
$httpProvider.defaults.headers.post = {};
$httpProvider.defaults.headers.put = {};
$httpProvider.defaults.headers.patch = {};
});
The browser will now send a POST directly. Hope this helps a lot of folks out there... My real problem was not understanding CORS enough.
Link to a great explanation: http://www.html5rocks.com/en/tutorials/cors/
Kudos to this answer for showing me the way.
You have enabled CORS and enabled Access-Control-Allow-Origin : * in the server.If still you get GET method working and POST method is not working then it might be because of the problem of Content-Type and data problem.
First AngularJS transmits data using Content-Type: application/json which is not serialized natively by some of the web servers (notably PHP). For them we have to transmit the data as Content-Type: x-www-form-urlencoded
Example :-
$scope.formLoginPost = function () {
$http({
url: url,
method: "POST",
data: $.param({ 'username': $scope.username, 'Password': $scope.Password }),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(function (response) {
// success
console.log('success');
console.log("then : " + JSON.stringify(response));
}, function (response) { // optional
// failed
console.log('failed');
console.log(JSON.stringify(response));
});
};
Note : I am using $.params to serialize the data to use Content-Type: x-www-form-urlencoded. Alternatively you can use the following javascript function
function params(obj){
var str = "";
for (var key in obj) {
if (str != "") {
str += "&";
}
str += key + "=" + encodeURIComponent(obj[key]);
}
return str;
}
and use params({ 'username': $scope.username, 'Password': $scope.Password }) to serialize it as the Content-Type: x-www-form-urlencoded requests only gets the POST data in username=john&Password=12345 form.
For a Node.js app, in the server.js file before registering all of my own routes, I put the code below. It sets the headers for all responses. It also ends the response gracefully if it is a pre-flight "OPTIONS" call and immediately sends the pre-flight response back to the client without "nexting" (is that a word?) down through the actual business logic routes. Here is my server.js file. Relevant sections highlighted for Stackoverflow use.
// server.js
// ==================
// BASE SETUP
// import the packages we need
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var morgan = require('morgan');
var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
// ====================================================
// configure app to use bodyParser()
// this will let us get the data from a POST
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// Logger
app.use(morgan('dev'));
// -------------------------------------------------------------
// STACKOVERFLOW -- PAY ATTENTION TO THIS NEXT SECTION !!!!!
// -------------------------------------------------------------
//Set CORS header and intercept "OPTIONS" preflight call from AngularJS
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
if (req.method === "OPTIONS")
res.send(200);
else
next();
}
// -------------------------------------------------------------
// STACKOVERFLOW -- END OF THIS SECTION, ONE MORE SECTION BELOW
// -------------------------------------------------------------
// =================================================
// ROUTES FOR OUR API
var route1 = require("./routes/route1");
var route2 = require("./routes/route2");
var error404 = require("./routes/error404");
// ======================================================
// REGISTER OUR ROUTES with app
// -------------------------------------------------------------
// STACKOVERFLOW -- PAY ATTENTION TO THIS NEXT SECTION !!!!!
// -------------------------------------------------------------
app.use(allowCrossDomain);
// -------------------------------------------------------------
// STACKOVERFLOW -- OK THAT IS THE LAST THING.
// -------------------------------------------------------------
app.use("/api/v1/route1/", route1);
app.use("/api/v1/route2/", route2);
app.use('/', error404);
// =================
// START THE SERVER
var port = process.env.PORT || 8080; // set our port
app.listen(port);
console.log('API Active on port ' + port);
I made a web-app using AngularJs where user can upload .txt files to a server using ng-file-upload.
Now I wanted a simple Node.js server to test the upload part and watch how progress bars and error messages in the page behave, but having a very poor knowledge about how Node.js and the entire backend thing work, I tried to use the Node.js server provided by ng-file-upload's very wiki.
I tried to make some changes that brought me to this app.js file:
var http = require('http')
, util = require('util')
, multiparty = require('multiparty')
, PORT = process.env.PORT || 27372
var server = http.createServer(function(req, res) {
if (req.url === '/') {
res.writeHead(200, {'content-type': 'text/html'});
res.end(
'<form action="/upload" enctype="multipart/form-data" method="post">'+
'<input type="text" name="title"><br>'+
'<input type="file" name="upload" multiple="multiple"><br>'+
'<input type="submit" value="Upload">'+
'</form>'
);
} else if (req.url === '/upload') {
var form = new multiparty.Form();
form.parse(req, function(err, fields, files) {
if (err) {
res.writeHead(400, {'content-type': 'text/plain'});
res.end("invalid request: " + err.message);
return;
}
res.writeHead(200, {'content-type': 'text/plain'});
res.write('received fields:\n\n '+util.inspect(fields));
res.write('\n\n');
res.end('received files:\n\n '+util.inspect(files));
});
} else {
res.writeHead(404, {'content-type': 'text/plain'});
res.end('404');
}
});
server.listen(PORT, function() {
console.info('listening on http://127.0.0.1:'+PORT+'/');
});
and the UserController.js is simple as this
UserController = function() {};
UserController.prototype.uploadFile = function(req, res) {
// We are able to access req.files.file thanks to
// the multiparty middleware
var file = req.files.file;
console.log(file.name);
console.log(file.type);
}
module.exports = new UserController();
Inside a directive's controller in my AngularJs app I use the ng-file-upload upload service in this way
var upload = Upload.upload({
url: 'http://127.0.0.1:27372/upload',
method: 'POST',
fields: newFields,
file: newFile
}).progress(function (evt) {
$scope.progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
}).success(function (data, status, headers, config) {
console.log("OK");
}).error(function(data, status, headers, config) {
console.log("KO");
});
Finally, I start the server like so:
node app.js
and all looks fine:
listening on http://127.0.0.1:27372
With all that being said, when I launch the AngularJs web-app and try to upload a file I get the following error
OPTIONS http://127.0.0.1:27372/upload 400 (Bad Request) angular.js:10514
XMLHttpRequest cannot load http://127.0.0.1:27372/upload. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. The response had HTTP status code 400. (index):1
After some googling I found many gists used to allow CORS requests like this one, but my Node.js knowledge is so poor I don't even know where I should place those lines of code.
Furthermore, I tried to get a console.log(err) within the app.js form.parse part itself and got this printed on the terminal:
DEBUG SERVER: err =
{ [Error: missing content-type header] status: 415, statusCode: 415 }
What am I missing and what can I do to get this simple Node.js server
working?
EDIT 29/07/2015
I chosed to follow the first option suggested by #Can Guney Aksakalli, because it's the only one I can do, but even if now the code looks like this:
var server = http.createServer(function(req, res) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
if (req.url === '/') {
res.writeHead(200, {'Content-type': 'text/html'});
// and the code stays the same
This solution it's not working; I keep getting the same error message in both the Chrome console and the terminal from which I called node app.js, as I wrote in the last part of my initial question.
You are serving html files on http://localhost:9000 and NodeJS application on http://localhost:27372; therefore you have CORS issue. (This issue is not related to angularjs though). You have to either enable CORS for NodeJS or serve your all application in the same domain.
Possible solutions:
1- Enabling CORS in NodeJS server
You can enable CORS in your server side by specifying allowed origins in response header. These lines would enable requests to your application from all domains. (add this to beginning of the function definition.)
var server = http.createServer(function(req, res) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
// the rest of the method ...
}
Enabling CORS for all domain is not always a good decision, please also check this.
2- Serving your html files from NodeJS application
Here with following additions you would serve your html files from NodeJS server. (You don't need to use the other server anymore.)
var serveStatic = require('serve-static');
var finalhandler = require('finalhandler');
//...
var serve = serveStatic('./path/to/your/static/folder');
var server = http.createServer(function(req, res) {
//...
var done = finalhandler(req, res);
serve(req, res, done);
});
I would also recommend you to use ExpressJS for richer server capabilities instead of vanilla node.js http server.
3- Providing a proxy connection from your html files server to nodejs app
I don't know what you are using as a server for static html files but it is possible to have a proxy between your static server to NodeJS application server.
EDIT 1
Here is a basic implementation for option 2- Serving your html files from NodeJS application.
In this example I used ExpressJS. Client side static files are served in public folder, for post request to /api/upload url would upload the file. Here is the server code app.js:
var express = require('express'),
path = require('path'),
multiparty = require('connect-multiparty'),
multipartyMiddleware = multiparty(),
PORT = process.env.PORT || 27372;
var app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.post('/api/upload', multipartyMiddleware, function(req, res) {
var file = req.files.file;
console.log(file.name);
console.log(file.type);
console.log(file.path);
});
var server = app.listen(PORT, function() {
var host = server.address().address;
var port = server.address().port;
console.log('the App listening at http://%s:%s', host, port);
});
Now public folder is served to root url. Here is the client file public/index.html:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Upload example</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
</head>
<body>
<div class="container">
<div>
<h1>Upload example</h1>
<hr />
<div ng-app="fileUpload" ng-controller="MyCtrl">
<button type="button" class="btn btn-default" ngf-select ng-model="file">Upload using model $watch</button>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script src="http://rawgit.com/danialfarid/ng-file-upload/master/dist/ng-file-upload.min.js"></script>
<script>
var app = angular.module('fileUpload', ['ngFileUpload']);
app.controller('MyCtrl', ['$scope', 'Upload', function($scope, Upload) {
$scope.$watch('file', function() {
var file = $scope.file;
if (!file) {
return;
}
Upload.upload({
url: 'api/upload',
file: file
}).progress(function(evt) {
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
console.log('progress: ' + progressPercentage + '% ' + evt.config.file.name);
}).success(function(data, status, headers, config) {
console.log('file ' + config.file.name + 'uploaded. Response: ' + data);
}).error(function(data, status, headers, config) {
console.log('error status: ' + status);
})
});;
}]);
</script>
</body>
</html>
Now you can run node app and try it on localhost:27372 with your browser.
(Here is the gist version: https://gist.github.com/aksakalli/1a56072f066d65248885)
EDIT 2
Here is a basic implementation for option 1- Enabling CORS in NodeJS server. I am using cors package to handle header configuration, now app.js code would be like this:
var express = require('express'),
multiparty = require('connect-multiparty'),
cors = require('cors'),
multipartyMiddleware = multiparty(),
app = express(),
PORT = process.env.PORT || 27372;
app.use(cors());
app.post('/api/upload', multipartyMiddleware, function(req, res) {
var file = req.files.file;
console.log(file.name);
console.log(file.type);
console.log(file.path);
});
var server = app.listen(PORT, function() {
var host = server.address().address;
var port = server.address().port;
console.log('the App listening at http://%s:%s', host, port);
});
For the first error:
OPTIONS http://127.0.0.1:27372/upload 400 (Bad Request) angular.js:10514
The ng-file-upload Upload service which you are using removes the Content-Type header, as seen here, before the request.
But the parse method from multiparty seems to require it.
If you are working from the given example from the wiki, I would advise you to also use express and multiparty as middleware, as it is stated in that example.
Your app.js would look like that:
var express = require('express'),
// Requires multiparty
multiparty = require('connect-multiparty'),
multipartyMiddleware = multiparty();
var app = express();
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
// Example endpoint
app.post('/upload', multipartyMiddleware, function(req, res) {
// We are able to access req.files.file thanks to
// the multiparty middleware
var file = req.files.file;
console.log(file.type);
console.log(file.name);
});
app.listen(27372);
For the second error:
It's a CORS problem as mentioned. The proposed app.js should allow CORS because of the following lines:
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
How do I parse my JSON with external middleware now that Express doesn't carry a body parser?
For a while, I was using Express bodyParser to receive and respond to JSON posts to the server. Each time I started up the server, express said something about bodyParser being removed soon, and sure enough, I've updated and now JSON requests seem to be showing null.
So I didn't understand how middleware worked, and had followed an express tutorial to use the body parser. Now, using separate body parser middleware, it seems I'm doing it wrong.
Before, my syntax was:
app.use(express.bodyParser());
Now, with the module body-parser as middleware, it's like this:
app.use(bodyParser.json());
And an example as a whole:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
function listen() {
app.use(bodyParser.json());
app.post('/login', function (req, res) {
var username = req.body.username;
var password = req.body.password;
console.log('User ' + username + ' is attempting login...');
validate(username, password, function (err, result) {
if (err) loginFail(req, res, err);
else loginSucceed(req, res, result);
});
});
app.listen(3333);
}
listen();
I tried express.json() as the middleware, but that triggers the fatal error:
Error: Most middleware (like json) is no longer bundled with Express
and must be installed separately. Please see
https://github.com/senchalabs/connect#middleware.
That link leads to the body-parser middleware that I'm using via app.use(bodyParser.json()).
Update:
Using bodyParser.json() results in no error, but the data values are null:
User undefined is attempting login...
My client code should be fine, but here it is for completeness:
function sendLogin() {
popLogCreds(creds);
var loginCredentials = {
"username": creds.username,
"password": creds.password
};
console.log("Sending login credentials: " +
JSON.stringify(loginCredentials, null, 4));
request = $.ajax({
url: "http://54.186.131.77:3333/login",
type: "POST",
crossDomain: true,
data: loginCredentials,
dataType: "json",
error: function () {
postError("Uh Oh! The Officeball server is down.");
},
success: function (data) {
var ParsedData = data;
sessionStorage.username = creds.username;
sessionStorage.password = creds.password;
sessionStorage.fname = ParsedData.fname;
sessionStorage.lname = ParsedData.lname;
sessionStorage.rank = ParsedData.rank;
console.log(sessionStorage);
window.location.replace("app.html");
}
});
}
Which results in:
Sending login credentials: {
"username": "jonathan#evisiion.com",
"password": "J******!"
}
And then the result is the POST's error output, which is, as above:
error : function () {
postError("Uh Oh! The Officeball server is down.");
}
Don't take that error message literally. Just means an error happened. The server is, in fact, getting that request, as shown up above.
By default, $.ajax() sends data URL-encoded as mentioned in the description of the processData option:
By default, data passed in to the data option as an object (technically, anything other than a string) will be processed and transformed into a query string, fitting to the default content-type "application/x-www-form-urlencoded".
The body-parser that corresponds to that Content-Type and format is urlencoded():
app.use(bodyParser.urlencoded());
If you'd rather use JSON for the request, you'll need to provide the data already formatted as such along with a matching contentType that bodyParser.json() recognizes:
request = $.ajax({
url: "http://54.186.131.77:3333/login",
type: "POST",
crossDomain: true,
data: JSON.stringify(loginCredentials),
contentType: 'application/json',
dataType: 'json'
// ...
});
Note for cross-domain: With these modifications, the server will have to handle preflight OPTIONS requests for the route.
And, note that a bodyParser isn't needed for HEAD or GET requests as the data is included in the URL rather than the body. Express parses that separately into req.query.
In your node code,
make sure you put these two lines of code
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyparser.urlencoded({ extended: false }));
app.use(bodyparser.json());
......then your other code follows..
enjoy...
I am learning Node.Js, I would like to understand how to interact between front-end / backend.
I would do backend --> Front End interaction by sendig data using app.get(), but now, I'd like to understand how can I get variable from Front End to Backend.
Front-ENd. (I want to pass varGetFromFrontend to backend)
<html>
<script>
var varGetFromFrontend = 2; // This is variable I want to pass to backend
</script>
<head>
<title>Home Page</title>
</head>
<body>
<h1> This is a test</h1>
</body>
</html>
On Node.Js (backend)
var express = require('express');
var app = new express();
app.use(express.json());
app.use(express.static(__dirname + '/public'));
var entries = [
{"id":1, "title":"Hello World!"},
{"id":2, "title":"Hello World!"}
{"id":3, "title":"Hello World!"}
{"id":4, "title":"Hello World!"}
];
if(entries.id == varGetFromFrontend){
console.log("This is to print a variable by choosing it from Front End")
console.log(varGetFromFrontend)
}
var port = Number(process.env.PORT || 5000);
app.listen(port);
I would like to know how can I print "varGetFromFrontend" on server side
Make an HTTP request to the server. Include the variable in the request.
There are lots of ways to do this:
Put it in a hidden input in a form, then submit the form.
or
Set location.href to a new value and include the variable in it (e.g. in a query string)
or
Use the XMLHttpRequest object to make an HTTP request
or
Create a script element and include the variable in the URL for the src attribute
(This is a non-exhaustive list)
You can interact with the nodejs server from the browser with socket.io
First, install socket.io:
npm install socket.io
and write these code to their respective filenames.
app.js:
var express = require("express");
var http = require("http");
var socketIO = require("socket.io");
var app = express();
app.get("/", function(req, res){
res.sendfile("./index.html");
});
var server = http.createServer(app);
var io = socketIO.listen(server, {log: false});
io.sockets.on("connection", function(socket){
socket.on("sendVar", function(value){
console.log("The value of the variable is " + value);
});
});
server.listen(5000);
index.html:
<html>
<head>
<title>Index Page</title>
</head>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
var variableFromFrontEnd = 2;
var socket = io.connect("/");
socket.on("connect", function(){
console.log("connected!")
socket.emit("sendVar", variableFromFrontEnd);
});
</script>
</html>
and run it.
Check out the MEAN framework I built: http://mean.wolframcreative.com/
This uses Node as the back-end server utilizing Express as the API router. The front-end uses angular and is purely an api consumption tool.
Short answer is this:
in angular:
$http
.get('/api/users/bobsaget')
.success(function (response) {
console.log(response);
});
in node(with express):
app.get('/api/users/:username', function (req, res) {
var variable = req.params.username;
//do logic here with the database(mongo) to get user info:
db.users.findOne({username: username}, function (error, response) {
if (!error) {
res.send(200, response);
} else {
res.send(500, {success: false, message: error.message});
}
});
)};
Long answer is to play around with my framework and get your hands dirty.
I'm currently working on a restful framework for node call snooze. I'm writing an api along side it and it's going very well. The framework is written to be modular and easy to use. Everything is built around modules, routes, controllers, services, and validators.
https://github.com/iamchairs/snooze
snooze.module('myServer', ['snooze-stdlib']) // inject the snooze-stdlib module
.route('get', '/users/:username', { // define the route
controller: 'UserCtrl', // what controller should handle this route
action: 'getUserByUsername', // what action to perform on this route
validator: 'GetUsername' // before processing this action what validation should occur
})
.controller('UserCtrl', function(User) { // inject the User service
return {
getUserByUsername: function(res, options) {
User.getUserByUsername(options.query.username).then(function(username) {
res.send(200, username);
}).fail(function(err) {
res.send(500, err);
});
}
};
})
.service('User', function($q) { // inject the $q service
return {
getUserByUsername: function() {
var deferred = $q.defer();
deferred.resolve('iamchairs');
return deferred.promise;
}
};
})
.validator('GetUsername', function($validator) { // inject the validator service
return function(deferred, req) {
if($validator.isLength(req.query.username, 2, 32)) {
deferred.resolve(); // resolve (valid request)
} else {
deferred.reject([400, 'Username must be between 2 and 32 characters']); // reject (invalid request)
}
}
});