I have tried reading a lot of posts on this but none have really helped me. I don't get how to access the data I am sending from a post request. For context, I have a .ejs html file where I am making an asynchronous post request to the server. This is the code for that:
$("#commentButton" + thisPostId).click(function () {
$.ajax({
type: "POST",
url: "/comment",
data: {
comment: $("#commentInput" + thisPostId).val(),
postId: $("#postIdInput" + thisPostId).val()
},
success: function (data) {
if (data.success) {
let asyncComment = "<p>whatsupbro</p>";
$("#li" + thisPostId).append(asyncComment);
} else {
// ADD BETTER ERROR IMPL
alert('error');
}
}
});
On the server side, I want to retrieve the arguments in "data". This is what I have so far. I have tried so many things, like doing req.data.comment, req.comment, etc. Below is the start of my node.js function that is supposed to get the request and do some stuff with it. What matters is I want the comment in commentInfo and postId in commentInfo to be what I am sending in the post request as "comment" and "postId". I really am just not sure how to access this data (req.body.mycomment doesn't work either).
var createComment = function(req, res) {
var commentInfo = {
comment: req.body.myComment,
username: req.session.username,
commentId: new Date().getTime(),
postId: req.body.postId
};
console.log(req['comment']);
Thanks for the help. If there is anything else I should add let me know.
You need appropriate middleware to actually read the body of the POST request and to then parse it and place the contents into req.body.
Assuming you are using Express, then you need one of these placed before the route that receives the POST:
app.use(express.json()); // for application/json content-type
app.use(express.urlencoded()); // for application/x-www-form-urlencoded content-type
Related
I have a backend that uses Node and the Express framework and a frontend in React. The code is in Typescript.
My backend uses the elastic search client to fetch the data but I don't think that's where my problem lies.
I need to retrieve a parameter that I fetch from the backend via the http header of my response in my frontend.
To do this I used these two functions from the Express doc http://expressjs.com/en/4x/api.html#res.set and http://expressjs.com/en/4x/api.html#res.json
So I wrote the following code for my route:
searchRouter.get('/search', (asyncHandler(async (req, res) => {
const response = await client.search<HitResult>({
index: my-index,
scroll: "1m",
body: {
My elastic request
}
});
res.set('data_to_send',response.body.data_to_send);
console.log('is there a hearder? ', res.headersSent) //always return false
res.json(response);
})));
But the header does not change with this method. So I tried to create an asynchronous function to fill my header with the following code:
async function buildHeader(response: express.Response<any, Record<string, any>>, headerName: string, headerValue: string | undefined): Promise<any> {
response.header(headerName,headerValue);
}
searchRouter.get('/search', (asyncHandler(async (req, res) => {
const response = await client.search<HitResult>({
index: my-index,
scroll: "1m",
body: {
My elastic request
}
});
await buildHeader(res, 'data_to_send', response.body.data_to_send);
console.log('is there a hearder? ', res.headersSent) //always return false
res.json(response);
})));
Whatever I do the header does not change and keeps its basic form, the following one:
content-length: "50643"
content-type: "application/json; charset=utf-8"
Does anyone see what I'm doing wrong and could help me, that would save me. Thanks in advance :)
As Itai pointed out to me, my problem came from the middleware I was using, CORS. By adding in the options of this middleware the two following fields:
'allowedHeaders': ['data_to_send'],
'exposedHeaders': ['data_to_send'],
Everything works as expected.
For more info:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
This must be a stupid question, but I'm just starting and would appreciate any help!
So I have this code to get query parameter:
app.get('/', (req, res) => {
var code = req.query.code;
console.log(code);
And when I go to http://localhost:3000/?code=123, I get the code value in console, so it works fine.
Now, I need to send a GET request and add the value of the var code, this is where I'm stuck.
Let's say, I should send a GET request to 'http://testtesttest123.com/' + var code + 'hi'.
How can I do this?
I've tried this way and some other ways, but nothing worked:
axios.get('http://testtesttest123.com/?&code=', {params: {code}}, '&hi')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
});
Thank you in advance!
The axios.get call should look like this.
axios.get('http://testtesttest123.com/?code=' + code + '&hi')
With code = 123, this will call the URL http://testtesttest123.com/?code=123&hi.
Use the params config to send through query parameters. To support your empty hi parameter, you can include it in the URL string
axios.get("http://testtesttest123.com/?hi", {
params: { code }
})
For a code value of 123, this will perform a GET request to
http://testtesttest123.com/?hi&code=123
It will also ensure that the code value is made safe for use in URLs
STUDENT QUESTION!
I'm learning about Node.js/Express and MySQL databases using the Sequelize ORM. Traditionally in our simple applications, after querying a MySQL database with Sequelize, we will issue a res.redirect('/') within Express PUT route's .then promise, similar to this:
app.post("/", function (req, res) {
db.Burgers.create({
burger_name: req.body.burger_name
}).then(function () {
res.redirect('/');
});
});
I'm running into a problem when creating a sequelize query using the findOrCreate() method. Namely, I'm struggling to find where to place the res.redirect statement on an AJAX PUT request. For some reason, when I have the res.redirect('/') attached within the express route for the PUT statement, I will see duplicate PUT requests in the Chrome Network inspector. The first PUT request is displayed as (localhost:3000/devour, type:text/plain, status:302).
The PUT request is received by the Express server and the sequelize query succeeds, updating the proper tables in the MySQL database. However, the redirect on the Express route does not succeed and Chrome Inpector shows an error " PUT http://localhost:3000/ 404 (Not Found)" and when I look at the Network tab I see a second PUT request (localhost:3000/, type:xhr, status:404).
This is the Express PUT route:
app.put("/devour", function (req, res) {
var customerId;
// Check to see if the customer name entered already exists, if not create
db.Customers.findOrCreate({
where: {
customer_name: req.body.customer_name
}
})
.spread((user, created) => {
if (created) console.log("User created");
customerId = user.id;
var update = {
"devoured": req.body.devoured,
"CustomerId": customerId
};
db.Burgers.update(update, {
where: {
id: req.body.id
}
}).then(function () {
res.redirect('/');
});
})
});
What is generating this second PUT request? Is it a response rather than request?
This is my first Sequelize query using the findOrCreate() method so perhaps I'm misunderstading the use of .spread().
If I comment out the res.redirect on the PUT Express route, the error does not occur but I have to manually refresh the page to see the updated data from the MySQL database.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
I added the 303 status code to my Express PUT route: res.redirect(303, '/'). This elmininated the 404 error on the redirect, however the HTML page was not refreshing with GET request to reload the page with updates from the PUT request.
Then I looked at my Ajax call and realized that, perhaps, I needed to add code there to handle the response from the server:
$.ajax({
url: URL,
type: 'PUT',
contentType: 'application/json',
data: JSON.stringify(dataObject)
})
So I added a .done promise callback and the page successfully refreshes following the PUT request:
$.ajax({
url: URL,
type: 'PUT',
contentType: 'application/json',
data: JSON.stringify(dataObject)
}).done(function(){
window.location.href = window.location.origin + '/'
})
I guess I'm a bit confused about why the server-side res.redirect(303, '/'), alone, doesn't result in the page refresh on the client-side. What is the point of providing the '/' path as an argument?
Thank you!
You can read more about what a redirect header does when included in PUT requests in Why POST redirects to GET and PUT redirects to PUT?
Long story short your PUT request remains a PUT request, just gets redirected to /.
Your app should work properly if you provide 303 status code.
res.redirect( 303, '/' );
I have a collection like
{
id:"david123",
friends[{id:joe321, lname"woo", fname"joe"}]
}
i want to add new elements into friends
i currently have this, but it does not seem to be working
app.post('/users/:uid/friends', function(req, res){
var userId = req.params.uid;
Friend.update({'_id': userId},
{$push: {Friends: req.body.friend}},
{ upsert : true },
function(err, result){
if (err){
console.log(err);
} else {
res.status(200).json(result);
}
})
});
i defined my schema like this
var FriendSchema = new mongoose.Schema({
_id: String,
Friends: [{
_id: String,
fname: String,
lname: String
}]
});
when i make a request i send
{ friend: '{userId:"john123",lname"smoth",fname"john"}',
userId: 'userId123' } and im getting
[TypeError: Cannot use 'in' operator to search for '_id' in {userId:"john123",lname"smoth",fname"john"}]
The sentence "it does not seem to be working" tells us nothing, really. Is there any error printed? Is there bad data inserted? No data? What is the response to the HTTP request? Those are the most important questions but since no relevant info is provided I can only give you some hints:
Make sure that the connection to Mongo is successful
Make sure that you're connecting to the database that you think you are
Make sure you use body parser with correct encoding if needed
Make sure to use $addToSet instead of $push to avoid duplicates
Make sure to return a response on error and not only on success
Make sure you send a request with POST method with JSON content type
Make sure that you send the data in the request body
Make sure that the JSON in your request contains the friend property
Make sure you have some request logging
For (3) see: https://github.com/expressjs/body-parser#bodyparserjsonoptions
For (4) see: https://docs.mongodb.com/manual/reference/operator/update/addToSet/
You didn't say anything about a framework that you use and you did not your question with a framework tag but your code suggests that you may be using Express. If that's the case then to use req.body in the request handlers you need to use a correct body parser middleware:
npm install body-parser --save
and in your code - at the beginning:
const bodyParser = require('body-parser');
and somewhere after you have app but before app.post(...); you need:
app.use(bodyParser.json());
if you want to have the request body parsed as JSON so you could use req.body and req.body.friend in your handler.
And use some basic logging in your request handler:
app.post('/users/:uid/friends', (req, res) => {
// start with:
console.log('Request body:' JSON.stringify(req.body));
// the rest of the logic ...
});
to see what is actually passed in the response and that it is correctly deserialized by the appropriate body parser.
I am using Node.js and the request module to create a backend, and we've chose Elasticsearch as our data storage. All fine so far, except it seems Node doesn't support request bodies on GET requests? This is necessary for Elasticsearch's _search API, which expects only GET requests as part of their semantic design. Is there a solution to force Node to send the request body even in the cases of a GET request, or a mean to use _search on Elasticsearch with another HTTP verb?
function elasticGet(url, data) {
data = data || {};
return Q.nfcall(request.get, {
uri: url,
body: JSON.stringify(data) //<-- noop
}).then(function(response) {
return JSON.parse(response[1]);
}, function(err) {
console.log(err);
});
}
The _search API also accepts the POST verb.
For simplicity, why not use their api rather than manually making requests?
simple example:
var elasticsearch = require('elasticsearch'),
client = new elasticsearch.Client({
host: '127.0.0.1:9200',
log: 'trace'
});
client.search({
index: '[your index]',
q: 'simple query',
fields: ['field']
}, function (err, results) {
if (err) next(err);
var ids = []
if (results && results.hits && results.hits.hits) {
ids = results.hits.hits.map(function (h) {
return h._id;
})
}
searchHandler(ids, next)
})
You can combine it with fullscale labs elastic.js to build really complex queries, really fast.
https://github.com/fullscale/elastic.js
I had such an issue a few days ago.
tld;dr use POST
According to https://www.elastic.co/guide/en/elasticsearch/guide/current/_empty_search.html#get_vs_post you can also use POST with elastic.
I tried it with axios but it returns all data like with no body.
So I used POST instead. It works for me and I hope it will help to someone else.