question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Need some advice about handling 302 redirects from Ajax

See original GitHub issue

Summary

We have a single page app based on Vue.js which uses Axios to make API calls. When a user’s session expires, API calls start returning a 302 redirect to the login page. Since its a single page app, sometimes users may just browse around directly in the app, therefore only making AJAX calls and not reloading the main index.html file.

When this happens, the 302’s are basically swallowed and the user is not redirected and the app breaks.

To complicate matters a bit further, the login page is based on a federated login service in Azure, so it’s on a different domain. This causes the browser to throw the following CORS error:

XMLHttpRequest cannot load login.microsoftonline.com. 
No 'Access-Control-Allow-Origin' header is present on the requested resource.  
Origin 'null' is therefore not allowed access.

I tried to use an interceptor but the error.response object is undefined, so I cannot even tell what the HTTP status of the response was. So the best I can come up with is that when error.response is undefined to assume it was a 302 and assume I need to forward the user to the login page:

axios.interceptors.response.use((response) => {
  return response
}, (error) => {
  // we can't seem to catch the 302 status code as an error,
  // however, since it redirects to another domain (login.microsoftonline.com) it causes
  // a CORS error which makes error.response be undefined here.  This assumes that any time
  // error.response is undefined that we need to redirect to the login page
  if (typeof error.response === 'undefined') {
    window.location = 'https://login.microsoftonline.com'
  } else {
    return Promise.reject(error)
  }
})

Is this the best we can do? Any further suggestions?

Context

  • Vue.js, vue-router single page app
  • axios version: v0.16.0
  • Environment: chrome 58, windows 10

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:25
  • Comments:13 (2 by maintainers)

github_iconTop GitHub Comments

47reactions
jcreadycommented, Jun 9, 2017

Browsers always follow redirects for XHRs or fetch() requests. There is no library that could prevent the redirect. What you need to do on your server-side is distinguish between XHR requests and normal browser navigation requests and send either a 403 w/ JSON and specify the URL you want to redirect to in there or send a 302 if the request is being made by a browser navigation request. You can do this a couple different ways, but I’ll list some here assuming you’re using Express:

Check the req.xhr to respond based on its boolean value

// The user needs to login again
if (req.xhr) {
  res.status(403).json({
    error: 'You must login to see this',
    location: 'https://login.microsoftonline.com'
  })
} else {
  res.redirect('https://login.microsoftonline.com')
}

Use res.format() to respond based on what the client accepts

By default axios sends an Accept header of application/json, text/plain, */* where as browser generally send the Accept header with text/html being listed first.

// The user needs to login again
res.format({
  json: () => res.status(403).json({
    error: 'You must login to see this',
    location: 'https://login.microsoftonline.com'
  }),
  html: () => res.redirect('https://login.microsoftonline.com')
  default: () => res.redirect('https://login.microsoftonline.com')
})

Then on your client-side you would use something like this when using either of the above solutions:

axios.interceptors.response.use((response) => {
  return response
}, (error) => {
  if (error.response && error.response.data && error.response.data.location) {
    window.location = error.response.data.location
  } else {
    return Promise.reject(error)
  }
})
43reactions
guguretecommented, Jun 7, 2017

Yes, I have the same issue. It is critical enough to consider alternatives to axios

Read more comments on GitHub >

github_iconTop Results From Across the Web

Cannot handle 302 redirect in ajax and why? - Stack Overflow
I have a back-end server written in asp.net mvc using Forms Authentication. When the user is not authenticated, the server will automatically ...
Read more >
How To Fix the HTTP 302 Error (5 Methods) - Kinsta
HTTP 302 codes are useful to temporarily redirect website users to another URL. If you're getting this error code, here are 5 ways...
Read more >
Ajax and 302 response code Testing
In our test program, because the Redirection URL returned by 302 does not have a corresponding handler on the server, the 404 status...
Read more >
Howto handle 302 redirects - Google Groups
Backbone uses the $.ajax call under the hood. Go to "http://api.jquery.com/jQuery.ajax/", and do a text search for statusCode. You'll see that statusCode is...
Read more >
Getting 302 redirect error on laravel ajax requests. - Laracasts
When i run ajax request 2 request get fired, in 1 i get 302 and in 1 i get 200 and i think...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found