Ajax Post request get converted to GET [duplicate] - javascript

I am having a very hard time understanding the exact process of "post/redirect/get".
I have combed through this site and the web for several hours and cannot find anything other than "here's the concept".
How to understand the post/redirect/get pattern?

Wikipedia explains this so well!
The Problem
The Solution

As you may know from your research, POST-redirect-GET looks like this:
The client gets a page with a form.
The form POSTs to the server.
The server performs the action, and then redirects to another page.
The client follows the redirect.
For example, say we have this structure of the website:
/posts (shows a list of posts and a link to "add post")
/<id> (view a particular post)
/create (if requested with the GET method, returns a form posting to itself; if it's a POST request, creates the post and redirects to the /<id> endpoint)
/posts itself isn't really relevant to this particular pattern, so I'll leave it out.
/posts/<id> might be implemented like this:
Find the post with that ID in the database.
Render a template with the content of that post.
/posts/create might be implemented like this:
If the request is a GET request:
Show an empty form with the target set to itself and the method set to POST.
If the request is a POST request:
Validate the fields.
If there are invalid fields, show the form again with errors indicated.
Otherwise, if all fields are valid:
Add the post to the database.
Redirect to /posts/<id> (where <id> is returned from the call to the database)

I'll try explaining it. Maybe the different perspective does the trick for you.
With PRG the browser ends up making two requests. The first request is a POST request and is typically used to modify data. The server responds with a Location header in the response and no HTML in the body. This causes the browser to be redirected to a new URL. The browser then makes a GET request to the new URL which responds with HTML content which the browser renders.
I'll try to explain why PRG should be used. The GET method is never supposed to modify data. When a user clicks a link the browser or proxy server may return a cached response and not send the request to the server; this means the data wasn't modified when you wanted it to be modified. Also, a POST request shouldn't be used to return data because if the user wants to just get a fresh copy of the data they're forced to re-execute the request which will make the server modify the data again. This is why the browser will give you that vague dialog asking you if you are sure you want to re-send the request and possibly modify data a second time or send an e-mail a second time.
PRG is a combination of POST and GET that uses each for what they are intended to be used for.

Just so people can see a code example (this is using express):
app.post('/data', function(req, res) {
data = req.body; //do stuff with data
res.redirect('public/db.html');
});
So to clarify, it instantly refreshes the webpage and so on refresh of that webpage (e.g. if you updated an element on it) it won't repost the form data.
My code used to look like this:
app.post('/data', function(req, res) {
data = req.body;
res.sendFile('public/db.html');
});
So here the response is sending the html file at the /data address. So in the address bar, after pressing the submit button it would say for me: localhost:8080/data.
But this means that on refresh of that page, if you have just submitted the form, it will submit it again. And you don't want the same form submitted twice in your database. So redirecting it to the webpage (res.redirect) instead of sending the file (res.sendFile) , stops the resubmission of that form.

It is all a matter of concept, there is no much more to understand :
POST is for the client to send data to the server
GET is for the client to request data from the server
So, conceptually, there is no sense for the server to answer with a resource data on a POST request, that's why there is a redirection to the (usually) same resource that has been created/updated. So, if POST is successful, the server opiniates that the client would want to fetch the fresh data, thus informing it to make a GET on it.

Related

How to get response headers using express.js

I'm trying to get a response header using express js but no way i try is working.
Here is where i set the header:
return res.status(400).header('loginError', error.details[0].message).redirect('/login');
This works and i can see the header in the network tab on inspect element but when i try to access it it doesn't return a value.
I've tried:
res.getHeader("loginError"), res.get("loginError"), res.header("loginError")
Here is my ejs code:
<div class="login-form-error">
<div class="login-form-error__inner">
<span id="login-form-error__span"><%=loginError%></span>
</div>
</div>
<% } %>
I set the loginError var when i render the page:
res.render('login/index.ejs', {
loginError: res.header
});
Any help is appreciated, sorry if this is a dumb question
From your proposed solution, it sounds like you're trying to do a redirect, but send some data with the redirect that will come back to the server when the client requests the redirected URL (on the next request).
You cannot use a custom header with a redirect. The header will go to the browser, but the browser will NOT include the header on the request that follows to the redirect URL. So your server won't get the header back again.
You can send data from one request to the next request from the same client in the following ways:
Set a query parameter on the redirect so that when the browser sends the redirected URL to the server, the data you attached as a query parameter will be part of the URL where your server can look for it and use it. This would be useful for data that is not particularly secret.
Use a server-side session such as express-session. Then, you can set a client-specific piece of data in the session object (which is a unique object for each user), send your redirect response and then when the redirected URL comes back on the next request, your server can check the session for the data (read that data and perhaps clear it).
Set a cookie along with sending the redirect response and then when the redirected request comes back to your server, you can check for the cookie and grab whatever you want in the cookie (and delete the cookie).
Using data in a server-side session is the most secure (as the data never leaves the server) if that's relevant for your particular use case.
You cannot use req.app.get() and req.app.set() because those are global to your server and thus multiple users will compete for the same values causing concurrency problems (where one user's value trounces that from another user or one user gets the data that belonged to another user). This is a buggy experience that will only hit you every once in a while and is hard to reproduce and figure out why things went wrong. Don't do it this way. It's analogous to trying to store data from two users in the same server-side variable. Only leads to problems.
For anyone wondering: Instead of using headers I found that if you use req.app.get(var) and req.app.set(var, value) you can easily send data from one request to another. I don't know if it is a secure way to send store data or not if anyone else has more info on that feel free to respond.

What is the post function behind form submitting?

I am curious to know the function implementation of form submitting using post method or how it works?
POST - Submits data to be processed to a specified resource
When you press button (usually it is type="submit") you send some data do server side. With Post method you can in code behind (server side) to do you job with data. Usually you will work with specified named data (like inputs for example).
I suggest you to look here.
It's the method the browser uses to talk to the server when asking for
a response that takes into account the data provided in the body of
the HTTP request: "Hey server, take a look at this data and send me
back an appropriate result." If a form is sent using this method, the
data is appended to the body of the HTTP request.

Can I use post to click a button on a page in JQuery?

I'm trying to request a page and click a button on it without opening a window so I'm thinking post could work. Here is my code:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"</script>
<script>
$(document).ready(function() {
$.post(
"http://m.roblox.com/Catalog/VerifyPurchase?assetid=161075864&type=tickets&expectedPrice=1",
$("ui-block-a").submit();
);
alert("work");
});
</script>
</head>
<body>
</body>
</html>
If I'm understanding post correctly, the first argument is the url to which it requests from and the second argument is the one where you can send data. I'm trying to send a request to click the "buy" button on the page if you follow the link. Can anyone help?
A post request sends data to a given URL. What the server does with that data from that point is entirely up to the server. It is very unlikely that the web page you are trying to simulate a button press on allows that behavior. If that was possible in general, it would leave users open to some very large security vulnerabilities. For example, a site could simulate donating money via PayPal without the user ever knowing.
In this particular case, the button appears to submit a form. In that case, you could always attempt to send the request directly to the page that the form submits to, which would simulate submitting the form. However form submissions are generally protected against stuff like this, because again, it could be used to act on behalf of the user.
Basically, the best option for something like this is to provide the user with instructions detailing what they need to do, and then open the page for them.
Assuming there is no other issues like CORS you can do the post like you are trying to do, but the following is invalid.
$.post( "http://m.roblox.com/Catalog/VerifyPurchase?assetid=161075864&type=tickets&expectedPrice=1", $("ui-block-a").submit();
You are doing a POST which required the data being send to the server to be in the request body and not the URL string.
When you post to a page you are actually posting directly to the server and not a page and in this case unless the $("ui-block-a").submit(); is returning data for the page you are posting to, it is not needed.
The following would be closer to what you are looking for with that post
$.post( "http://m.roblox.com/Catalog/VerifyPurchase", { assetid: "161075864", type: "2pticketsm", expectedPrice: "1" } );
If it was successful you should see a allow-orgins error in your developer / inspector console.
$.post() is an abbreviated form of $.ajax(), with POST pre-selected as type. There are also $.get() (with GET pre-selected as type), and $.load() (with the returned data immediately injected into the specified element). But $.ajax() is the grand-daddy of them all.
AJAX is a method of exchanging data with a processor file on a server, without leaving / refreshing the page you are on. That is, with AJAX (or $.post), you can send information to a processing page on the server -- such as: my_processor.php -- the processing page can do something with the data (for example, use the data to query a database), and then echo out data, which is returned to the originating page. The received data can then be injected into a DIV on the original page, or something of the sort.
An ajax routine is usually triggered by some event on the originating page (the user presses a button, or selects a value in a drop-down, or some such). Javascript (or jQuery) code detects the event, and the AJAX code is usually actioned in the javascript event.
Here are some simple examples of what has been described.

Handling authentication through AJAX?

This is a newbie question to AJAX experts: In case an unauthenticated user tries to post a comment to an article and send it to the server through AJAX, I need the remote PHP script to return...
a 401 and a logon/password form which the user will fill and try again, or
a 301 to redirect the user to a full-page logon/password form which, if successfull, will then return the user to the original comment page.
If possible, I'd rather use AJAX for both authentication + posting, so that the user doesn't need to see a full page just for authentication. Is it possible? FWIW, I'm using jQuery to learn about AJAX.
Thank you.
Yes. Your AJAX script might be making a request to, say, comment.php. That script should check if the session has been authorised, usually a variable in $_SESSION['...']. If so, then the comment should be handled. If not, the user should be directed by that script to log in.

detecting JSON loaded by browser

I have an application in which most requests are submitted via AJAX, though some are submitted via "regular" HTTP requests. If a request is submitted and the user's session has timed out, the following JSON is returned:
{"authentication":"required"}
The JavaScript function which submits all AJAX requests handles this response by showing a popup message and redirecting the user back to the login page.
However, when a non-AJAX request receives this response the JSON is simply shown in the browser because the response is processed directly by the browser (i.e. the aforementioned JavaScript function is bypassed). Obviously this is not ideal and I would like the non-AJAX requests that receive this response to behave the same as the AJAX requests. In order to achieve this, I can think of 2 options:
Go through the application and convert all the requests to AJAX requests. This would work, but could also take a long time!
The JSON shown above is generated by a very simple JSP. I'm wondering if it might be possible to add a JavaScript event handler to this JSP which is run just before the content is displayed in the browser - I'm assuming this would never be called for AJAX requests? This handler could call the other JavaScript code that displays the popup and performs the redirection.
If anyone knows how exactly I can implement the handler I've outlined in (2), or has any other potential solutions, I'd be very grateful if they'd pass them on.
Cheers,
Don
3) Change your AJAX code to add a variable to the GET or POST: outputJson=1
You cannot add a handler to the JSP that way. Anything you add to it will make it a non-JSON producing page.
There are two options that I can see:
Add a parameter to the page by appending a URL parameter to the screen that modifies the output.
URL: http://domain/page.jsp?ajaxRequest=true
would output json only
URL: http://domain/page.jsp
would display a jsp page that could forward to another page.
OR
change the response to have the forwarding code in the JSP that will get executed by the web browser if it is hit directly. Then have your calling AJAX to strip the forwarding code out, and then process what is left.
4) Read up on the 'Accept' request HTTP header.
Then, on the server side tailor the output:
e.g.
if(Accept contains application/json...) { // client asking for json, likely to be XHR
return {"foo":"bar"}
} else { // other
return "Location: /login-please";
}
Start with a smarter error message, like this:
{"error":"authentication required"}
Wrap the JSON output in a callback:
errorHandler({"error":"authentication required"});
Have a handler waiting in your script:
function errorHandler(r) {
alert(r.error);
}
And don't forget to send it down as text/javascript and not application/x-json.

Categories