Getting data sent from AJAX on Express server - javascript

My code below is sending data across my express server using a AJAX request. I need to access that data once sent, on my express server to do some manipulation. How can I go about doing this?
Express Server Snippet:
app.get("/time",function(req,res){
client.messages.create({
to: "+1" + req.data.number,
from: '+166**',
body: "This is the ship that made the Kessel Run in fourteen parsecs?",
mediaUrl: "https://c1.staticflickr.com/3/2899/14341091933_1e92e62d12_b.jpg",
});
});
Ajax Request:
$.ajax({url: "/time",
data : { name : 'Justin', number : '662***' }
});

If you are talking about the GET variable in the server:
app.get("/time",function(req,res){
client.messages.create({
to: "+1" + req.params.number, // should be `req.params` instead
from: '+166**',
body: "This is the ship that made the Kessel Run in fourteen parsecs?",
mediaUrl: "https://c1.staticflickr.com/3/2899/14341091933_1e92e62d12_b.jpg",
});
console.log(req.params.name)
console.log(req.params.number)
});
If you are saying the response of the server, then:
$.ajax({
url: "/time",
data : { name : 'Justin', number : '662***' }
}).done(function (response) {
console.log(response)
});
I've read the question 3 times, and still couldn't figure out what was being asked, sorry.

If you are trying to send the data to Express, you probably should be doing this with a "POST" method in your Ajax call. Then, having a route just like the one you have, but app.post. You also should use the "body-parser" middleware, before your "post" route.
So, you should have something like this on your server (regarding just what I am saying):
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/time', (req, res) => {
console.log(req.body); // your data here
})
In your Ajax call, just add a 'post' method.
What #joaumg says it's about req.params is also correct, but with a POST seems more correct to me. Your data will be safer.

Related

Parse sendBeacon data in Express

I'm trying to start logging my own WebVitals. The simple use-case in their example docs looks like this:
function sendToAnalytics(metric) {
// Replace with whatever serialization method you prefer.
// Note: JSON.stringify will likely include more data than you need.
const body = JSON.stringify(metric);
// Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
(navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) ||
fetch('/analytics', {body, method: 'POST', keepalive: true});
}
That all seems simple enough. Here's my actual implementation:
function sendToLog(metric) {
// Replace with whatever serialization method you prefer.
// Note: JSON.stringify will likely include more data than you need.
const body = JSON.stringify(metric);
console.log(`Sending body ${body}`);
// Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
// (navigator.sendBeacon && navigator.sendBeacon('https://localho st:9292/api/log', body)) ||
fetch('https://localhost:9292/api/log', {body: body, method: 'POST', headers: { 'Content-Type': 'application/json' }, keepalive: true});
}
I had to modify the fetch to include the "body" property name and add headers to get it to work, but that is now working. However, if I uncomment the navigator.sendBeacon line, I just get {} for the body.
I'm using NodeJS and Express on the backend. My starting point was this:
const app = express();
app.use(
express.json({
// We need the raw body to verify webhook signatures.
// Let's compute it only when hitting the Stripe webhook endpoint.
verify: function (req, res, buf) {
if (req.originalUrl.startsWith(API_PREFIX + '/webhook')) {
req.rawBody = buf.toString();
}
},
})
);
app.use(cors());
// Expose an endpoint for client logging.
app.post(API_PREFIX + '/log', async (req, res) => {
const message = req.body;
console.log('Got message');
console.dir(message, { depth: null });
logger.info(message);
res.sendStatus(200);
});
There's this similar question, where the accepted answer suggests that adding body-parser and app.use(bodyParser.raw()) should do the trick, and then in the comments there's discussion of using bodyParser.json()) instead.
I've tried both of those:
import bodyParser from 'body-parser';
...
//app.use(bodyParser.raw());
//app.use(bodyParser.json());
app.use(
express.json({
// We need the raw body to verify webhook signatures.
// Let's compute it only when hitting the Stripe webhook endpoint.
verify: function (req, res, buf) {
if (req.originalUrl.startsWith(API_PREFIX + '/webhook')) {
req.rawBody = buf.toString();
}
},
})
);
app.use(cors());
(i.e., uncommenting either of the two lines at the beginning), and in all 3 cases I still get an empty body when sendBeacon is used.
The Express documentation says,
[express.json] is a built-in middleware function in Express. It
parses incoming requests with JSON payloads and is based on
body-parser....A new body object containing the parsed data is
populated on the request object after the middleware (i.e. req.body),
or an empty object ({}) if there was no body to parse, the
Content-Type was not matched, or an error occurred.
So, a) I guess I shouldn't need the body-parser, since express.json is just doing that anyhow; and b) I'm hitting one of those three conditions (there's no body to parse, the Content-Type was not matched, or an error occurred). Assuming that's the case, how do I diagnose which one it is, and then fix it (in such a way that the fetch fallback continues to work). Or, if there's some other problem, back to the original question, how do I get this to work? :)
navigator.sendBeacon sends Content-Type: text/plain whereas express.json() only parses the body if Content-Type: application/json.
Use express.text() in combination with JSON.parse(req.body) instead, or additionally:
app.post(API_PREFIX + '/log',
express.json(), express.text(), function(req, res) {
if (typeof req.body === "string") req.body = JSON.parse(req.body);
...
});

Headers not set node.js api push notification

Hello im trying to set up push notifications for my webapp.
I'm getting my subscription like I should.
It saves it to my database correctly.
It sends my notification like it should if there only is ONE user in the db
and i want to send to more than only one user :)
Im using:
Vue.js (framework)
Axios (post)
node.js (api)
mongoDB (database)
Here's my post to API.
await axios({
method: 'post',
url: 'API',
data: {
subscription: JSON.stringify(subscription),
storeId: storeId
},
headers: {
'Content-Type': 'application/json'
}
})
It registreres my post, but then i get an throw error.
that "Can't set headers after they are sent."
I'm using CORS in my app like this:
const cors = require('cors')
const app = express();
app.use(bodyParser.json());
app.use(cors())
app.use(morgan('combined'))
The way I'm handling the post from my website is by finding my subscriptions and then map through and say foreach subscription
webpush
//subscribe routes
app.post('/pushNotification', (req, res) => {
var storeId = req.body.storeId
res.setHeader('Content-Type', 'application/json');
console.log(storeId)
if (req.body.storeId != null) {
console.log('Test1')
//get pushSubscription object
//create payload
const payload = JSON.stringify({ title: 'push test' })
Push.find({
"storeId": storeId
},
'subscription', function(error, response) {
console.log('Test2')
console.log(response)
response.map(item => {
res.status(201).json({});
console.log('Test3')
var subscription = item.subscription
console.log(subscription)
webpush.sendNotification(subscription, payload).catch(err => console.error(err));
})
})
} else {
res.send("failed")
}
})
As i can read around somewhere is it im not setting headers or something right. I have used cors like in tutorials and stuff.
So it's like it is crashing because it iterates wrong.
but i can't see how.
ERROR MESSAGE:
Thanks in advance
you are getting this error because res.status(201).json({}) has already set the headers and sent back the response to the client but webpush.sendNotification also trying to set the headers.You should use only webpush.sendNotification(subscription, payload).catch(err => console.error(err));
res.json([body]) sets the corresponding header and sends the result:
Sends a JSON response. This method sends a response (with the correct content-type) that is the parameter converted to a JSON string using JSON.stringify().
So, first of all you don't need to set header manually.
second, If the response has more than one item, since you can't send multiple result for a request, you shouldn't use res.json in a map.
Moreover, be aware of webpush.sendNotification that it may send a result too.

Handling ajax requests, not receiving data

i'm having a hard time setting up my client-side ajax calls to send data to node express server.
i want to fire my ajax request "onclick" of an href link.
I'm trying to send the ID of the link as a variable to the server, but the server doesn't receive my data (without setInterval)
if i put the ajax request inside a setInterval() (which i don't want to do, because i only want to send the data once a link is clicked to the server),
the server receives the data in res.req.body, why?
client side:
$('.link_group').click(function () {
data = $(this).attr('id');
$.ajax({
type: "POST",
url: "/ajax_handler",
data: {id: data}
});
});
server side
app.post("/ajax_handler", function(req, res) {
res.send({ //works as it should....
user : req.session.user,
data_objekt: req.session.data
});
if(res.req.body) {
console.log(res.req.body);
}
});
Is this even a common way to "catch" the data from client?
if(res.req.body) {...
doesn't seems right, but i don't know how to do it in a smarter way / can't find any good examples.
I'm about to fire 3-4 Ajax other requests to /ajax_handler which leads to my next question: how to handle multiple ajax requests to the same url?
Thanks in advance!
Are you parsing the request? req.body is initially empty/undefined. You will need to pass it to a middleware that parses the data into req.body. Body-parser is a nodejs module that can achieve this. Here's how to a POST request with JSON data being sent.
const bodyParser = require('body-parser')
app.use(bodyParser.json());
app.post("/ajax_handler", function(req, res) {
res.send({ //works as it should....
user : req.session.user,
data_objekt: req.session.data
});
if(req.body) {
console.log(req.body);
}
});

Neither Node.js PUT or POST routes are presenting the data that is being received

I tried this with a number of different modules and methods.
Even by proving the other modules do work as expected in Node by building a separate test project and testing each module individually.
Posting FROM Node's hosted router to a remote API (not TO Node's hosted API)
This problem is not one of SENDING data to an API. It must IMO a problem in the receiving API's not giving up the data it IS receiving for some reason.
I've proven the PUT or POST calls are sending the data by sending the call to http://httpbin/org. That site shows me I'm sending what I expect to be sending.
Here is how I'm sending. I can even see in the receiving API that that API is certainly getting called successfully.
-- sending -- ((Again. This shows my node.http attempt. But I get the same problem using requestjs, requestifyjs, needlejs))
router.get('/', function (req, res, next) {
var hst = req.headers.host.split(':');
var lookbackURL = 'https://' + req.headers.host + req.baseUrl;
lookbackURL = 'http"httpbin.org/put';
var dat = {
what: 'ever'
, try: 'again'
};
var bdy = JSON.stringify(dat);
var options = {
host: hst[0], port: hst[1], path: req.baseUrl, method: 'PUT'
, headers: { 'Content-Type': 'application/json' }
};
var r = nodeHttp.request(options); r.write(bdy); r.end();
res.sendStatus(200);
});
-- receiving --
router.put('/', function (req, res, next) {
console.log('r', req);
});
No matter what module or method I use, in all cases, the receiving req object doesn't contain the what or try data.
BUT in my test project the data is there as I expect it to be, in all cases.
Doing the same console.log(req); in the test project, reqestjs, requestjs, needlejs, node.http all show a proper body object.
But in this problem there isn't a body object in req.
And sending this put/post to http://httpbin.org I can see the body object is being sent.
Any ideas?
Issue found. And it was something no one on here could have gotten for the code I posted.
For reasons I will not go into I have to take body-parser out this application. This also means app.use() won't have a parser given to it.
And that means I have to deal with getting the data on my own. So I've added a req.on('data') listener to read the chunk from the call to the API.
router.put('/', function (req, res, next) {
var data = '';
req.on('data', function (chunk) {
data += chunk;
.....
});
.....
I also decided to do this as a PUT using Requestify.
This just goes to show how easy it is to become complacent and forget how things really work; the assumption of body-parser (or other things) always being there for instance. Or what it is really doing for you.
NEXT I have to figure out how to get a value out of the `req.on('data) back to the method PUTting to the API. Any tips? Appreciated.

How to perform a POST request with session data to an endpoint within the server node js

I am working on express and I need to perform a POST request to an endpoint within the server. My code for this is :
request({
url : 'http://localhost:3000/api/oauth2/authorize',
qs:{
transaction_id:req.oauth2.transactionID,
user:req.user,
client : req.oauth2.client
},
headers:{
'Authorization':auth,
'Content-Type':'application/x-www-form-urlencoded'
},
method:'POST'
},function(err,res,bo){
console.log("Got response with body :"+bo);
});
localhost is the current server, this works properly but the session data is lost when i perform the POST request.
Is there any other way to perform a POST within the same server or to save the session data such that it is maintained after the POST?
Well, typically you register your routes something like:
var handlePostRequest = function(req,res,next) {
// process req.body etc.
};
app.post('/api/oauth2/authorize', handlePostRequest);
If you want to call that endpoint from within your application, you simply call handlePostRequest() providing the req, res, next objects as well.
Assuming handlePostRequest is in global scope, or required already; in your example that would be:
app.get('/some/other/endpoint', function(req,res,next){
// override the default req.body with your supplied data
req.body = {
transaction_id: req.oauth2.transactionID,
user: req.user,
client: req.oauth2.client
};
// you may also override req.headers etc. for authorization
// ...
// then call the "api" again with the new values
return handlePostRequest(req,res,next);
});
IF you however strictly want to make a POST request (for some reason), you need to supply the sessionID as well, which will be in your cookie. Then the session data will be available.

Categories

Resources