How to get response headers using express.js - javascript

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.

Related

Ajax Post request get converted to GET [duplicate]

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.

HTTP GET request working on normal session but not in 'incognito' session

Having some trouble understanding why this issue is happening, specifically within the Steam environment.
When I go to this URL and am logged in to Steam, the request goes through fine and I get the return that I'm expecting. However, when I try the request in an incognito session, I get an empty set of results. I've looked through the code that Steam itself uses to send this request (ctrl-f '// Load' and it should bring you to the relevant code). There doesn't seem to be any identifying information being passed in this request, and even in incognito mode Steam will still load up the price history charts for the item just fine. I can't understand why the request will not work in a session in which the user isn't logged in to Steam even though the page itself will still display price history using the same request.
Since this occurs on Valve's servers, this is simply an educated guess as to what is occurring.
When you visit this URL without being logged in, the server is sending back a 400 Bad Request
It appears this is due to the lack of a steamLogin cookie. When you visit the URL without being logged in, these cookies are set
timezoneOffset
Steam_Language
community_game_list_scroll_size
recentlyVisitedAppHubs
sessionid
steamCC_<IP_OF_COMPUTER>
After logging in, when the request is successful, the steamLogin cookie also exists.
It appears you need this cookie to get the information you want.
Can't comment (rep too low) but FYI, the item detail page works because the data for the graph is passed inside the html file in a bracket. You could set up a DOM environment, load the html and scrape it out without needing to login.
As the other poster mentioned, the api call you want to use requires the steamLogin cookie to work.

How to authenticate an AJAX request to a PHP file?

On my website I have a registration page which makes an AJAX request to check if a username is available after it has been entered. This file is called check.php and is in the same directory as the registration.php file. When data is posted to check.php it will perform a query at a MySQL database and return how many users it found with that username.
If anybody were to post data to the check.php file they would see the result, too. I need to stop this somehow, I've read on a few answers I need to "authenticate" each request. This is probably a very large topic although I'm not too sure what to search for to find more about it. Is authenticating each request a good way to stop unnecessary username checks? If so I would really appreciate it if anyone could point me in the right direction as to how to do this.
A solution is to generate a unique token in session, and put it in all pages that will contain a form. Post this token on each AJAX request you make.
It is called CSRF protection, Cross-Site Request Forgery.
You can add a protection layer checking the user referer in HTTP headers.
Answer for common case: no - you can't prevent this, since AJAX is just an HTTP-request. It can be sent no matter how you'll protect your server. So if the point is - to protect from 'evil hackers' - there's no way to do this. The correct though is to check/validate anything on server side.
But is it's about only basic check, you can read
if (strtolower($_SERVER['HTTP_X_REQUESTED_WITH'])=='xmlhttprequest')
-but be aware - this is also a data, which came from client i.e. it can't be trusted (actually, it's just HTTP-request header, nothing more)
I think you can create a Session variable when the user logs in your aplication and check if this variable has the correct value whe you post something to your 'check.php' file to check if your user is previous authenticate
Missing a lot of info but conceptually I am not sure you are worrying about a real risk. Bottom line is that people can use your form to check if emails exist so it's logical they can use check.php as well. Would be overkill to try and prevent that.
I have one think - you can generate some unique token, store it on SESSION before show the page. Than on each checking you must to add this token to request. check.php must regenerate token and return it new.
But each request can emulate and it not protect you from people, which want to know results of check.php. Nothing protect...
Also you can make mechanism for analyzing ip request for checking

Getting current URL from inside an iframe

I need to check the referrer from inside an iframe. If accessing the page via the bookmark, I cannot do this. Instead I grab the URL, with client side javascript as I cannot get the masked URL with server side requests.
Now I have the URL in clietn side javascript - how do I feed it into my server side code execution on the first page load?
Is there a much simpler way of getting the current URL in the address bar, from inside an iframe?
Thank you,
Chris
You can use Ajax to exchange data between client and server without refreshing the page.
To do the Ajax request only on the first page load, you could combine sessions with cookies:
Check server side if the sessions
variable not_first_page_load is
already set. If it's not set it
means it is the first page load:
create a cookie first_page_load
and after that set the sessions
variable, so that forthcoming
requests won't trigger this any more.
On the client side you should
check for the cookie
first_page_load. If you find it, then
you should make the Ajax
request.
Back on the server side, where
you handle the Ajax request, you
should remove the cookie
first_page_load.

What is a non intrusive history back button or alternative if Javascript is disabled?

If JavaScript is disabled what's a way of linking to the previous document in the session history?
Can PHP be used to simply link to the REFERRER or is there a better alternative?
Edit: Further to this, can previous post variables be retained?
You're really mixing the idea of previous document in client session history vs. server session history.
Since Javascript is client-side, executing a history.back() renders the control to the browser, which then decides which page was last in the history (keeping in mind that the last page may not be a page within your domain). When you're using server-side PHP, the HTTP header referrer is whatever the browser supplied to you. If your server-side URI wasn't called as a result of an explicit click on a link, form GET/POST, etc. , your script probably won't get a referrer header value.
If you only want to capture the referrer within your site's domain, you can start maintaining a breadcrumb trail server-side (in the user's session). eg: $_SESSION['breadcrumbs'] = array( 'page1', 'page2', ... )
POST variables can be persisted in the SESSION too though I've never seen a good reason to do so. If you're trying to return an error message for a form and expect to get back the POST, you shouldn't be saving the state of the original POST.

Categories