I want to send a jsonstring to my server from client. I'm pretty sure I'm sending it OK, But i can't seem to figure out how to read it on server-side. The variable 'sendJSONString' is what I'm trying to send. I've seen many examples where the data is sent in the URL and then extracted. But I'd really rather not do that.
On Client Side i have this code:
module.exports = function sendAuthToServer(retVal, _userName, _AUTHKey){
var sendJSONString = JSON.stringify({userName:_userName, AUTHKey:_AUTHKey});
var gotData = [];
var xhr = new XMLHttpRequest();
xhr.open('GET', encodeURI('/AUTH'));
xhr.onload = function() {
if (xhr.status === 200) {
gotData = JSON.parse(xhr.responseText);
retVal(gotData);
}
else {
alert('Request failed. Returned status of ' + xhr.status);
}
};
xhr.send(sendJSONString);
}
On Server Side i have this.
module.exports = function giveQueryList(app){
app.get('/AUTH', function(req, res) {
res.json('ServerResponse');
console.log(req.ip, req);
});
}
app is using express and is set up like this
//CONFIG ROUTER/SERVER
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));//MAKE CONTENT IN VIEWS FOLDER AVAILABLE TO CLIENT
app.set('port', process.env.PORT || 8888);
//USE MIDDLEWARE
app.use(express.static(path.join(__dirname, 'views')));
You are sending the data with a GET HTTP verb. Try changing that to POST or PUT (you'll need to adjust your express route accordingly).
If not done already, you should use middleware like body-parser to parse the information send by the client. Then, you can access the information posted/puted by the client on the req.body object.
Related
im trying to create a simple webpage with some server side functions but somehow 2 things arent working as they supposed to work.
via html button im running a clientside javascript that does a http post request.
Client side javascript
httpRequest = new XMLHttpRequest()
httpRequest.open('POST', '/test2')
httpRequest.send(var1,var2,var3,var4);
Server.js
var express = require('express');
var bodyParser = require("body-parser");
var dbFunc = require("./dbFunctions.js");
var app = express();
var path = require('path');
var port = 8888;
//allow to use body-parser
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
//allow to use static files
app.use(express.static("public"));
//listen to smth
app.post('/test2', function (req, res) {
console.log("worked");
});
//start server
app.listen(port);
console.log("Server running on port" + port);
My server detects this post http request and does the "console.log" but how do i get the parameters from the http.request as a variable? I tried to work with bodyParser but somehow my object is always empty.
Another thing is, ive created another Javascript file(dbFunctions.js) and also implemented it in the server file but if i try to run a function(dbFunc.test("hello") for example) it says "dbFunc.test is not a function".
dbFunctions.js
function DBFunctions(){
function test(a){
console.log(a);
}
}
Ive also tried to do something like this, but this gave me the same error.
function test(a){
console.log(a);
}
Could someone give me a hint or tell me what i am missing?
Answer1:
The way you are sending data into post request is wrong, you slould send in format of,
xhttp.send("val1=val1&val2=val2");
httpRequest = new XMLHttpRequest()
httpRequest.open('POST', '/test2')
httpRequest.send(var1=var1&var2=var2&var3=var2&var3=var3);
To POST data like an HTML form, add an HTTP header with setRequestHeader(). Specify the data you want to send in the send() method:
httpRequest = new XMLHttpRequest()
httpRequest.open('POST', '/test2')
httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
httpRequest.send(var1=var1&var2=var2&var3=var2&var3=var3);
In your server.js, use req.body to get those values.
app.post('/test2', function (req, res) {
console.log("worked");
console.log(req.body)
});
XMLHttp request example
Answer2:
From your dbFunctions.js file you should export your function using module exports in node js.
dbFunctions.js:
var exports = module.exports = {};
exports.test = function(a) {
console.log(a);
};
You can also do as,
module.exports = {
test: function(a) {
console.log(a)
},
}
Now in your server.js
var dbFunc = require("./dbFunctions.js");
dbFunc.test();
Node js module exports
All your posted variables will be available in req.body try console.log(req.body).
Secondly you most probably not exporting test function from dbFunction.js, that's why getting "dbFunc.test is not a function" because dbFunc.test is undefined.
Note: As mentioned in one of the comment, you need to use httpRequest.send(var1,var2,var3,var4); in the right way. It does not expect multiple parameters.
Like: httpRequest.send("var=var1&var1=var2")
Please refer: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send
I have an Express project that has client-side javascript in a separate file that generates a graph. I am trying to pass variables from the express routes to this javascript file so the graph can be drawn.
I have tried the code below but I am getting following error.
Error: Cannot find module 'js'
app.get('/users', function(req, res) {
res.render(path.join(__dirname, '../views/js/users_chart.js'), {
'users': users
});
});
I think it'd be helpful for you to review the Express documentation for res.render and serving static files
You can't render JS files.
It appears you want to serve your static user_chart.js with
/* server.js */
app.set('view engine', 'ejs');
app.register('.html', require('ejs'));
// serve your js statically
app.use('/js', path.join(__dirname, '../views/js/users_chart.js')
app.get('/users', function(req, res) {
// pass variable to html page
res.render('users.html', {
'users': users
});
});
// in users.html
<script type="text/javascript" src="/js/users_chart.js">
This post is probably helpful as well
After receiving great help, found out a solution.
In order to have a javascript file in the client side that would receive the variable from the routes, I had to send the variable in JSON from the routes file to the javascript file the client side. I used XMLHttpRequest in order to receive the JSON in the javascript file of the client side.
Bellow is the code for users_graph.js which is the client side javascript file.
var xmlhttp = new XMLHttpRequest();
var url = "/users";
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var users = JSON.parse(xmlhttp.responseText).users;
// do something with the users variable that was passed by the routes
}
};
xmlhttp.open("GET", url, true);
xmlhttp.setRequestHeader('Accept', 'application/json');
xmlhttp.send();
I'm very new to node and trying to set up a simple backend solution to handle the routes in my Backbone application. Right now I'm routing everything to index.html. My problem is when I make a data request the response comes back with Content-Type:text/html; charset=UTF-8 when I need it to be Content-Type:application/json. I know I need to set this header somewhere but not sure where and was wondering if someone could help?
JS
var express = require('express');
var port = 8000;
var server = express();
server.use('/dist', express.static(__dirname + '/dist'));
server.get('scripts/data/*.json', function(req, res) {
return res.json({
success: true
})
});
server.get('*', function(req, res){
return res.sendFile(__dirname + '/index.html');
});
server.listen(port, function() {
console.log('server listening on port ' + port);
});
You need to do it in get method
add
res.setHeader("Content-Type", "application/json");
before sendFile
https://nodejs.org/api/http.html#http_response_setheader_name_value
You can also use middleware:
In express you can use express.static(root, [options])
Where one of option can be: setHeaders function
Check these links:
Send additional http headers with Express.JS
http://expressjs.com/api.html
http://expressjs.com/starter/static-files.html
Here's another approach.
As pointed out in the answer above, you can pass additional parameters to express.static.
So, in order to serve your *.json files you should put this code about your * route:
app.use('/scripts', express.static(__dirname + '/scripts'), {
setHeaders: function(res) {
res.setHeader("Content-Type", "application/json");
}
});
So I have built a html form to interact with Slack. Currently my js code looks like this.
$("#submitemail").click(function(){
$.post(
"https://openpgh.slack.com/services/hooks/incoming-webhook?token=MY_SECRET_TOKEN",
JSON.stringify({'text':'invite request from: '+$("#email").val(),'username':'Slack Inviter','icon_emoji':':raising_hand:'})
).success(function(){
$("#email").val("");
});
});
if anyone were to just copy this right out of my html file they could just run a console command and change the JSON and bombard my slack group with massive amounts of nonsense until they hit the API call limit.
What I am wondering is if I could store this in my index.js (I am using a node.js template) as a var and then call it in the html.
Any options or advice is greatly appreciated I am very new to this.
My structure is:
Slack App
|_node_modules
| |_express
|_public
| |_index.html
| |_node.svg (idk what this does)
|_.gitignore
|_app.json
|_index.js
|_package.json
|_procfile
|_README.md
the code for my index.js is just
var express = require('express');
var app = express();
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
app.listen(app.get('port'), function() {
console.log("Node app is running at localhost:" + app.get('port'))
});
I can throw in my full html if you want its just a basic modal w/ a button to click to execute the form and pull the email.
Disclaimer: this code is untested
You would basically do something like this:
index.js (commented to explain what i added):
var express = require('express');
// install request module
var request = require('request');
var app = express();
// make a new route that you can call from the client side
app.get('/getSlackData', function(req, res) {
//variable to hold your response from slack
var slackResponse;
//make the request to slack
var slackUrl = "https://openpgh.slack.com/services/hooks/incoming-webhook?token=MY_SECRET_TOKEN""
request(slackUrl, function (error, response, body) {
if (!error && response.statusCode == 200) {
slackReponse = response;
} else {
console.log(error);
});
return slackResponse;
});
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
app.listen(app.get('port'), function() {
console.log("Node app is running at localhost:" + app.get('port'))
});
So we added a new route, that is basically an API you can call from the client side, it will return the JSON object that you got from Slack. You can pretty much leave your client side code the same, just change the route you're calling:
$("#submitemail").click(function(){
$.post("/getSlackData",
JSON.stringify({'text':'invite request from:'+$("#email").val(),'username':'Slack Inviter','icon_emoji':':raising_hand:'})
).success(function(){
$("#email").val("");
});
});
I hope I understood your question correctly, this should at least get you pointed in the right direction.
I have the following Node.js code:
var express = require('express');
var app = express.createServer(express.logger());
app.use(express.bodyParser());
app.post('/', function(request, response) {
response.write(request.body.user);
response.end();
});
Now if I POST something like:
curl -d user=Someone -H Accept:application/json --url http://localhost:5000
I get Someone as expected. Now, what if I want to get the full request body? I tried doing response.write(request.body) but Node.js throws an exception saying "first argument must be a string or Buffer" then goes to an "infinite loop" with an exception that says "Can't set headers after they are sent."; this also true even if I did var reqBody = request.body; and then writing response.write(reqBody).
What's the issue here?
Also, can I just get the raw request without using express.bodyParser()?
Starting from express v4.16 there is no need to require any additional modules, just use the built-in JSON middleware:
app.use(express.json())
Like this:
const express = require('express')
app.use(express.json()) // <==== parse request body as JSON
app.listen(8080)
app.post('/test', (req, res) => {
res.json({requestBody: req.body}) // <==== req.body will be a parsed JSON object
})
Note - body-parser, on which this depends, is already included with express.
Also don't forget to send the header Content-Type: application/json
Express 4.0 and above:
$ npm install --save body-parser
And then in your node app:
const bodyParser = require('body-parser');
app.use(bodyParser);
Express 3.0 and below:
Try passing this in your cURL call:
--header "Content-Type: application/json"
and making sure your data is in JSON format:
{"user":"someone"}
Also, you can use console.dir in your node.js code to see the data inside the object as in the following example:
var express = require('express');
var app = express.createServer();
app.use(express.bodyParser());
app.post('/', function(req, res){
console.dir(req.body);
res.send("test");
});
app.listen(3000);
This other question might also help: How to receive JSON in express node.js POST request?
If you don't want to use the bodyParser check out this other question: https://stackoverflow.com/a/9920700/446681
As of Express 4, the following code appears to do the trick.
Note that you'll need to install body-parser using npm.
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.listen(8888);
app.post('/update', function(req, res) {
console.log(req.body); // the posted data
});
For 2019, you don't need to install body-parser.
You can use:
var express = require('express');
var app = express();
app.use(express.json())
app.use(express.urlencoded({extended: true}))
app.listen(8888);
app.post('/update', function(req, res) {
console.log(req.body); // the posted data
});
You should not use body-parser it is deprecated. Try this instead
const express = require('express')
const app = express()
app.use(express.json()) //Notice express.json middleware
The app.use() function is used to mount the specified middleware function(s) at the path which is being specified. It is mostly used to set up middleware for your application.
Now to access the body just do the following
app.post('/', (req, res) => {
console.log(req.body)
})
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json())
var port = 9000;
app.post('/post/data', function(req, res) {
console.log('receiving data...');
console.log('body is ',req.body);
res.send(req.body);
});
// start the server
app.listen(port);
console.log('Server started! At http://localhost:' + port);
This will help you. I assume you are sending body in json.
This can be achieved without body-parser dependency as well, listen to request:data and request:end and return the response on end of request, refer below code sample. ref:https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/#request-body
var express = require('express');
var app = express.createServer(express.logger());
app.post('/', function(request, response) {
// push the data to body
var body = [];
request.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
// on end of data, perform necessary action
body = Buffer.concat(body).toString();
response.write(request.body.user);
response.end();
});
});
In my case, I was missing to set the header:
"Content-Type: application/json"
Try this:
response.write(JSON.stringify(request.body));
That will take the object which bodyParser has created for you and turn it back into a string and write it to the response. If you want the exact request body (with the same whitespace, etc), you will need data and end listeners attached to the request before and build up the string chunk by chunk as you can see in the json parsing source code from connect.
The accepted answer only works for a body that is compatible with the JSON format. In general, the body can be accessed using
app.use(
Express.raw({
inflate: true,
limit: '50mb',
type: () => true, // this matches all content types
})
);
like posted here. The req.body has a Buffer type and can be converted into the desired format.
For example into a string via:
let body = req.body.toString()
Or into JSON via:
let body = req.body.toJSON();
If you're lazy enough to read chunks of post data.
you could simply paste below lines
to read json.
Below is for TypeScript similar can be done for JS as well.
app.ts
import bodyParser from "body-parser";
// support application/json type post data
this.app.use(bodyParser.json());
// support application/x-www-form-urlencoded post data
this.app.use(bodyParser.urlencoded({ extended: false }));
In one of your any controller which receives POST call use as shown below
userController.ts
public async POSTUser(_req: Request, _res: Response) {
try {
const onRecord = <UserModel>_req.body;
/* Your business logic */
_res.status(201).send("User Created");
}
else{
_res.status(500).send("Server error");
}
};
_req.body should be parsing you json data into your TS Model.
I'm absolutely new to JS and ES, but what seems to work for me is just this:
JSON.stringify(req.body)
Let me know if there's anything wrong with it!
Install Body Parser by below command
$ npm install --save body-parser
Configure Body Parser
const bodyParser = require('body-parser');
app.use(bodyParser);
app.use(bodyParser.json()); //Make sure u have added this line
app.use(bodyParser.urlencoded({ extended: false }));
What you claim to have "tried doing" is exactly what you wrote in the code that works "as expected" when you invoke it with curl.
The error you're getting doesn't appear to be related to any of the code you've shown us.
If you want to get the raw request, set handlers on request for the data and end events (and, of course, remove any invocations of express.bodyParser()). Note that the data events will occur in chunks, and that unless you set an encoding for the data event those chunks will be buffers, not strings.
You use the following code to log post data:
router.post("/users",function(req,res){
res.send(JSON.stringify(req.body, null, 4));
});