前言
移动应用的本质是数据消费——从服务器获取数据、提交表单、上传文件,这一切都依赖 HTTP 网络请求。HarmonyOS 提供了@ohos.net.http模块,封装了完整的 HTTP 客户端能力,支持 GET/POST 等常见方法、自定义请求头、超时控制、响应解析等核心功能。
相比 Web 端的fetch/XMLHttpRequest,HarmonyOS 的 HTTP 模块采用了更接近原生网络栈的设计——createHttp()创建请求任务、request()发起请求、destroy()释放资源。这种显式的生命周期管理让开发者对网络连接有更精细的控制。
本文通过一个可交互的API 请求调试器Demo,深入讲解@ohos.net.http的全部核心 API,涵盖请求配置、响应处理、错误捕获和资源释放。
导入与基础概念
@ohos.net.http从@kit.NetworkKit导入,模块核心是http命名空间下的三个关键元素:
import{http}from'@kit.NetworkKit';| 元素 | 类型 | 说明 |
|---|---|---|
http.createHttp() | 函数 | 创建 HTTP 请求任务实例 |
http.HttpRequest | 接口 | 请求任务对象,提供request、destroy等方法 |
http.HttpResponse | 接口 | 响应对象,包含result、responseCode、header |
createHttp() —— 创建请求任务
一切 HTTP 请求的起点是createHttp(),它返回一个HttpRequest实例:
lethttpRequest:http.HttpRequest=http.createHttp();每个HttpRequest实例代表一个独立的网络任务。多次调用createHttp()会创建多个互不干扰的任务实例,可以并发发送多个请求。
创建实例后必须在使用完毕后调用destroy()释放底层 socket 等系统资源,否则会造成资源泄漏。
HttpRequest.request() —— 发送请求
基础用法(GET 请求)
lethttpRequest=http.createHttp();letresponse:http.HttpResponse=awaithttpRequest.request('https://api.example.com/data');httpRequest.destroy();不带options参数时,默认使用 GET 方法。返回的HttpResponse对象包含完整的响应数据。
完整配置(指定方法和请求头)
lethttpRequest=http.createHttp();letoptions:http.HttpRequestOptions={method:http.RequestMethod.GET,connectTimeout:10000,readTimeout:10000,header:{'Content-Type':'application/json','User-Agent':'HarmonyOS-App/1.0'}};letresponse:http.HttpResponse=awaithttpRequest.request(url,options);HttpRequestOptions 详细参数
HttpRequestOptions接口提供了丰富的请求配置选项:
interfaceHttpRequestOptions{method?:RequestMethod;// 请求方法,默认 GETheader?:Object;// 自定义请求头extraData?:string|Object|ArrayBuffer;// POST 请求体connectTimeout?:number;// 连接超时(毫秒),默认 60000readTimeout?:number;// 读取超时(毫秒),默认 60000expectDataType?:HttpDataType;// 期望的响应数据类型usingProtocol?:HttpProtocol;// 协议类型(HTTP/1.1 或 HTTP/2.0)usingCache?:boolean;// 是否使用缓存priority?:number;// 请求优先级 0-10multiFormDataList?:MultiFormData[];// 多表单数据certificatePinning?:CertificatePinning;// 证书锁定dnsPrefetch?:string[];// DNS 预解析clientCert?:ClientCert;// 客户端证书}RequestMethod 枚举
enumRequestMethod{OPTIONS='OPTIONS',GET='GET',HEAD='HEAD',POST='POST',PUT='PUT',DELETE='DELETE',TRACE='TRACE',CONNECT='CONNECT'}POST 请求
发送 POST 请求需要设置method和extraData:
lethttpRequest=http.createHttp();letoptions:http.HttpRequestOptions={method:http.RequestMethod.POST,header:{'Content-Type':'application/json'},extraData:JSON.stringify({title:'foo',body:'bar',userId:1})};letresponse=awaithttpRequest.request('https://jsonplaceholder.typicode.com/posts',options);httpRequest.destroy();extraData支持三种数据类型:
- string:纯文本或 JSON 字符串
- Object:JavaScript 对象(框架会自动序列化)
- ArrayBuffer:二进制数据(适合上传文件)
超时控制
connectTimeout控制建立 TCP 连接的最大等待时间,readTimeout控制等待服务器响应的最大时间。两者都应合理设置——太短会导致慢网络环境下请求频繁失败,太长会让用户等待过久。
letoptions:http.HttpRequestOptions={connectTimeout:5000,// 连接超时 5 秒readTimeout:15000// 读取超时 15 秒};对于需要快速响应的接口(如搜索建议),可以设置更短的超时;对于上传大文件的接口,应该设置更长的超时。
HttpResponse —— 响应处理
响应字段
interfaceHttpResponse{result:string|Object|ArrayBuffer;// 响应体resultType:HttpDataType;// 响应体类型标识responseCode:number;// HTTP 状态码header:Object;// 响应头cookies:string;// Cookie 字符串}响应体的三种数据类型
result的类型由expectDataType控制:
enumHttpDataType{STRING=0,// 字符串(默认)OBJECT=1,// JSON 对象ARRAY_BUFFER=2// 二进制数据}字符串(STRING):最常见的情况,API 返回 JSON 文本时使用。直接用JSON.parse()解析:
if(typeofresponse.result==='string'){letdata=JSON.parse(response.resultasstring);}对象(OBJECT):设置expectDataType: http.HttpDataType.OBJECT后,框架自动将 JSON 响应解析为对象。通过下标访问字段:
letoptions:http.HttpRequestOptions={expectDataType:http.HttpDataType.OBJECT};letresponse=awaithttpRequest.request(url,options);letresult:Object=response.result;letuserId=(resultasRecord<string,Object>)['userId'];二进制(ARRAY_BUFFER):适合下载图片、文件等二进制数据。结合util.TextDecoder可以转回文本:
import{util}from'@kit.ArkTS';if(response.resultinstanceofArrayBuffer){letdecoder=util.TextDecoder.create('utf-8');lettext=decoder.decodeWithStream(newUint8Array(response.resultasArrayBuffer),undefined);}状态码检查
responseCode是 HTTP 标准状态码:200 表示成功,2xx 系列均表示成功;4xx 表示客户端错误;5xx 表示服务器错误。
if(response.responseCode===200){// 成功}elseif(response.responseCode>=400){// 错误处理}注意:HTTP 层面的错误(如 404、500)不会抛出异常,request()仍然正常返回HttpResponse,只是responseCode不是 2xx。只有网络层面的错误(如 DNS 解析失败、连接超时、TLS 握手失败)才会通过异常抛出。
响应头解析
response.header是一个键值对对象,通过下标访问:
letheader:Object=response.header;letcontentType=(headerasRecord<string,string>)['content-type'];letserver=(headerasRecord<string,string>)['server'];HttpRequest.destroy() —— 资源释放
这是最重要的 API 之一,但开发者经常忽略。每个HttpRequest实例持有底层 socket 连接,不及时destroy()会导致:
- 内存泄漏——未释放的 socket 占用内存
- 连接耗尽——系统文件描述符有限,泄露过多会导致新请求失败
- 性能退化——后台积累的僵尸连接影响网络栈性能
最佳实践:在try-finally中确保始终调用destroy():
asyncfunctionfetchData(url:string):Promise<http.HttpResponse|null>{lethttpRequest:http.HttpRequest|null=null;try{httpRequest=http.createHttp();letresponse=awaithttpRequest.request(url);returnresponse;}catch(err){console.error('请求失败');returnnull;}finally{if(httpRequest){httpRequest.destroy();}}}on(‘headersReceive’) —— 响应头事件
在请求过程中,可以在request()之前注册headersReceive事件监听器,在服务器返回响应头(但响应体尚未接收完毕)时触发:
lethttpRequest=http.createHttp();httpRequest.on('headersReceive',(header:Object)=>{console.info('收到响应头');letcontentType=(headerasRecord<string,string>)['content-type'];});letresponse=awaithttpRequest.request(url);httpRequest.destroy();这个事件在以下场景非常有用:
- 根据
content-type提前决定如何解析响应体 - 根据
content-length计算下载进度 - 记录请求耗时(在事件中计算与请求开始的时间差)
错误处理
HTTP 模块的异常分为两类:
1. 网络层异常(抛出错误)
以下情况会通过catch捕获:
try{letresponse=awaithttpRequest.request(url);}catch(err){leterrObj=errasObject;letrec=errObjasRecord<string,Object>;letmessage=rec['message']asstring;// 常见错误信息:// - "Couldn't resolve host name" → DNS 解析失败// - "Timeout was reached" → 超时// - "SSL certificate problem" → TLS 证书问题// - "Failed to connect to" → 服务器不可达}2. HTTP 层错误(正常响应)
4xx 和 5xx 状态码不会抛出异常,需要检查responseCode:
letresponse=awaithttpRequest.request(url);if(response.responseCode>=200&&response.responseCode<300){// 成功处理}elseif(response.responseCode===404){// 资源不存在}elseif(response.responseCode>=500){// 服务器错误}性能与安全建议
1. 实例复用
同一个域名下的多次请求可以复用HttpRequest实例,底层会复用 TCP 连接(HTTP Keep-Alive):
// 推荐:复用同一个实例lethttpRequest=http.createHttp();for(leturlofurls){letresponse=awaithttpRequest.request(url);}httpRequest.destroy();// 不推荐:每次都创建新实例(浪费连接)for(leturlofurls){letreq=http.createHttp();letresponse=awaitreq.request(url);req.destroy();}2. HTTPS 证书安全
生产环境应当严格验证 HTTPS 证书。HarmonyOS 默认启用系统 CA 证书库验证,这是最安全的配置。开发阶段如果遇到自签名证书,可以在测试环境使用以下配置,但绝对不能用于生产环境:
// 仅开发调试用,切勿在生产代码中使用letoptions:http.HttpRequestOptions={remoteValidation:'skip'// 跳过证书验证(危险!)};3. DNS 预解析
对于已知的目标域名,可以在应用启动时预解析 DNS,减少首次请求的延迟:
letoptions:http.HttpRequestOptions={dnsPrefetch:['api.example.com','cdn.example.com']};4. 请求优先级
当同时发起多个请求时,可以设置优先级让重要请求优先获得网络资源:
letoptions:http.HttpRequestOptions={priority:5// 0(最低)到 10(最高)};Demo:API 请求调试器
我们构建了一个完整的 HTTP 请求调试工具,可以在真机或模拟器上实际发送网络请求并查看响应。
功能模块
- URL 输入与快捷 API:输入任意 URL,或点击预设的 3 个 JSONPlaceholder API 快速填充
- GET/POST 方法切换:可视化按钮切换,GET 蓝色、POST 粉色
- 发送请求与加载状态:按钮在请求中显示"请求中…"并禁用,防止重复发送
- 响应摘要卡片:展示状态码(绿色=2xx,红色=错误,橙色=其他)、请求方法、耗时
- 响应头显示:解析并显示前 10 个响应头
- 响应体预览:等宽字体、可滚动文本框,超过 2000 字符自动截断并标注完整长度
- 请求历史:记录最近 15 条请求的序号、方法、URL、状态码和时间
核心发送逻辑
asyncsendRequest():Promise<void>{this.isLoading=true;letstartTime:number=Date.now();lethttpRequest:http.HttpRequest|null=null;try{httpRequest=http.createHttp();letoptions:http.HttpRequestOptions={method:this.methods[this.methodIndex]==='POST'?http.RequestMethod.POST:http.RequestMethod.GET,connectTimeout:10000,readTimeout:10000,header:{'Content-Type':'application/json','User-Agent':'HarmonyOS-HttpDemo/1.0'}};letresponse:http.HttpResponse=awaithttpRequest.request(this.urlInput.trim(),options);letelapsed:number=Date.now()-startTime;this.statusCode=response.responseCode.toString();this.responseTime=elapsed+'ms';// 解析响应体if(typeofresponse.result==='string'){this.responseBody=response.resultasstring;}elseif(response.resultinstanceofArrayBuffer){letdecoder=util.TextDecoder.create('utf-8');this.responseBody=decoder.decodeWithStream(newUint8Array(response.resultasArrayBuffer),undefined);}else{this.responseBody=JSON.stringify(response.result);}// 解析响应头if(response.header){lethdr:Object=response.header;letheaderStr:string='';letkeys:string[]=Object.keys(hdr);for(leti=0;i<Math.min(keys.length,10);i++){headerStr+=keys[i]+': '+(hdrasRecord<string,string>)[keys[i]]+'\n';}this.responseHeaders=headerStr;}this.addHistory(this.methods[this.methodIndex],this.urlInput.trim(),response.responseCode.toString());}catch(err){this.statusCode='ERROR';letrec:Record<string,Object>=errasRecord<string,Object>;this.responseBody='错误: '+(rec['message']asstring);this.addHistory(this.methods[this.methodIndex],this.urlInput.trim(),'FAIL');}finally{if(httpRequest){httpRequest.destroy();}this.isLoading=false;}}请求历史管理
使用不可变状态更新模式维护最近 15 条记录:
addHistory(method:string,url:string,status:string):void{this.historyIndex++;letrecord=newRequestRecord(this.historyIndex,method,url,status,newDate().toLocaleTimeString());letnewHistory:RequestRecord[]=[record].concat(this.history);if(newHistory.length>15){newHistory.pop();}this.history=newHistory;}注意事项
Demo 使用的jsonplaceholder.typicode.com是一个公开的测试 API,返回模拟数据。在实际应用开发中,你需要:
- 申请网络权限:在
module.json5中添加ohos.permission.INTERNET - 配置网络安全:生产环境使用 HTTPS,开发调试可在
module.json5中配置networkSecurity - 处理大响应:Demo 截断 2000 字符以上的响应,实际应用中应流式处理大文件下载
总结
本文详细讲解了 HarmonyOS@ohos.net.http模块的核心 API:
- createHttp()— 创建请求任务,返回 HttpRequest 实例
- HttpRequest.request()— 发送请求,支持 GET/POST 等方法、自定义请求头、超时控制
- HttpResponse— 响应处理,支持字符串/对象/二进制三种数据类型
- HttpRequest.destroy()— 资源释放,务必在请求完成后调用
- on(‘headersReceive’)— 响应头事件,提前获取元数据
- 错误处理— 区分网络层异常(catch)和 HTTP 层错误(responseCode)
HarmonyOS 的 HTTP 模块提供了完整的网络请求能力,其 API 设计强调显式资源管理,通过createHttp/destroy配对确保不泄露系统资源。结合 Promise 异步模型,可以写出清晰、可维护的网络层代码。
API 请求调试器 Demo 是一个实用的开发工具,不仅展示 HTTP 模块的使用方式,本身也可以用于日常调试第三方 API 接口。