I will demonstrate my problem with this simplified code:
app.get('/test', (req, res) => {
let x = req.query.someVar;
app.post('/test', (req, res) => {
console.log(x);
});
res.send(`Hello ${req.query.someVar}`);
});
The first time this code runs, the POST callback function saves a reference to x which is whatever I pass as query parameters. if I change the query parameters, send another GET request it will be updated in the server's response i.e.res.send(Hello ${req.query.someVar}); but a POST request will still log the original x value to the console.
Why is it behaving this way? I have tried many things like passing by objects and through other functions, etc..
I am familiar with how closures work, but obviously not entirely as this is most definitely a problem with the POST call back preserving the value of the query parameters and not updating them.
Thanks.
I'm not sure what you are trying to do. No one defines a POST inside of a GET, they do that at the root level, unless you want the GET request to change the behavior of your server. app.post means 'add a new route to handle a POST'. Perhaps you wanted to actually send an HTTP request from the GET handler?
If you want the behavior to change maybe just handle the POST at the root level and set a global flag in the GET handler to indicate that POST should do something different with subsequent requests.
Related
I'm setting up my routes for an expressjs app, and I'm seeing 2 routes being executed when I hit one endpoint. Here is my code:
app.get("/forgot-password", (req, res) => {
....
});
app.get("/:modelName/:id?", (req, res) => {
....
});
I get that the second one essentially will catch everything if the first one is not a match. But I was under the impression that once one route is matched, no others are ran. The correct output is showing in the browser, but I'm seeing errors from the second route show up in my console.
Is there any way to prevent this other than putting some type of prefix to the second route? (making it /model/:modelName...)
Be sure to end your request with req.end, otherwise the request object will get passed to the next middleware in the stack.
Or be sure to call a method that calls req.end, such as res.redirect() or res.send.
I am trying to determine if i can call res.send(data) and then res.render('reports') simultaneously.
To explain further in detail, when i route to '/reports', first on my server side i making a REST call to an API which returns back json data. Now i want this json data to be accessed on the client, for which i am making an ajax call from my javascript. Hence the use of res.send(), but i also want to render the page in this call
So it looks like the following on my server side code
router.get('/reports', function(req,res){
//Making the REST Call to get the json data
//then
res.send(json);
res.render('reports');
});
Every time i hit the '/reports' on the browser, I see the json value instead of the page being rendered and my console throws an Error: Can't set headers after they are sent.
You could use content negotiation for that, where your AJAX request sets the Accept header to tell your Express server to return JSON instead of HTML:
router.get('/reports', function(req,res) {
...
if (req.accepts('json')) {
return res.send(theData);
} else {
return res.render('reports', ...);
};
});
Alternatively, you can check if the request was made with an AJAX call using req.xhr (although that's not 100% failsafe).
No you can't do both, but you could render the page and send the data at the same time:
res.render('reports',{data:json});
and then access those data in the newly rendered page.
alternatively you could send a flag when making the call , and then decide whether you want to render or send based on this flag.
Ideally, it needs to be 2 separate route, one spitting json and other rendering a view. Else, you could pass a url param, depending on which you return json or render a view.
router.get('/reports/json', function(req,res){
var data = JSON_OBJECT;
res.send(data);
});
router.get('/reports', function(req,res){
var data = JSON_OBJECT;
res.render('path-to-view-file', data);
});
No, you can't. You can only have a single response to a given request. The browser is either expecting an HTML document or it is expecting JSON, it doesn't make sense to give it both at once.
render just renders a view and then calls send.
You could write your view to output an HTML document with a <script> element containing your JSON in the form of a JavaScript literal.
I am trying to write a json object in my node application, integrating the Twilio API. When console logging the object all objects are returned properly but when I write it to the document only the first object is written. Why? How should I change the code to see the same written response as in my console log.
var express = require('express');
var app = express();
app.use(express.bodyParser());
app.get('/', function(req, res) {
var accountSid = 'xxx';
var authToken = 'xxx';
var client = require('twilio')(accountSid, authToken);
client.messages.list({
from: "xxx",
to: "xxx"
}, function(err, data) {
data.messages.forEach(function(message) {
console.log(message.body); // THIS WILL DISPLAY ALL OBJECTS
res.json(message.body); // THIS WILL ONLY DISPLAY THE FIRST OBJECT
});
});
});
app.listen(1337);
I am new to Node JS and think this is easy to solve, but I still can’t find the solution.
res.json(...); sends back the response. You are doing that in the first iteration over the array, hence the client only gets the first message.
If you want to extract body from all messages and send all of them back, then do that. Create an array with the data you want and send it back. Example:
res.json(data.messages.map(function(message) {
return message.body;
}));
You can only call res.json once per request. You're calling it multiple times in a loop. The first time you call it, the browser receives the response, and you'll get a headers already sent exceptions (or something like that) for all other res.json calls.
res.json actually does a data conversion to JSON. I'd be willing to bet there is something it is not dealing with, or it's simply screwing it up. If the response from Twilio is already json, you probably don't need to do that. Try res.send, instead, which just returns whatever you got back.
I have an issue where I'm trying to make a post request using Restangular:
I'll setup the query like so:
var auth = Restangular.all('auth');
var check = auth.one('check');
Then I'll do the post request like so:
var user = {
email: 'randomemail#gmail.com',
pass: 'randompass'
}
check.post(user)
However, the request shows an error, when I check the network, the request is sent as so :
http://localhost/auth/check/[object object]
Why does the post request attach the object like a query parameter instead of sending it in the request body?
If i'm formatting this post request incorrectly, can someone point out the correct way to format a post request using one and all in Restangular.
Thanks!
When you post to a one(), post() is actually expecting a subElement as the first argument, which is why it's attaching the object passed to the path...
(from documentation)
post(subElement, elementToPost, [queryParams, headers]): Does a POST
and creates a subElement. Subelement is mandatory and is the nested
resource. Element to post is the object to post to the server
To post to /auth/check, you can use customPOST()...
auth.customPOST(user, 'check');
Edit - Here are a couple of examples if you are set on using post()...
Restangular.one('auth').post('check', user);
Or
auth.all('check').post(user);
I'm losing my understanding of parameters in a call back.
app.get('/', function(req, res) {
res.render('index');
});
// A route for the home page - will render a view
This is using the express library and is a basic home page route. I'm just confused on how does this actually get the req/res objects? Does the server itself invoke the function whenever it receives a req/res object on the '/' page ?
I understand what the function does, I just don't know how it actually receives its parameters.
Yes, you get those parameters from the server. Whenever Express (i.e. Node.js) receives a request it runs your callback and provides those two parameters.
Think of it like a talk between two persons:
You: 'Hey Golo, I'm an expert in X. So when anybody asks you about X, please tell me and give me their phone number.'
Me: 'Okay, fine, I'll do that.'
(…)
Me: 'Hey HelloWorld, I now have a request. The contact data are +49 177 …'
Please tell me and give me their phone number. is the callback. The phone number is the parameter to the callback.
So, the phone number in this case is the very same thing as your req and res objects. And I am acting like Node.js / Express in this example, you are the application that is run.
HTH.
Here is an intuitive way to look at it:
app.get() is a function that takes 2 parameters, the first is your path taken as a string and the second param is a function. This function will be called back by app.get();
So let's say that you invoke app.get like so:
app.get('/', function abc(req, res){..})
Then, the implementation of app.get will be something along the lines of :
app.get = function(path, callBackFunction){
// do some stuff here to get the values of req and res
callBackFunction(req, res); // calling back the function passed to us with req and res
}