1# HTTP Data Request 2 3## When to Use 4 5An application can initiate a data request over HTTP. Common HTTP methods include **GET**, **POST**, **OPTIONS**, **HEAD**, **PUT**, **DELETE**, **TRACE**, and **CONNECT**. 6 7<!--RP1--> 8 9<!--RP1End--> 10 11## Available APIs 12 13The HTTP request function is mainly implemented by the HTTP module. 14 15To use related APIs, you must declare the **ohos.permission.INTERNET** permission. 16 17For details about how to apply for permissions, see [Declaring Permissions](../security/AccessToken/declare-permissions.md). 18 19The following table provides only a simple description of the related APIs. For details, see [API Reference](../reference/apis-network-kit/js-apis-http.md). 20 21| API | Description | 22| ----------------------------------------- | ----------------------------------- | 23| createHttp() | Creates an HTTP request. | 24| request() | Initiates an HTTP request to a given URL. | 25| requestInStream()<sup>10+</sup> | Initiates an HTTP network request to a given URL and returns a streaming response.| 26| destroy() | Destroys an HTTP request. | 27| on(type: 'headersReceive') | Registers an observer for HTTP Response Header events. | 28| off(type: 'headersReceive') | Unregisters the observer for HTTP Response Header events.| 29| once\('headersReceive'\)<sup>8+</sup> | Registers a one-time observer for HTTP Response Header events.| 30| on\('dataReceive'\)<sup>10+</sup> | Registers an observer for events indicating receiving of HTTP streaming responses. | 31| off\('dataReceive'\)<sup>10+</sup> | Unregisters the observer for events indicating receiving of HTTP streaming responses. | 32| on\('dataEnd'\)<sup>10+</sup> | Registers an observer for events indicating completion of receiving HTTP streaming responses. | 33| off\('dataEnd'\)<sup>10+</sup> | Unregisters the observer for events indicating completion of receiving HTTP streaming responses.| 34| on\('dataReceiveProgress'\)<sup>10+</sup> | Registers an observer for events indicating progress of receiving HTTP streaming responses. | 35| off\('dataReceiveProgress'\)<sup>10+</sup> | Unregisters the observer for events indicating progress of receiving HTTP streaming responses.| 36| on\('dataSendProgress'\)<sup>11+</sup> | Registers an observer for events indicating progress of sending HTTP requests. | 37| off\('dataSendProgress'\)<sup>11+</sup> | Unregisters the observer for events indicating progress of sending HTTP requests.| 38 39## Initiating an HTTP Data Request 40 411. Import the **http** namespace from **@kit.NetworkKit**. 422. Call **createHttp()** to create an **HttpRequest** object. 433. Call **httpRequest.on()** to subscribe to HTTP response header events. This API returns a response earlier than the request. You can subscribe to HTTP response header events based on service requirements. 444. Call **httpRequest.request()** to initiate a network request. You need to pass in the URL and optional parameters of the HTTP request. 455. Parse the returned result based on service requirements. 466. Call **off()** to unsubscribe from HTTP response header events. 477. Call **httpRequest.destroy()** to release resources after the request is processed. 48 49>**NOTE** 50> 51>In the sample code provided in this topic, **this.context** is used to obtain the UIAbilityContext, where **this** indicates a UIAbility instance inherited from **UIAbility**. To use **UIAbilityContext** APIs on pages, see [Obtaining the Context of UIAbility](../application-models/uiability-usage.md#obtaining-the-context-of-uiability). 52 53```ts 54// Import the http namespace. 55import { http } from '@kit.NetworkKit'; 56import { BusinessError } from '@kit.BasicServicesKit'; 57import { common } from '@kit.AbilityKit'; 58 59let context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext; 60// Each httpRequest corresponds to an HTTP request task and cannot be reused. 61let httpRequest = http.createHttp(); 62// This API is used to listen for the HTTP Response Header event, which is returned earlier than the result of the HTTP request. It is up to you whether to listen for HTTP Response Header events. 63// on('headerReceive', AsyncCallback) is replaced by on('headersReceive', Callback) since API version 8. 64httpRequest.on('headersReceive', (header) => { 65 console.info('header: ' + JSON.stringify(header)); 66}); 67httpRequest.request( 68 // Customize EXAMPLE_URL in extraData on your own. It is up to you whether to add parameters to the URL. 69 "EXAMPLE_URL", 70 { 71 method: http.RequestMethod.POST, // Optional. The default value is http.RequestMethod.GET. 72 // You can add header fields based on service requirements. 73 header: { 74 'Content-Type': 'application/json' 75 }, 76 // This field is used to transfer the request body when a POST request is used. Its format needs to be negotiated with the server. 77 extraData: "data to send", 78 expectDataType: http.HttpDataType.STRING, // Optional. This field specifies the type of the return data. 79 usingCache: true, // Optional. The default value is true. 80 priority: 1, // Optional. The default value is 1. 81 connectTimeout: 60000 // Optional. The default value is 60000, in ms. 82 readTimeout: 60000, // Optional. The default value is 60000, in ms. 83 usingProtocol: http.HttpProtocol.HTTP1_1, // Optional. The default protocol type is automatically specified by the system. 84 usingProxy: false, // Optional. By default, network proxy is not used. This field is supported since API version 10. 85 caPath: '/path/to/cacert.pem', // Optional. The prebuilt CA certificate is used by default. This field is supported since API version 10. 86 clientCert: { // Optional. The client certificate is not used by default. This field is supported since API version 11. 87 certPath: '/path/to/client.pem', // The client certificate is not used by default. This field is supported since API version 11. 88 keyPath: '/path/to/client.key', // If the certificate contains key information, an empty string is passed. This field is supported since API version 11. 89 certType: http.CertType.PEM, // Certificate type, optional. A certificate in the PEM format is used by default. This field is supported since API version 11. 90 keyPassword: "passwordToKey" // Password of the key file, optional. It is supported since API version 11. 91 }, 92 multiFormDataList: [ // Optional. This field is valid only when content-Type in the header is multipart/form-data. It is supported since API version 11. 93 { 94 name: "Part1", // Data name. This field is supported since API version 11. 95 contentType: 'text/plain', // Data type. This field is supported since API version 11. 96 data: 'Example data', // Data content, optional. This field is supported since API version 11. 97 remoteFileName: 'example.txt' // Optional. This field is supported since API version 11. 98 }, { 99 name: "Part2", // Data name. This field is supported since API version 11. 100 contentType: 'text/plain', // Data type. This field is supported since API version 11. 101 // data/app/el2/100/base/com.example.myapplication/haps/entry/files/fileName.txt 102 filePath: `${context.filesDir}/fileName.txt`, // File path, optional. This field is supported since API version 11. 103 remoteFileName: 'fileName.txt' // Optional. This field is supported since API version 11. 104 } 105 ] 106 }, (err: BusinessError, data: http.HttpResponse) => { 107 if (!err) { 108 // data.result carries the HTTP response. Parse the response based on service requirements. 109 console.info('Result:' + JSON.stringify(data.result)); 110 console.info('code:' + JSON.stringify(data.responseCode)); 111 // data.header carries the HTTP response header. Parse the content based on service requirements. 112 console.info('header:' + JSON.stringify(data.header)); 113 console.info('cookies:' + JSON.stringify(data.cookies)); // 8+ 114 // Call the destroy() method to release resources after HttpRequest is complete. 115 httpRequest.destroy(); 116 } else { 117 console.error('error:' + JSON.stringify(err)); 118 // Unsubscribe from HTTP Response Header events. 119 httpRequest.off('headersReceive'); 120 // Call the destroy() method to release resources after HttpRequest is complete. 121 httpRequest.destroy(); 122 } 123 } 124); 125``` 126 127## Initiating an HTTP Streaming Request 128 1291. Import the **http** namespace from **@kit.NetworkKit**. 1302. Call **createHttp()** to create an **HttpRequest** object. 1313. Depending on your need, call **on()** of the **HttpRequest** object to subscribe to HTTP response header events as well as events indicating receiving of HTTP streaming responses, progress of receiving HTTP streaming responses, and completion of receiving HTTP streaming responses. 1324. Call **requestInStream()** to initiate a network request. You need to pass in the URL and optional parameters of the HTTP request. 1335. Parse the returned response code as needed. 1346. Call **off()** of the **HttpRequest** object to unsubscribe from the related events. 1357. Call **httpRequest.destroy()** to release resources after the request is processed. 136 137```ts 138// Import the http namespace. 139import { http } from '@kit.NetworkKit'; 140import { BusinessError } from '@kit.BasicServicesKit'; 141 142// Each httpRequest corresponds to an HTTP request task and cannot be reused. 143let httpRequest = http.createHttp(); 144// Subscribe to HTTP response header events. 145httpRequest.on('headersReceive', (header: Object) => { 146 console.info('header: ' + JSON.stringify(header)); 147}); 148// Subscribe to events indicating receiving of HTTP streaming responses. 149let res = new ArrayBuffer(0); 150httpRequest.on('dataReceive', (data: ArrayBuffer) => { 151 const newRes = new ArrayBuffer(res.byteLength + data.byteLength); 152 const resView = new Uint8Array(newRes); 153 resView.set(new Uint8Array(res)); 154 resView.set(new Uint8Array(data), res.byteLength); 155 res = newRes; 156 console.info('res length: ' + res.byteLength); 157}); 158// Subscribe to events indicating completion of receiving HTTP streaming responses. 159httpRequest.on('dataEnd', () => { 160 console.info('No more data in response, data receive end'); 161}); 162// Subscribe to events indicating progress of receiving HTTP streaming responses. 163class Data { 164 receiveSize: number = 0; 165 totalSize: number = 0; 166} 167httpRequest.on('dataReceiveProgress', (data: Data) => { 168 console.log("dataReceiveProgress receiveSize:" + data.receiveSize + ", totalSize:" + data.totalSize); 169}); 170 171let streamInfo: http.HttpRequestOptions = { 172 method: http.RequestMethod.POST, // Optional. The default value is http.RequestMethod.GET. 173 // You can add header fields based on service requirements. 174 header: { 175 'Content-Type': 'application/json' 176 }, 177 // This field is used to transfer the request body when a POST request is used. Its format needs to be negotiated with the server. 178 extraData: "data to send", 179 expectDataType: http.HttpDataType.STRING, // Optional. This field specifies the type of the return data. 180 usingCache: true, // Optional. The default value is true. 181 priority: 1, // Optional. The default value is 1. 182 connectTimeout: 60000 // Optional. The default value is 60000, in ms. 183 readTimeout: 60000, // Optional. The default value is 60000, in ms. If a large amount of data needs to be transmitted, you are advised to set this parameter to a larger value to ensure normal data transmission. 184 usingProtocol: http.HttpProtocol.HTTP1_1 // Optional. The default protocol type is automatically specified by the system. 185} 186 187// Customize EXAMPLE_URL in extraData on your own. It is up to you whether to add parameters to the URL. 188httpRequest.requestInStream("EXAMPLE_URL", streamInfo).then((data: number) => { 189 console.info("requestInStream OK!"); 190 console.info('ResponseCode :' + JSON.stringify(data)); 191 // Unsubscribe from HTTP Response Header events. 192 httpRequest.off('headersReceive'); 193 // Unregister the observer for events indicating receiving of HTTP streaming responses. 194 httpRequest.off('dataReceive'); 195 // Unregister the observer for events indicating progress of receiving HTTP streaming responses. 196 httpRequest.off('dataReceiveProgress'); 197 // Unregister the observer for events indicating completion of receiving HTTP streaming responses. 198 httpRequest.off('dataEnd'); 199 // Call the destroy() method to release resources after HttpRequest is complete. 200 httpRequest.destroy(); 201}).catch((err: Error) => { 202 console.info("requestInStream ERROR : err = " + JSON.stringify(err)); 203}); 204``` 205 206## Certificate Pinning 207 208You can prebuild application-level certificates or a public key hash values for certificate pinning. This way, an HTTPS connection can be established only when the prebuilt certificate is used. 209 210Both modes are configured through `src/main/resources/base/profile/network_config.json`. In the configuration file, you can create mapping between prebuilt certificates and network servers. 211 212If you do not know the certificate mapping a server domain name, you can use the following command to obtain the certificate. When running the command, change `www.example.com` to the server domain name and `www.example.com.pem` to the name of the obtained certificate file. 213 214``` 215openssl s_client -servername www.example.com -connect www.example.com:443 \ 216 < /dev/null | sed -n "/-----BEGIN/,/-----END/p" > www.example.com.pem 217``` 218 219If you are using a Windows environment, you need to: 220 221* Replace `/dev/null` with `NUL`. 222* Press **Enter** to exit. This is different from OpenSSL of Linux, which may exit until the user enters a value. 223* If the **sed** command is not present, copy the content between `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----` (with these two lines included) in the command output and save it. 224 225### Prebuilding Application-level Certificates 226 227Prebuilding application-level certificates means to embed the original certificate files in the application. Currently, certificate files in the **.crt** and **.pem** formats are supported. 228 229> **NOTE** 230> 231> Currently, certificate pinning has been enabled for the ohos.net.http and Image components, and the hash values of all certificates in the certificate chain are matched. If any certificate is updated on the server, the verification fails. Therefore, if any certificate on the server has been updated, upgrade the application to the latest version as soon as possible. Otherwise, network connection may fail. 232 233### Prebuilding Certificate Public Key Hash Values 234 235You can create mapping between public key hash values and domain name certificates in the configuration file. This way, access to the domain name is allowed only if the used domain name certificate matches the prebuilt public key hash value. 236 237The public key hash value of the domain name certificate can be calculated using the following command. Assume that the domain name certificate is obtained using the preceding OpenSSL command and saved in the `www.example.com.pem` file. The line that starts with # is treated as a comment. 238 239``` 240# Extract the public key from the certificate. 241openssl x509 -in www.example.com.pem -pubkey -noout > www.example.com.pubkey.pem 242# Convert the public key from the pem format to the der format. 243openssl asn1parse -noout -inform pem -in www.example.com.pubkey.pem -out www.example.com.pubkey.der 244# Calculate the SHA256 of the public key and convert it to Base64. 245openssl dgst -sha256 -binary www.example.com.pubkey.der | openssl base64 246``` 247 248### Example of the JSON Configuration File 249 250The following is an example of prebuilt application-level certificates. For details about the configuration path, see [Network Connection Security Configuration](https://developer.huawei.com/consumer/en/doc/best-practices/bpta-network-ca-security#section5454123841911). 251 252```json 253{ 254 "network-security-config": { 255 "base-config": { 256 "trust-anchors": [ 257 { 258 "certificates": "/etc/security/certificates" 259 } 260 ] 261 }, 262 "domain-config": [ 263 { 264 "domains": [ 265 { 266 "include-subdomains": true, 267 "name": "example.com" 268 } 269 ], 270 "trust-anchors": [ 271 { 272 "certificates": "/data/storage/el1/bundle/entry/resources/resfile" 273 } 274 ] 275 } 276 ] 277 } 278} 279``` 280 281The following is an example of prebuilt certificate public key hash values: 282``` 283{ 284 "network-security-config": { 285 "domain-config": [ 286 { 287 "domains": [ 288 { 289 "include-subdomains": true, 290 "name": "server.com" 291 } 292 ], 293 "pin-set": { 294 "expiration": "2024-11-08", 295 "pin": [ 296 { 297 "digest-algorithm": "sha256", 298 "digest": "FEDCBA987654321" 299 } 300 ] 301 } 302 } 303 ] 304 } 305} 306``` 307 308The following is an example configuration for overall and host name–based HTTP access: 309``` 310{ 311 "network-security-config": { 312 "base-config": { 313 "cleartextTrafficPermitted": true 314 }, 315 "domain-config": [ 316 { 317 "domains": [ 318 { 319 "include-subdomains": true, 320 "name": "example.com" 321 } 322 ], 323 "cleartextTrafficPermitted": false 324 } 325 ] 326 } 327} 328``` 329 330The following is an example configuration of the certificate pin: 331``` 332{ 333 "network-security-config": { 334 "domain-config": [ 335 { 336 "domains": [ 337 { 338 "include-subdomains": true, 339 "name": "server.com" 340 } 341 ], 342 "pin-set": { 343 "expiration": "2024-11-08", 344 "pin": [ 345 { 346 "digest-algorithm": "sha256", 347 "digest": "FEDCBA987654321" 348 } 349 ] 350 } 351 } 352 ] 353 }, 354 "trust-global-user-ca": false, 355 "trust-current-user-ca": false, 356} 357``` 358 359**Description of fields** 360 361| Field | Type | Description | 362| --------------------------| --------------- | -------------------------------------- | 363|network-security-config | object |Network security configuration. The value can contain zero or one **base-config** and must contain one **domain-config**.| 364|base-config | object |Application security configuration. The value must contain one **trust-anchors**. | 365|domain-config | array |Domain security configuration. The value can contain any number of items. An item must contain one **domains** and can contain zero or one **trust-anchors** and **pin-set**.| 366|trust-anchors | array |Trusted CA. The value can contain any number of items. An item must contain one **certificates**.| 367|certificates | string |CA certificate path.| 368|domains | array |Domain. The value can contain any number of items. An item must contain one **name** (string: domain name) and can contain zero or one **include-subdomains**.| 369|include-subdomains | boolean |Whether a rule applies to subdomains. Whether a rule applies to subdomains. The value **true** indicates that the rule applies to subdomains, and the value **false** indicates the opposite.| 370|pin-set | object |Certificate public key hash setting. The value must contain one **pin** and can contain zero or one **expiration**.| 371|expiration | string |Expiration time of the certificate public key hash.| 372|pin | array |Certificate public key hash. The value can contain any number of items. An item must contain one **digest-algorithm** and **digest**.| 373|digest-algorithm | string |Digest algorithm used to generate hashes. Currently, only `sha256` is supported. | 374|digest | string |Public key hash.| 375|cleartextTrafficPermitted | boolean |Whether plaintext HTTP is allowed. The value **true** indicates that plaintext HTTP is allowed, and the value **false** indicates the opposite.| 376 377 378## Configuring Untrusted User-Installed CA Certificates 379By default, the system trusts the prebuilt CA certificates and user-installed CA certificates. To further improve security, you can configure untrusted user-installed CA certificates in **src/main/resources/base/profile/network_config.json**. For more network connection security configurations, see [Network Connection Security Configuration](https://developer.huawei.com/consumer/en/doc/best-practices/bpta-network-ca-security#section5454123841911). 380``` 381{ 382 "network-security-config": { 383 ... ... 384 }, 385 "trust-global-user-ca": false, // Set whether to trust the CA certificate manually installed by the enterprise MDM system or device administrator. The default value is true. 386 "trust-current-user-ca" : false // Set whether to trust the certificate installed by the current user. The default value is true. 387} 388``` 389