2008-10-13 21:29:50 8 Comments
I'm using $.post()
to call a servlet using Ajax and then using the resulting HTML fragment to replace a div
element in the user's current page. However, if the session times out, the server sends a redirect directive to send the user to the login page. In this case, jQuery is replacing the div
element with the contents of the login page, forcing the user's eyes to witness a rare scene indeed.
How can I manage a redirect directive from an Ajax call with jQuery 1.2.6?
Related Questions
Sponsored Content
56 Answered Questions
[SOLVED] How do I check if an element is hidden in jQuery?
- 2008-10-07 13:03:18
- Philip Morton
- 2554760 View
- 7501 Score
- 56 Answer
- Tags: javascript jquery dom visibility
65 Answered Questions
[SOLVED] How to check whether a checkbox is checked in jQuery?
- 2009-05-23 15:16:39
- Prasad
- 4029812 View
- 4407 Score
- 65 Answer
- Tags: javascript jquery html checkbox
27 Answered Questions
[SOLVED] How can I refresh a page with jQuery?
- 2011-03-23 11:55:31
- luca
- 2400816 View
- 2374 Score
- 27 Answer
- Tags: javascript jquery refresh reload
36 Answered Questions
[SOLVED] How do I return the response from an asynchronous call?
- 2013-01-08 17:06:14
- Felix Kling
- 1343385 View
- 5232 Score
- 36 Answer
- Tags: javascript jquery ajax asynchronous xmlhttprequest
58 Answered Questions
[SOLVED] How do I redirect to another webpage?
- 2009-02-02 12:54:16
- venkatachalam
- 5980020 View
- 7725 Score
- 58 Answer
- Tags: javascript jquery redirect
22 Answered Questions
[SOLVED] How to make an AJAX call without jQuery?
- 2011-12-19 20:27:46
- discky
- 669274 View
- 751 Score
- 22 Answer
- Tags: javascript ajax
17 Answered Questions
[SOLVED] Abort Ajax requests using jQuery
- 2009-01-15 12:45:18
- lukewm
- 573839 View
- 1782 Score
- 17 Answer
- Tags: javascript jquery ajax
34 Answered Questions
[SOLVED] How can I know which radio button is selected via jQuery?
- 2009-02-27 19:53:27
- juan
- 2082813 View
- 2590 Score
- 34 Answer
- Tags: javascript jquery html jquery-selectors radio-button
14 Answered Questions
[SOLVED] How can I get jQuery to perform a synchronous, rather than asynchronous, Ajax request?
- 2008-09-25 13:26:54
- Artem Tikhomirov
- 694915 View
- 1173 Score
- 14 Answer
- Tags: javascript jquery ajax asynchronous
1 Answered Questions
[SOLVED] Control a request when a jQuery Ajax call done
- 2016-02-25 15:48:52
- nnnnMM
- 123 View
- 4 Score
- 1 Answer
- Tags: javascript jquery ajax xmlhttprequest
30 comments
@Steg 2009-10-07 22:54:26
I read this question and implemented the approach that has been stated regarding setting the response HTTP status code to 278 in order to avoid the browser transparently handling the redirects. Even though this worked, I was a little dissatisfied as it is a bit of a hack.
After more digging around, I ditched this approach and used JSON. In this case, all responses to AJAX requests have the status code 200 and the body of the response contains a JSON object that is constructed on the server. The JavaScript on the client can then use the JSON object to decide what it needs to do.
I had a similar problem to yours. I perform an AJAX request that has 2 possible responses: one that redirects the browser to a new page and one that replaces an existing HTML form on the current page with a new one. The jQuery code to do this looks something like:
The JSON object "data" is constructed on the server to have 2 members:
data.redirect
anddata.form
. I found this approach to be much better.@Carles Barrobés 2010-12-17 13:05:16
As stated in the solution in stackoverflow.com/questions/503093/… it is better to use window.location.replace(data.redirect); than window.location.href = data.redirect;
@Sergei Golos 2011-02-24 19:06:38
Any reason why it it wouldn't be better to use HTTP codes on the action. For example a 307 code which is HTTP Temporary Redirect?
@Miguel Silva 2011-05-03 03:08:33
@Sergei Golos the reason is that if you do a HTTP redirect, the redirect actually never arrives to the ajax success callback. The browser processes the redirect delivering a 200 code with the content of the redirect's destination.
@Vnge 2013-12-08 01:47:35
what would the server code look like? to have a return value of data.form and data.redirect. basically how do i determine if i put a redirect in it?
@Pedro Hoehl Carvalho 2015-10-22 14:01:51
This answer would be more helpful if it had shown how this is done on the server.
@Triynko 2015-11-05 20:27:29
200 codes aren't the only codes that jQuery ajax considers success. It also considers 304 (not modified) a successful request, and will trigger the success callback. I generally use the HTTP status code to indicate success as a boolean, by either return 200 for failure or 201 for success. This works brilliantly for MVC, because during failure you generally want to redisplay the page with the model errors, so you want to return a 200. On success, you may or may not want to return and display data, but in either case its very easy to check whether the status is 201 (for success) or not.
@smwikipedia 2016-01-06 13:35:00
@Steg Why NOT let browser handle the 302 transparently? Isn't it good enough?
@SamDasti 2018-06-12 14:21:22
i want to redirect user to current page I am trying this its not working for me
@DanMan 2018-11-20 14:07:18
This isn't RESTful. You're basically doing SOAP with JSON instead of XML.
@Fuseteam 2019-03-29 12:02:48
@smwikipedia because sometimes the response is a log in screen
@Amol Jadhav 2019-06-03 05:49:14
It is working fine for me. Thank you!
@Chaim Klar 2018-07-12 21:45:43
Let me just quote again the problem as described by @Steg
IMHO this is a real challenge and will have to be officially extended to the current HTTP standards.
I believe the new Http Standard will be to use a new status-code. meaning: currently
301/302
tells the browser to go and fetch the content of this request to a newlocation
.In the extended standard, it will say that if the response
status: 308
(just an example), then the browser should redirect the main page to thelocation
provided.That being said; I'm inclined to already mimic this future behavior, and therefore when a document.redirect is needed, I have the server respond as:
When JS gets the "
status: 204
", it checks for the existence of thex-status: 308
header, and does a document.redirect to the page provided in thelocation
header.Does this make any sense to you?
@John 2013-09-17 16:07:15
While the answers seem to work for people if you're using Spring Security I have found extending LoginUrlAuthenticationEntryPoint and adding specific code to handle AJAX more robust. Most of the examples intercept all redirects not just authentication failures. This was undesirable for the project I work on. You may find the need to also extend ExceptionTranslationFilter and override the "sendStartAuthentication" method to remove the caching step if you don't want the failed AJAX request cached.
Example AjaxAwareAuthenticationEntryPoint:
Sources: 1, 2
@John 2013-12-12 20:50:44
It would be helpful (to me) if down voters would explain why they are down voting. If there is something bad with this solution I would like to learn from my mistakes. Thanks.
@J Slick 2014-03-24 21:01:03
If using Spring and also using JSF, then also check for this: ("partial/ajax").equalsIgnoreCase(request.getHeader("faces-request"));
@J Slick 2014-03-24 21:08:16
Users might have voted down because you didn't mention: (1) the requisite client-side mods to detect your error response; (2) the requisite mods to Spring configuration to add your customized LoginUrlAuthenticationEntryPoint to the filter chain.
@Darren Parker 2018-03-21 20:47:42
Your answer is similar to this one from @Arpad. It worked for me; using Spring Security 3.2.9. stackoverflow.com/a/8426947/4505142
@Tyr 2012-01-06 01:33:08
I resolved this issue like this:
Add a middleware to process response, if it is a redirect for an ajax request, change the response to a normal response with the redirect url.
Then in ajaxComplete, if the response contains redirect, it must be a redirect, so change the browser's location.
@Darren Parker 2018-03-21 21:17:45
I got a working solulion using the answers from @John and @Arpad link and @RobWinch link
I use Spring Security 3.2.9 and jQuery 1.10.2.
Extend Spring's class to cause 4XX response only from AJAX requests:
applicationContext-security.xml
In my JSPs, add a global AJAX error handler as shown here
Also, remove existing error handlers from AJAX calls in JSP pages:
I hope it helps others.
Update1 I found that I needed to add the option (always-use-default-target="true") to the form-login config. This was needed since after an AJAX request gets redirected to the login page (due to expired session), Spring remembers the previous AJAX request and auto redirects to it after login. This causes the returned JSON to be displayed on the browser page. Of course, not what I want.
Update2 Instead of using
always-use-default-target="true"
, use @RobWinch example of blocking AJAX requests from the requstCache. This allows normal links to be redirected to their original target after login, but AJAX go to the home page after login.@SuperG 2009-02-23 23:49:11
I solved this issue by:
Adding a custom header to the response:
Binding a JavaScript function to the
ajaxSuccess
event and checking to see if the header exists:@Bretticus 2010-08-04 17:21:51
What an awesome solution. I like the idea of a one-stop solution. I need to check for a 403 status, but I can use the ajaxSuccess bind on body for this (which is what I was really looking for.) Thanks.
@Bretticus 2010-08-04 18:42:44
I just did this and found that I needed ajaxComplete where I was using the $.get() function and any status other than 200 was not firing. In fact, I could have probably just bound to ajaxError instead. See my answer below for more details.
@Sisir 2011-09-01 09:20:30
The header in what language?
@Joseph 2012-04-19 14:22:12
This worked great for me. Just set the javascript to reload the current page with
location.reload();
as our model requires redirect to a separate authorization site.@jwaliszko 2012-06-18 07:11:08
It's ok in many cases, but what if your framework handles authorization ?
@mwoods79 2012-11-22 03:20:21
This solution requires the browser to know the URL for authentication. Although this solves the problem, it is (in my opinion) not a maintainable solution. If the authentication controller changes, now you are maintaining the routes file and the javascript. i.e. This is bad programming practice.
@rintcius 2012-11-24 16:40:06
I like the header approach but also think - like @mwoods79 - that the knowledge of where to redirect to should not be duplicated. I solved that by adding a header REDIRECT_LOCATION instead of a boolean.
@sieppl 2013-02-18 14:35:51
Take care to set the header on the response AFTER the redirect. As described in other answers on this page, the redirect may be transparent to the ajaxSucces handler. Thus I included the header on the GET response of the login page (which was eventually and only triggering ajaxSuccess in my scenario).
@shashwat 2014-01-02 04:47:35
And you could add this check somewhere in
Global.asax
. InApplication_AuthenticateRequest
event@Pedro Hoehl Carvalho 2015-10-22 14:23:26
Does anyone know how to do this on Spring Security?
@Przemek Marcinkiewicz 2016-10-27 13:31:05
This problem may appear then using ASP.NET MVC RedirectToAction method. To prevent form displaying the response in div you can simply do some kind of ajax response filter for incomming responses with $.ajaxSetup. If the response contains MVC redirection you can evaluate this expression on JS side. Example code for JS below:
If data is: "window.location = '/Acount/Login'" above filter will catch that and evaluate to make the redirection instead of letting the data to be displayed.
@GMsoF 2017-05-12 02:10:45
data
is in the response body or header?@Elliot Vargas 2009-01-27 18:10:32
The solution that was eventually implemented was to use a wrapper for the callback function of the Ajax call and in this wrapper check for the existence of a specific element on the returned HTML chunk. If the element was found then the wrapper executed a redirection. If not, the wrapper forwarded the call to the actual callback function.
For example, our wrapper function was something like:
Then, when making the Ajax call we used something like:
This worked for us because all Ajax calls always returned HTML inside a DIV element that we use to replace a piece of the page. Also, we only needed to redirect to the login page.
@Simen Echholt 2010-11-18 03:02:32
Note that this can be shortened to function cbWrapper(funct) { return function(data) { if($("#myForm", data).size() > 0) top.location.href="login"; else funct(data); } } . You then only need cbWrapper(myActualCB) when calling .post. Yes, code in comments is a mess but it should be noted :)
@sunil 2016-07-20 10:46:18
size is depreciated so you can use .length here in place of size
@SamDasti 2018-06-12 14:18:25
i am trying this its not working for me
@morten.c 2014-05-01 21:42:08
Another solution I found (especially useful if you want to set a global behaviour) is to use the
$.ajaxsetup()
method together with thestatusCode
property. Like others pointed out, don't use a redirect statuscode (3xx
), instead use a4xx
statuscode and handle the redirect client-side.Replace
400
with the statuscode you want to handle. Like already mentioned401 Unauthorized
could be a good idea. I use the400
since it's very unspecific and I can use the401
for more specific cases (like wrong login credentials). So instead of redirecting directly your backend should return a4xx
error-code when the session timed out and you you handle the redirect client-side. Works perfect for me even with frameworks like backbone.js@Vikrant 2017-01-27 07:43:45
Where to mention the function on page?
@morten.c 2017-01-27 16:52:50
@Vikrant If I understand your question correctly, you can call the function right after jQuery is loaded and before you're doing your actual requests.
@Tomer 2016-04-08 23:26:17
Some might find the below useful:
I wanted clients to be redirected to the login page for any rest-action that is sent without an authorization token. Since all of my rest-actions are Ajax based, I needed a good generic way to redirect to the login page instead of handling the Ajax success function.
This is what I've done:
On any Ajax request my server will return a Json 200 response "NEED TO AUTHENTICATE" (if the client needs to authenticate).
Simple example in Java (server side):
In my Javascript I've added the following code:
And that's about it.
@Thomas Hansen 2008-11-20 08:39:42
No browsers handle 301 and 302 responses correctly. And in fact the standard even says they should handle them "transparently" which is a MASSIVE headache for Ajax Library vendors. In Ra-Ajax we were forced into using HTTP response status code 278 (just some "unused" success code) to handle transparently redirects from the server...
This really annoys me, and if someone here have some "pull" in W3C I would appreciate that you could let W3C know that we really need to handle 301 and 302 codes ourselves...! ;)
@Chris Marisic 2012-06-07 21:51:08
I for one move that 278 should become apart of the official HTTP Spec.
@Philippe Rathé 2013-09-12 21:27:46
Doesn't it already handle them transparently? If a resource has moved, handling it transparently means repeating the request on the provided URL. That is what I would expect using the XMLHttpRequest API.
@smwikipedia 2016-01-06 13:19:03
@PhilippeRathé Agree. Transparently handling is just what I want. And I don't know why it is considered bad.
@cmc 2017-06-06 12:39:13
@smwikipedia To arrange for a redirect of the markup in main section without redirecting the page.
@Ali Adlavaran 2015-07-30 06:02:24
Finally, I solve the problem by adding a custom
HTTP Header
. Just before response for every request in server side, i add the current requested url to response's header.My application type on server is
Asp.Net MVC
, and it has a good place to do it. inGlobal.asax
i implemented theApplication_EndRequest
event so:It works perfect for me! Now in every response of the
JQuery
$.post
i have the requestedurl
and also other response headers which comes as result ofPOST
method by status302
,303
,... .and other important thing is that there is no need to modify code on server side nor client side.
and the next is the ability to get access to the other information of post action such errors, messages, and ..., In this way.
I posted this, maybe help someone :)
@Rob 2014-02-14 13:56:55
Most of the given solutions use a workaround, using an extra header or an inappropiate HTTP code. Those solutions will most probably work but feel a bit 'hacky'. I've come up with another solution.
We're using WIF which is configured to redirect (passiveRedirectEnabled="true") on a 401 response. The redirect is usefull when handling normal requests but won't work for AJAX requests (since browsers won't execute the 302/redirect).
Using the following code in your global.asax you can disable the redirect for AJAX requests:
This allows you to return 401 responses for AJAX requests, which your javascript can then handle by reloading the page. Reloading the page will throw a 401 which will be handled by WIF (and WIF will redirect the user to the login page).
An example javascript to handle 401 errors:
@DanMan 2018-11-20 14:04:55
Good solution. Thanks.
@camara90100 2014-03-15 15:49:40
this worked for me:
on success, ajax will get the same status code the browser gets from the server and execute it.
@Naeem Sarfraz 2018-10-26 10:27:19
huh? this just logs to the console the status of the request? Which for success will be 2xx.
@rynop 2012-10-23 16:27:56
I think a better way to handle this is to leverage the existing HTTP protocol response codes, specifically
401 Unauthorized
.Here is how I solved it:
Client side: Bind to the ajax events
IMO this is more generic and you are not writing some new custom spec/header. You also should not have to modify any of your existing ajax calls.
Edit: Per @Rob's comment below, 401 (the HTTP status code for authentication errors) should be the indicator. See 403 Forbidden vs 401 Unauthorized HTTP responses for more detail. With that being said some web frameworks use 403 for both authentication AND authorization errors - so adapt accordingly. Thanks Rob.
@Marius Balčytis 2013-07-14 21:14:37
I use the same approach. Does jQuery really calls ajaxSuccess on 403 error code? I think only ajaxError part is actually needed
@jwaliszko 2013-05-06 23:55:06
I know this topic is old, but I'll give yet another approach I've found and previously described here. Basically I'm using ASP.MVC with WIF (but this is not really important for the context of this topic - answer is adequate no matter which frameworks are used. The clue stays unchanged - dealing with issues related to authentication failures while performing ajax requests).
The approach shown below can be applied to all ajax requests out of the box (if they do not redefine beforeSend event obviously).
Before any ajax request is performed
CheckPulse
method is invoked (the controller method which can be anything simplest):If user is not authenticated (token has expired) such method cannot be accessed (protected by
Authorize
attribute). Because the framework handles authentication, while token expires, it puts http status 302 to the response. If you don't want your browser to handle 302 response transparently, catch it in Global.asax and change response status - for example to 200 OK. Additionally, add header, which instructs you to process such response in special way (later at the client side):Finally at the client side check for such custom header. If present - full redirection to logon page should be done (in my case
window.location
is replaced by url from request which is handled automatically by my framework).@Frinavale 2013-10-28 16:38:18
I fixed the problem by using the PostAuthenticateRequest event instead of the EndRequest event.
@Frinavale 2013-10-28 21:15:38
@JaroslawWaliszko I pasted the wrong event into my last reply! I meant the PreSendRequestHeaders event.....not PostAuthenticateRequest! >>blush<< thank you for pointing out my mistake.
@Rob 2014-02-14 14:01:19
@JaroslawWaliszko when using WIF you can also return 401 responses for AJAX requests and let your javascript handle these. Also you're assuming that all 302 require authentication which might not be true in all cases. I've added an answer if anyone is interested.
@jocull 2013-02-06 13:45:02
I didn't have any success with the header solution - they were never picked up in my ajaxSuccess / ajaxComplete method. I used Steg's answer with the custom response, but I modified the JS side some. I setup a method that I call in each function so I can use standard
$.get
and$.post
methods.Example of it in use...
@karthik339 2013-01-07 06:35:28
If you also want to pass the values then you can also set the session variables and access Eg: In your jsp you can write
And then you can store this temp value in your javascript variable and play around
@Juri 2012-05-23 10:02:27
I just wanted to share my approach as this might it might help someone:
I basically included a JavaScript module which handles the authentication stuff like displaying the username and also this case handling the redirect to the login page.
My scenario: We basically have an ISA server in between which listens to all requests and responds with a 302 and a location header to our login page.
In my JavaScript module my initial approach was something like
The problem (as many here already mentioned) is that the browser handles the redirect by itself wherefore my
ajaxComplete
callback got never called, but instead I got the response of the already redirected Login page which obviously was astatus 200
. The problem: how do you detect whether the successful 200 response is your actual login page or just some other arbitrary page??The solution
Since I was not able to capture 302 redirect responses, I added a
LoginPage
header on my login page which contained the url of the login page itself. In the module I now listen for the header and do a redirect:...and that works like charm :). You might wonder why I include the url in the
LoginPage
header...well basically because I found no way of determining the url ofGET
resulting from the automatic location redirect from thexhr
object...@uınbɐɥs 2012-10-14 04:01:25
+1 - but custom headers are supposed to start with
X-
, so a better header to use would beX-LoginPage: http://example.com/login
.@Juri 2012-10-14 07:31:26
@ShaquinTrifonoff Not any more. I didn't use the X- prefix because in June 2011 an ITEF document proposed their deprecation and indeed, with June 2012 it is no official that custom headers should no more be prefixed with
X-
.@scott stone 2013-08-01 21:44:17
We also have an ISA server and I just ran into the same issue. Rather than work around it in code, we used the instructions in kb2596444 to configure ISA to stop redirecting.
@Curtis Yallop 2012-04-10 19:38:59
You can also hook XMLHttpRequest send prototype. This will work for all sends (jQuery/dojo/etc) with one handler.
I wrote this code to handle a 500 page expired error, but it should work just as well to trap a 200 redirect. Ready the wikipedia entry on XMLHttpRequest onreadystatechange about the meaning of readyState.
@Paul Richards 2011-12-05 19:59:00
I solved this by putting the following in my login.php page.
@BrianY 2011-08-23 19:21:35
I like Timmerz's method with a slight twist of lemon. If you ever get returned contentType of text/html when you're expecting JSON, you are most likely being redirected. In my case, I just simply reload the page, and it gets redirected to the login page. Oh, and check that the jqXHR status is 200, which seems silly, because you are in the error function, right? Otherwise, legitimate error cases will force an iterative reload (oops)
@Johnny 2012-04-20 20:32:38
thanks a lot Brian, your answer was the best for my scenario, although I would like if there was a safer check such as comparing which url/page is redirecting to instead of the simple "content-type" check. I was unable to find which page is redirecting to from the jqXHR object.
@Eric 2015-07-23 20:41:20
I checked for status 401 and then redirect. Works like a champ.
@Priyanka 2011-09-10 16:44:42
@Benny Jobigan 2011-08-28 10:18:14
I was having this problem on a django app I'm tinkering with (disclaimer: I'm tinkering to learn, and am in no way an expert). What I wanted to do was use jQuery ajax to send a DELETE request to a resource, delete it on the server side, then send a redirect back to (basically) the homepage. When I sent
HttpResponseRedirect('/the-redirect/')
from the python script, jQuery's ajax method was receiving 200 instead of 302. So, what I did was to send a response of 300 with:Then I sent/handled the request on the client with jQuery.ajax like so:
Maybe using 300 isn't "right", but at least it worked just like I wanted it to.
PS :this was a huge pain to edit on the mobile version of SO. Stupid ISP put my service cancellation request through right when I was done with my answer!
@podeig 2010-10-05 06:53:07
Try
Put it on the login page. If it was loaded in a div on the main page, it will redirect til the login page. "#site" is a id of a div which is located on all pages except login page.
@Timmerz 2010-08-17 18:07:11
I have a simple solution that works for me, no server code change needed...just add a tsp of nutmeg...
I check the presence of html tag, but you can change the indexOf to search for whatever unique string exists in your login page...
@adriaanp 2011-08-24 06:49:18
This does not seem to work for me, it keeps on calling the function defined with ajax call, it's like it is not overriding the success method.
@Bretticus 2010-08-04 18:47:29
I just wanted to latch on to any ajax requests for the entire page. @SuperG got me started. Here is what I ended up with:
I wanted to specifically check for certain http status codes to base my decision on. However, you can just bind to ajaxError to get anything other than success (200 only perhaps?) I could have just written:
@Tim Abell 2011-08-08 10:41:46
the latter would hide any other errors making troubleshooting problematic
@Rob 2014-02-14 13:37:56
A 403 does not mean that the user isn't authenticated, it means that the (probably authenticated) user does not have permission to view the requested resource. So it should not redirect to the login page
@Graham King 2009-08-06 20:17:07
Putting together what Vladimir Prudnikov and Thomas Hansen said:
This makes the browser treat the response as a success, and hand it to your Javascript.
@Juan Toro 2008-11-14 20:56:26
in the servlet you should put
response.setStatus(response.SC_MOVED_PERMANENTLY);
to send the '301' xmlHttp status you need for a redirection...and in the $.ajax function you should not use the
.toString()
function..., justif (xmlHttp.status == 301) { top.location.href = 'xxxx.jsp'; }
the problem is it is not very flexible, you can't decide where you want to redirect..
redirecting through the servlets should be the best way. but i still can not find the right way to do it.
@Vladimir Prudnikov 2008-10-19 10:14:46
Additionally you will probably want to redirect user to the given in headers URL. So finally it will looks like this:
UPD: Opps. Have the same task, but it not works. Doing this stuff. I'll show you solution when I'll find it.
@TheCrazyProgrammer 2017-02-24 01:14:56
This answer should be deleted by the author as he himself says that this doesn' work. He can post a working solution later. -1
@Martin Zvarík 2019-12-11 02:44:07
The idea is good, but the problem is that "Location" header is never passed.
@Martin Zvarík 2019-12-11 02:46:46
My edit was rejected, so... you have to use "var xmlHttp = $.ajax({ ...." the variable can't be inside... then use: console.log(xmlHttp.getAllResponseHeaders());