preface

Some time ago, I took over a project and saw a code like this:

    if( isHTML(data) && response.request.responseURL? .indexOf(CAS_PREFIX) > -1
    ) {
      window.location.href = response.request.responseURL;
    }
Copy the code

The main function is to jump to the login page when the content of the backend response is HTML. This solution made me feel a little uncomfortable, so I learned exactly why the code was there.

The core of the function lies in user authentication. The back-end envisage scheme is: the current end initiates an interface request, and when the back-end identifies that the user is not logged in, it will give the front end a status code of 302, which is very important. The front end directly jumps to the login page without processing.

What they don’t know, however, is that ajax requests from the front end don’t jump directly, or even capture a 302 status code.

Common status code

The HTTP response status code indicates whether a particular HTTP request has completed successfully. Responses fall into five categories: message response (100-199), success response (200-299), redirection (300-399), client error (400-499), and server error (500-599).

  • 200: Request succeeded
  • 301: Permanent redirect
  • 302: Temporary redirect
  • 303: Hard Candy Girl
  • 304: Contents unchanged
  • 4: Arsenal
  • 401: Verification is required
  • 403: Access denied
  • 404: Not found
  • 500: The server is abnormal

More status codes: Portals

We know that browsers behave differently for different status codes. How does the browser react when 302 is returned?

The browser processes the 302 status code

A redirect, as the name suggests, redirects the request to a new address.

When the browser initiates a request and the server returns a 302 status code, the browser will re-initiate the request based on the location field in the response header. The browser throws an ERR_TOO_MANY_REDIRECT exception when there are too many redirects.

Requests fall into two categories:

  • Browser page request: Jump to a new page.
  • Ajax request: Returns a response to the last redirected address. This redirection can lead to cross-domain problems.

As mentioned earlier, the server found it convenient to return to 302, presumably assuming that Ajax would also redirect to the new page.

Prevent Ajax redirects

When making requests using the FETCH Api, you can configure how to handle redirects using the Redirect parameter.

Redirect has three optional values:

  • follow: Automatic redirection
  • error: Terminates automatically and throws an error if a redirect occursTypeError: Failed to fetch
  • manual: Manually processes redirection

Follow is used by default in Chrome (manual was the default before Chrome 47).

When we set it to manual, we get a response of type OPAquereDirect if a redirection occurs:

{
    "body": null."bodyUsed": false."headers": {},
    "ok": false."redirected": false."status": 0."statusText": ""."type": "opaqueredirect"."url": "https://xxx.com",}Copy the code

In general, we don’t need to handle redirects manually, because you don’t know if the redirection is just a redirection because you’re not logged in.

How do I solve the problem of unlogged hops

When the user is not logged in, in addition to the 302 status code, we can choose to use 401 or 403 status code, so that at least the front end can catch and make the jump processing.

In the project, the protocol format between us and the server is json, and the content format of the response is as follows:

{
    "code": 0."data": null."msg": "ok"
}
Copy the code

Typically, the server will respond with the HTTP status code of 200 and then use the code field in the body to identify the business exception. So if the user is not logged in, it is also a good choice to respond with the following:

{
    "code": 40401."data": "https://login.xxx.com"."msg": "Unauthorized"
}
Copy the code

If you really want to consider auto-jump scenarios, you can differentiate on the server side whether the request comes from a page request or an Ajax request, and then respond differently depending on the request. Take Express for example:

// The user needs to login again
if (req.xhr) {
  res.status(200).json({
    code: 40401.data: 'https://login.xxx.com'.msg: "Unauthorized"})}else {
  res.redirect('https://login.xxx.com')}Copy the code

In addition, we can use the Accept request header to differentiate the response.

The Accept request header is used to tell the client what type of content it can process, which is represented by MIME type. With the Content negotiation mechanism, the server can select one of many alternatives to apply and notify the client of its choice using the Content-Type reply header. The browser sets the appropriate value for the request header based on the context of the request, for example, fetching a CSS cascading style sheet is different from fetching an image, video, or script file.

Common, directly in the browser navigation bar open an address, Accept the value will probably be Accept: text/HTML and application/XHTML + XML, application/XML. Q = 0.9, image/avif, image/webp image/apng, * / *; Q = 0.8, application/signed – exchange; v=b3; Q = 0.9; For ajax requests, it would be: Accept: application/json, text/javascript, */*; Q = 0.01. Among them; The value of q= (q factor weight) represents the weight.

More Accept: Portal

After the language

Finally, click on the problem.

When the back end returns you the 302, in their opinion, it should look like this:

On the front end, however, it looks like this:

Above, a brief discussion of the common and not often handled status code 302, if there is any mistake, welcome to correct!