Why can NodeJS request set post form later using Chain API? - javascript

I am try to figure out why we can set the form for the post request using .form after I have called request.post.
This is the code snippet from official document
request.post('http://service.com/upload', {form:{key:'value'}})
// or
request.post('http://service.com/upload').form({key:'value'})
// or
request.post({url:'http://service.com/upload', form: {key:'value'}},
function(err,httpResponse,body){ /* ... */ })
I am confused about the second example request.post('http://service.com/upload').form({key:'value'}).
In my opinion, it should not work because once request.post(...) has been called, the request will be sent. And then the call to .form is like you are setting the post form after the request has been sent. So how can this work ? Is there anything wrong ?

And then the call to .form is like you are setting the post form after the request has been sent. So how can this work ?
Apparently, when you do this:
request.post('http://service.com/upload')
The request is not immediately sent. Instead, it is registered (with a setImmediate() or process.nextTick()) to be sent on the next tick of the event loop.
So, when you execute request(...).form({key:'value'}), the .form() gets a chance to modify the request before it is sent.
In the doc for .post(), there is this statement that explains:
For advanced cases, you can access the form-data object itself via r.form(). This can be modified until the request is fired on the next cycle of the event-loop. (Note that this calling form() will clear the currently set form data for that request.)
In that above statement, r is the return value from calling request.post() so r.form() refers to request.post(...).form(...) which is your specific situation.
And, in the source code is this comment:
// start() is called once we are ready to send the outgoing HTTP request.
// this is usually called on the first write(), end() or on nextTick()

Related

Using a POST request inside a GET request's call back (Closures)

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.

How do I intercept an API call and display data from it using a UserScript?

There's a webapp that makes a request (let's call it /api/item). This request returns a json body with a field called itemData which is normally hidden from the user, but I want to make that shown.
So how do I make a userscript that listens for the request at /api/item and displays the itemData field?
For reference the way the webapp is making the request is:
return Promise.resolve(new Request(e,r)).then(sendCookies).then(addLangParam).then(addCacheParam).then(addXsrfKey).then(checkZeroRating).then(function(e) {
return fetch(e)
}).then(checkStatus).then(checkApiVersionMismatch).then(checkApiResponse)
Most of that is irrelevant, but the important part is Request (I think).
This webapp is not using XMLHttpRequest, but the Fetch API.
You can use the fetch-intercept npm module to intercept fetch requests. Example code:
import fetchIntercept from 'fetch-intercept'
fetchIntercept.register({
response(response) {
console.log(response)
return response
}
})
Do you have access to the promise returned ?
If so, then you may add another "then".
Otherwise, you may overwrite "checkApiResponse"

Is it possible to call a Javascript function before every request to the server?

I am having some content in local storage . I want to send this in http header every time a request to the server is being made by invoking something like (xhr.setRequestHeader('custom-header', 'value');). Instead of calling the function which does this task before every request , I want it to be called automatically .
This can be done easily by overwriting the send method:
// save the real `send`
var realSend = XMLHttpRequest.prototype.send;
// replace `send` with a wrapper
XMLHttpRequest.prototype.send = function() {
this.setRequestHeader("X-Foobar", "my header content");
// run the real `send`
realSend.apply(this, arguments);
}
This turns XMLHttpRequest.prototype.send into a function that does some arbitrary operation (here, setting the X-Foobar request header on the XMLHttpRequest instance) and then executes the actual Ajax request with the real send method.
Local storage was actually designed not to be sent to the server automatically. This was done to improve on cookies, which result in a large overhead (if they hold much data) due to their being sent with every page request. That slows things down and makes is very bad for mobile phones particularly. So you will have to continue with the method you are already using, or take one of the alternative suggestions offered in other replies.

JSF 1.2 AJAX Redirect to URL

I've got a requirement where we need to redirect to a page for JSF 1.2 Ajax call. In our case, we need to redirect to session expired page when the ajax call get fired after the session got expired. We are implementing the session expiry check in a filter and the invocation of httpservletresponse.sendRedirect is redirecting correctly to the session expired page as expected, but the url is not getting changed which is the issue now.
Any hints/soultion either at the client/server side is highly appreciated.
~Ragesh
Finally I managed to find a solution for the above problem.
In the filter, I set the response header "Location" and another custom header which I'll use in the client side to filter the response.
Filter code:
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
httpServletResponse.setHeader("x-timeout-status", "true");
httpServletResponse.setHeader("Location", httpServletResponse
.encodeRedirectURL(sessionexpiryurl));
Richfaces have got a javascript file with various callbacks required during the AJAX call invocation which is packed inside the Richfaces libraries. There is one callback function called "processResponse" which will get invoked upon receiving response for all AJAX call initiated by JSF Ajax components . I've made use of this to handle the redirection functionality.
JS code:
var originalAjaxProcessResponse = A4J.AJAX.processResponse;
A4J.AJAX.processResponse = function(req) {
if (req.getResponseHeader('x-timeout-Status') != undefined && req.getResponseHeader('x-timeout-status') == 'true') {
window.location.href = req.getResponseHeader('Location');
} else {
originalAjaxProcessResponse(req);
}
}
Here we are overriding the method to handle our specific case and delegate the rest of the ajax call response handling to the in-built processing provided by richfaces.
Please let me know if you see any limitation to this solution or have a better solution to this problem
~Ragesh

Using one and all chaining in Restangular post requests

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);

Categories