1# Resolving Cross-Origin Resource Access 2 3## Background 4 5For security purposes, the ArkWeb kernel does not allow the file and resource protocols to access cross-origin requests. As such, the **Web** component blocks such requests when loading local offline resources. To allow cross-origin requests using the file, you can use method 2 to set a path list. When **Web** components cannot access local cross-origin resources, the DevTools console displays the following error message: 6 7``` 8Access to script at 'xxx' from origin 'xxx' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, arkweb, data, chrome-extension, chrome, https, chrome-untrusted. 9``` 10 11## Solutions to Local Cross-Origin Resource Access 12 13- Method 1 14 15 Use HTTP or HTTPS instead of the file or resource protocol to enable **Web** components to successfully access cross-origin resources. Customize URL domain names for individuals or organizations to prevent conflicts with actual domain names on the Internet. You also need to use the [onInterceptRequest](../reference/apis-arkweb/arkts-basic-components-web-events.md#oninterceptrequest9) API of the **Web** component to intercept and replace local resources. 16 17 The following uses an example to describe how to use HTTP or HTTPS to access local cross-origin resources. the **index.html** and **js/script.js** files are stored in the **rawfile** folder of the project directory. When the resource protocol is used to access the **index.html** file, the **js/script.js** file is intercepted due to cross-origin access and cannot be loaded. In the example, the domain name **https:\//www\.example.com/** is used to replace the original resource protocol, and the **onInterceptRequest** API is used to replace the resource to ensure that the **js/script.js** file can be successfully loaded. In this way, the cross-origin interception problem is solved. 18 19 ```ts 20 // main/ets/pages/Index.ets 21 import { webview } from '@kit.ArkWeb'; 22 23 @Entry 24 @Component 25 struct Index { 26 @State message: string = 'Hello World'; 27 webviewController: webview.WebviewController = new webview.WebviewController(); 28 // Construct a mapping table between domain names and local files. 29 schemeMap = new Map([ 30 ["https://www.example.com/index.html", "index.html"], 31 ["https://www.example.com/js/script.js", "js/script.js"], 32 ]) 33 // Construct the local file and construct the return value format mimeType. 34 mimeTypeMap = new Map([ 35 ["index.html", 'text/html'], 36 ["js/script.js", "text/javascript"] 37 ]) 38 39 build() { 40 Row() { 41 Column() { 42 // For the local index.html file, use HTTP or HTTPS in place of file or resource as the protocol and construct a custom domain name. 43 // In this example, www.example.com is constructed. 44 Web({ src: "https://www.example.com/index.html", controller: this.webviewController }) 45 .javaScriptAccess(true) 46 .fileAccess(true) 47 .domStorageAccess(true) 48 .geolocationAccess(true) 49 .width("100%") 50 .height("100%") 51 .onInterceptRequest((event) => { 52 if (!event) { 53 return; 54 } 55 // Search for the local offline resource to be loaded, and then intercept and replace the resource. 56 if (this.schemeMap.has(event.request.getRequestUrl())) { 57 let rawfileName: string = this.schemeMap.get(event.request.getRequestUrl())!; 58 let mimeType = this.mimeTypeMap.get(rawfileName); 59 if (typeof mimeType === 'string') { 60 let response = new WebResourceResponse(); 61 // Construct the response data. If the local file is in rawfile, you can set the response data as follows: 62 response.setResponseData($rawfile(rawfileName)); 63 response.setResponseEncoding('utf-8'); 64 response.setResponseMimeType(mimeType); 65 response.setResponseCode(200); 66 response.setReasonMessage('OK'); 67 response.setResponseIsReady(true); 68 return response; 69 } 70 } 71 return null; 72 }) 73 } 74 .width('100%') 75 } 76 .height('100%') 77 } 78 } 79 ``` 80 81 ```html 82 <!-- main/resources/rawfile/index.html --> 83 <html> 84 <head> 85 <meta name="viewport" content="width=device-width,initial-scale=1"> 86 </head> 87 <body> 88 <script crossorigin src="./js/script.js"></script> 89 </body> 90 </html> 91 ``` 92 93 ```js 94 // main/resources/rawfile/js/script.js 95 const body = document.body; 96 const element = document.createElement('div'); 97 element.textContent = 'success'; 98 body.appendChild(element); 99 ``` 100 101- Method 2 102 103 Use [setPathAllowingUniversalAccess](../reference/apis-arkweb/arkts-apis-webview-WebviewController.md#setpathallowinguniversalaccess12) to set a path list for cross-origin access to local files using the file protocol. Note that only the resources in the path list can be accessed by the file protocol when this method is used. In this case, the behavior of [fileAccess](../reference/apis-arkweb/arkts-basic-components-web-attributes.md#fileaccess) is overwritten. The paths in the list should be any of the following directories: 104 105 1. The application file directory and its subdirectories, which can be obtained through [Context.filesDir](../reference/apis-ability-kit/js-apis-inner-application-context.md#context), such as: 106 107 * /data/storage/el2/base/files/example 108 * /data/storage/el2/base/haps/entry/files/example 109 110 2. The application resource directory and its subdirectories, which can be obtained through [Context.resourceDir](../reference/apis-ability-kit/js-apis-inner-application-context.md#context), such as: 111 112 * /data/storage/el1/bundle/entry/resource/resfile 113 * /data/storage/el1/bundle/entry/resource/resfile/example 114 115 If a path is not any of the preceding paths, an error code 401 is reported and the path list fails to be set. If the path list is empty, the access scope of the file protocol complies with the [fileAccess](../reference/apis-arkweb/arkts-basic-components-web-attributes.md#fileaccess) rule. The following is an example: 116 117 ```ts 118 // main/ets/pages/index.ets 119 import { webview } from '@kit.ArkWeb'; 120 import { BusinessError } from '@kit.BasicServicesKit'; 121 122 @Entry 123 @Component 124 struct WebComponent { 125 controller: WebviewController = new webview.WebviewController(); 126 uiContext: UIContext = this.getUIContext(); 127 128 build() { 129 Row() { 130 Web({ src: "", controller: this.controller }) 131 .onControllerAttached(() => { 132 try { 133 // Set the list of paths that allow cross-domain access. 134 this.controller.setPathAllowingUniversalAccess([ 135 this.uiContext.getHostContext()!.resourceDir, 136 this.uiContext.getHostContext()!.filesDir + "/example" 137 ]) 138 this.controller.loadUrl("file://" + this.uiContext.getHostContext()!.resourceDir + "/index.html") 139 } catch (error) { 140 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 141 } 142 }) 143 .javaScriptAccess(true) 144 .fileAccess(true) 145 .domStorageAccess(true) 146 } 147 } 148 } 149 ``` 150 151 ```html 152 <!-- main/resources/resfile/index.html --> 153 <!DOCTYPE html> 154 <html lang="en"> 155 156 <head> 157 <meta charset="utf-8"> 158 <title>Demo</title> 159 <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, viewport-fit=cover"> 160 <script> 161 function getFile() { 162 var file = "file:///data/storage/el1/bundle/entry/resources/resfile/js/script.js"; 163 // Use the file protocol to access the local JS file through XMLHttpRequest. 164 var xmlHttpReq = new XMLHttpRequest(); 165 xmlHttpReq.onreadystatechange = function(){ 166 console.log("readyState:" + xmlHttpReq.readyState); 167 console.log("status:" + xmlHttpReq.status); 168 if(xmlHttpReq.readyState == 4){ 169 if (xmlHttpReq.status == 200) { 170 // If the path list is set on eTS, resources can be obtained. 171 const element = document.getElementById('text'); 172 element.textContent = "load " + file + " success"; 173 } else { 174 // If the path list is not set on eTS, a CORS error is triggered. 175 const element = document.getElementById('text'); 176 element.textContent = "load " + file + " failed"; 177 } 178 } 179 } 180 xmlHttpReq.open("GET", file); 181 xmlHttpReq.send(null); 182 } 183 </script> 184 </head> 185 186 <body> 187 <div class="page"> 188 <button id="example" onclick="getFile()">loadFile</button> 189 </div> 190 <div id="text"></div> 191 </body> 192 193 </html> 194 ``` 195 196 ```javascript 197 // main/resources/resfile/js/script.js 198 const body = document.body; 199 const element = document.createElement('div'); 200 element.textContent = 'success'; 201 body.appendChild(element); 202 ``` 203