Network Redirection Scenarios and Solutions in HarmonyOS

Time: Column:HTML+CSS views:263

Network Redirection Scenarios and Solutions in HarmonyOS

Scenario Description

When developing applications, you may encounter automatic redirection on pages, where some actions need to be performed based on the business logic. This article will explain how to handle such redirection cases.

Solution Description

Redirection refers to the process where the server directs the user's request to another page. Typically, the server sends back a specific status code that informs the browser to perform the redirection.

  • Permanent Redirection: Status codes like 301 (Moved Permanently) or 308 (Permanent Redirect) are used to permanently change a URL and retain existing links.

  • Temporary Redirection: Status codes like 302 (Found), 303 (See Other), or 307 (Temporary Redirect) are used for temporary access or displaying progress pages.

  • Special Redirection: Codes such as 304 (Not Modified) and 300 (Multiple Choice) are used in unique cases, such as cache validation.

Triggering and Detecting Redirection in WebView

In a WebView, both URL redirection and page jumps look similar, as they change the URL to load different content. JavaScript can implement page jumps using window.location.replace("url") or window.location.href="url". Similarly, a <meta> tag with the http-equiv attribute set to "refresh" can also achieve a redirect.

To distinguish between direct jumps and system-level redirection in a WebView, you can use:

event.data.isRedirect()

in the onLoadIntercept callback to determine the type of redirection.

Scenario 1: Identifying Redirection via Callback

Solution

Use the WebView callback onLoadIntercept, and check the event.data.isRedirect() method to determine whether the redirection is direct or a system-level redirection.

Core Code

Example 1: Redirect using window.location.href="url".

<!-- jump.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Jump Example</title>
    <script>
      // Automatically redirect after the page loads
      window.location.href = "https://developer.huawei.com/consumer/cn/";
    </script>
  </head>
  <body>
    Jump Example
  </body>
</html>

Example 2: Redirect using <meta> tag's http-equiv attribute.

<!-- metaJump.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html;charset=gb2312" />
    <meta 
      http-equiv="Refresh" 
      content="3;url=https://developer.huawei.com/consumer/cn/" 
    />
  </head>
  <body>
    <p>You will be automatically redirected to <a href="https://developer.huawei.com/consumer/cn/">https://developer.huawei.com/consumer/cn/</a></p>
    <p>Redirecting in 3 seconds.</p>
    <p>If not, please click the link above.</p>
  </body>
</html>

In the onLoadIntercept method of the WebView component, setting the return value to false allows the page to load without interception. After loading the local H5 file, you can see that isRedirect returns false, indicating no system redirection occurred. When clicking the button to load a URL with system redirection, isRedirect returns true, confirming the system-level redirect.

import webview from '@ohos.web.webview';

@Entry
@Component
struct Index {
  controller: WebviewController = new webview.WebviewController();
  redirectUrl: string = 'https://test url';
  @State redirectRes: string = '';

  build() {
    Column() {
      Button(`Load Server Redirect Url`).onClick((event: ClickEvent) => {
        this.controller.loadUrl(this.redirectUrl);
      });
      Web({
        src: $rawfile('jump.html'),
        controller: this.controller
      })
      .domStorageAccess(true)
      .onLoadIntercept((event) => {
        if (event) {
          if (event.data.isRedirect()) {
            console.log('3xx System Redirection');
            console.log('Redirected URL: ' + event.data.getRequestUrl());
          } else {
            console.log('Regular Page Jump');
            console.log('Redirected URL: ' + event.data.getRequestUrl());
          }
        }
        return false;
      });
    }
  }
}

Scenario 2: Redirection Loop When Returning from a History Stack

When a WebView loads a link that triggers a system redirection, the redirection may remain in the history stack. Returning to the previous page may result in another automatic redirection, causing a loop where the user can't exit.

Solution

By listening to the onBackPress lifecycle event, you can check the accessBackward() method to determine whether there is a history stack. If a system redirection occurred, adjust the history step with backOrForward() to prevent the loop.

Core Code

import web_webview from '@ohos.web.webview';

@Entry
@Component
struct WebComponent {
  controller: web_webview.WebviewController = new web_webview.WebviewController();
  @State isRedirect: boolean = false;
  @State num: number = 1;

  onBackPress(): boolean | void {
    if (this.controller.accessBackward()) {
      if (this.isRedirect) {
        this.controller.backOrForward(this.num - 2);
      } else {
        this.controller.backOrForward(-1);
      }
      return true;
    }
    return false;
  }

  build() {
    Column() {
      Web({
        src: $rawfile('jump.html'),
        controller: this.controller
      })
      .domStorageAccess(true)
      .javaScriptAccess(true)
      .onLoadIntercept((event) => {
        if (event.data.isRedirect()) {
          this.isRedirect = true;
          this.num--;
        } else {
          this.isRedirect = false;
        }
        return false;
      });
    }
  }
}

Scenario 3: Retrieving Response Headers after a System Redirection

If you need to access the status code or URL after a redirection, you can use the rcp module to retrieve response headers.

Solution

Use the session.get() method in the rcp module to get the response headers.

Core Code

import { BusinessError } from '@kit.BasicServicesKit';
import { rcp } from '@kit.RemoteCommunicationKit';

@Entry
@Component
struct PageRedirection {
  build() {
    RelativeContainer() {
      Button('Get Response Headers').onClick(() => {
        const session = rcp.createSession();
        session.get("https://test url").then((response) => {
          console.info(`${JSON.stringify(response.headers)}`);
        }).catch((err: BusinessError) => {
          console.error(`Error: code ${err.code}, message ${err.message}`);
        });
      });
    }
    .height('100%')
    .width('100%');
  }
}

In this case, the rms3-status field represents the HTTP status code, and location indicates the redirected URL.

Network Redirection Scenarios and Solutions in HarmonyOS