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)
or308 (Permanent Redirect)
are used to permanently change a URL and retain existing links.Temporary Redirection: Status codes like
302 (Found)
,303 (See Other)
, or307 (Temporary Redirect)
are used for temporary access or displaying progress pages.Special Redirection: Codes such as
304 (Not Modified)
and300 (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.