# 拦截Web组件发起的网络请求 通过[网络拦截接口(arkweb_scheme_handler.h)](../reference/apis-arkweb/arkweb__scheme__handler_8h.md)对Web组件发出的请求进行拦截,并可以为被拦截的请求提供自定义的响应头以及响应体。 ## 为Web组件设置网络拦截器 为指定的Web组件或者ServiceWorker设置ArkWeb_SchemeHandler,当Web内核发出相应scheme请求的时候,会触发ArkWeb_SchemeHandler的回调。需要在Web组件初始化之后设置网络拦截器。 当请求开始的时候会回调ArkWeb_OnRequestStart,请求结束的时候会回调ArkWeb_OnRequestStop。 如果想要拦截Web组件发出的第一个请求,可以通过[initializeWebEngine](../reference/apis-arkweb/js-apis-webview.md#initializewebengine)对Web组件提前进行初始化,然后设置拦截器进行拦截。 ```c++ // 创建一个ArkWeb_SchemeHandler对象。 ArkWeb_SchemeHandler *schemeHandler; OH_ArkWeb_CreateSchemeHandler(&schemeHandler); // 为ArkWeb_SchemeHandler设置ArkWeb_OnRequestStart与ArkWeb_OnRequestStop回调。 OH_ArkWebSchemeHandler_SetOnRequestStart(schemeHandler, OnURLRequestStart); OH_ArkWebSchemeHandler_SetOnRequestStop(schemeHandler, OnURLRequestStop); // 拦截webTag为“scheme-handler”的Web组件发出的scheme为“https”的请求。 OH_ArkWeb_SetSchemeHandler("https", "scheme-handler", schemeHandler); OH_ArkWebServiceWorker_SetSchemeHandler("https", schemeHandler); ``` 也可以拦截非Web组件内置scheme的请求。 ```c++ // 创建一个ArkWeb_SchemeHandler对象。 ArkWeb_SchemeHandler *schemeHandler; OH_ArkWeb_CreateSchemeHandler(&schemeHandler); // 为ArkWeb_SchemeHandler设置ArkWeb_OnRequestStart与ArkWeb_OnRequestStop回调。 OH_ArkWebSchemeHandler_SetOnRequestStart(schemeHandler, OnURLRequestStart); OH_ArkWebSchemeHandler_SetOnRequestStop(schemeHandler, OnURLRequestStop); // 拦截webTag为“scheme-handler”的Web组件发出的scheme为“custom”的请求。 OH_ArkWeb_SetSchemeHandler("custom", "scheme-handler", schemeHandler); OH_ArkWebServiceWorker_SetSchemeHandler("custom", schemeHandler); ``` ## 设置自定义scheme需要遵循的规则 如果要拦截自定义scheme的请求,需要提前将自定义scheme注册到Web内核。需要在Web组件初始化之前进行注册,Web组件初始化后再注册会失败。 ```c++ // 注册“custom“ scheme到Web组件,并指定该scheme需要遵循标准的scheme规则,允许该scheme发出跨域请求。 OH_ArkWeb_RegisterCustomSchemes("custom", ARKWEB_SCHEME_OPTION_STANDARD | ARKWEB_SCHEME_OPTION_CORS_ENABLED); // 注册“custom-local” scheme到Web组件,并指定该scheme需要遵循与“file” scheme一样的规则。 OH_ArkWeb_RegisterCustomSchemes("custom-local", ARKWEB_SCHEME_OPTION_LOCAL); // 注册“custom-csp-bypassing”到Web组件,并指定该scheme需要遵循标准的scheme规则,允许忽略CSP检查。 OH_ArkWeb_RegisterCustomSchemes("custom-csp-bypassing", ARKWEB_SCHEME_OPTION_CSP_BYPASSING | ARKWEB_SCHEME_OPTION_STANDARD); // 注册“custom-isolated”到Web组件,并指定该scheme的请求必须从相同scheme加载的网页中发起。 OH_ArkWeb_RegisterCustomSchemes("custom-isolated", ARKWEB_SCHEME_OPTION_DISPLAY_ISOLATED); ``` 由于注册scheme需要在Web组件初始化之前进行注册,而网络拦截器需要在Web组件初始化之后设置,建议在EntryAbility的onCreate中调用c++接口注册scheme。 scheme注册完毕后,通过[initializeWebEngine](../reference/apis-arkweb/js-apis-webview.md#initializewebengine)对Web组件进行初始化,初始化完成后再设置网络拦截器。 ```ts export default class EntryAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { // 注册scheme的配置。 testNapi.registerCustomSchemes(); // 初始化Web组件内核,该操作会初始化Browser进程以及创建BrowserContext。 webview.WebviewController.initializeWebEngine(); // 创建并设置ArkWeb_SchemeHandler。 testNapi.setSchemeHandler(); } ... }; ``` ## 获取被拦截请求的请求信息 通过OH_ArkWebResourceRequest_*接口获取被拦截请求的信息。可以获取url、method、referrer、headers、resourceType等信息。 ```c++ char* url; OH_ArkWebResourceRequest_GetUrl(resourceRequest_, &url); OH_ArkWeb_ReleaseString(url); char* method; OH_ArkWebResourceRequest_GetMethod(resourceRequest_, &method); OH_ArkWeb_ReleaseString(method); int32_t resourceType = OH_ArkWebResourceRequest_GetResourceType(resourceRequest_); char* frameUrl; OH_ArkWebResourceRequest_GetFrameUrl(resourceRequest_, &frameUrl); OH_ArkWeb_ReleaseString(frameUrl); ... ``` 支持获取PUT/POST类请求的上传数据。数据类型支持BYTES、FILE、BLOB和CHUNKED。 ```c++ // 获取被拦截请求的上传数据。 OH_ArkWebResourceRequest_GetHttpBodyStream(resourceRequest(), &stream_); // 设置读取上传数据的读回调。 OH_ArkWebHttpBodyStream_SetReadCallback(stream_, ReadCallback); // 初始化ArkWeb_HttpBodyStream,其它OH_ArkWebHttpBodyStream*函数需要在初始化进行调用。 OH_ArkWebHttpBodyStream_Init(stream_, InitCallback); ``` ## 为被拦截的请求提供自定义的响应体 Web组件的网络拦截支持在worker线程以流的方式为被拦截的请求提供自定义的响应体。也可以以特定的[网络错误码(arkweb_net_error_list.h)](../reference/apis-arkweb/arkweb__net__error__list_8h.md)结束当前被拦截的请求。 ```c++ // 为被拦截的请求创建一个响应头。 ArkWeb_Response *response; OH_ArkWeb_CreateResponse(&response); // 设置HTTP状态码为200。 OH_ArkWebResponse_SetStatus(response, 200); // 设置响应体的编码格式。 OH_ArkWebResponse_SetCharset(response, "UTF-8"); // 设置响应体的大小。 OH_ArkWebResponse_SetHeaderByName(response, "content-length", "1024", false); // 将为被拦截的请求创建的响应头传递给Web组件。 OH_ArkWebResourceHandler_DidReceiveResponse(resourceHandler, response); // 该函数可以调用多次,数据可以分多份来传递给Web组件。 OH_ArkWebResourceHandler_DidReceiveData(resourceHandler, buffer, bufLen); // 读取响应体结束,当然如果希望该请求失败的话也可以通过调用OH_ArkWebResourceHandler_DidFailWithError(resourceHandler_, errorCode); // 传递给Web组件一个错误码并结束该请求。 OH_ArkWebResourceHandler_DidFinish(resourceHandler); ``` ## 完整示例 使用DevEco Studio创建一个默认的Native C++工程,需要提前准备一个mp4文件,命名为test.mp4,将test.mp4放到main/resources/rawfile下。 main/ets/pages/index.ets ```ts import testNapi from 'libentry.so'; import { webview } from '@kit.ArkWeb'; import { resourceManager } from '@kit.LocalizationKit'; @Entry @Component struct Index { mycontroller: webview.WebviewController = new webview.WebviewController("scheme-handler"); build() { Row() { Column() { Button("goback").onClick( event => { this.mycontroller.backward(); }) Web({ src: $rawfile("test.html"), controller: this.mycontroller}) .javaScriptAccess(true) .width('100%') .height('100%') .databaseAccess(true) .fileAccess(false) .domStorageAccess(true) .cacheMode(CacheMode.Default) .onPageBegin( event => { testNapi.initResourceManager(getContext().resourceManager); }) } .width('100%') } .height('100%') } } ``` main/ets/entryability/EntryAbility.ets ```ts import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; import { window } from '@kit.ArkUI'; import testNapi from 'libentry.so'; import { webview } from '@kit.ArkWeb'; export default class EntryAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { // 注册三方协议的配置。 testNapi.registerCustomSchemes(); // 初始化Web组件内核,该操作会初始化Browser进程以及创建BrowserContext。 webview.WebviewController.initializeWebEngine(); // 设置SchemeHandler。 testNapi.setSchemeHandler(); } onDestroy(): void { } onWindowStageCreate(windowStage: window.WindowStage): void { windowStage.loadContent('pages/Index', (err, data) => { if (err.code) { return; } }); } onWindowStageDestroy(): void { } onForeground(): void { } onBackground(): void { } }; ``` main/cpp/hello.cpp ```c++ #include "hilog/log.h" #include "napi/native_api.h" #include "rawfile_request.h" #include "rawfile/raw_file_manager.h" #include "web/arkweb_scheme_handler.h" #include "web/arkweb_net_error_list.h" #undef LOG_TAG #define LOG_TAG "ss-handler" ArkWeb_SchemeHandler *g_schemeHandler; ArkWeb_SchemeHandler *g_schemeHandlerForSW; NativeResourceManager *g_resourceManager; // 注册三方协议的配置,需要在Web内核初始化之前调用,否则会注册失败。 static napi_value RegisterCustomSchemes(napi_env env, napi_callback_info info) { OH_LOG_INFO(LOG_APP, "register custom schemes"); OH_ArkWeb_RegisterCustomSchemes("custom", ARKWEB_SCHEME_OPTION_STANDARD | ARKWEB_SCHEME_OPTION_CORS_ENABLED); OH_ArkWeb_RegisterCustomSchemes("custom-local", ARKWEB_SCHEME_OPTION_LOCAL); OH_ArkWeb_RegisterCustomSchemes("custom-csp-bypassing", ARKWEB_SCHEME_OPTION_CSP_BYPASSING | ARKWEB_SCHEME_OPTION_STANDARD); OH_ArkWeb_RegisterCustomSchemes("custom-isolated", ARKWEB_SCHEME_OPTION_DISPLAY_ISOLATED); return nullptr; } // 请求开始的回调,在该函数中我们创建一个RawfileRequest来实现对Web内核请求的拦截。 void OnURLRequestStart(const ArkWeb_SchemeHandler *schemeHandler, ArkWeb_ResourceRequest *resourceRequest, const ArkWeb_ResourceHandler *resourceHandler, bool *intercept) { *intercept = true; RawfileRequest* request = new RawfileRequest(resourceRequest, resourceHandler, g_resourceManager); OH_ArkWebResourceRequest_SetUserData(resourceRequest, request); request->Start(); } // 请求结束的回调,在该函数中我们需要标记RawfileRequest已经结束了,内部不应该再使用ResourceHandler。 void OnURLRequestStop(const ArkWeb_SchemeHandler *schemeHandler, const ArkWeb_ResourceRequest *request) { if (!request) { OH_LOG_ERROR(LOG_APP, "on request stop request is nullptr."); return; } RawfileRequest *rawfileRequest = (RawfileRequest *)OH_ArkWebResourceRequest_GetUserData(request); if (rawfileRequest) { rawfileRequest->Stop(); } } void OnURLRequestStartForSW(const ArkWeb_SchemeHandler *schemeHandler, ArkWeb_ResourceRequest *resourceRequest, const ArkWeb_ResourceHandler *resourceHandler, bool *intercept) { *intercept = true; RawfileRequest* request = new RawfileRequest(resourceRequest, resourceHandler, g_resourceManager); OH_ArkWebResourceRequest_SetUserData(resourceRequest, request); request->Start(); } void OnURLRequestStopForSW(const ArkWeb_SchemeHandler *schemeHandler, const ArkWeb_ResourceRequest *request) { if (!request) { OH_LOG_ERROR(LOG_APP, "on request stop request is nullptr."); return; } RawfileRequest *rawfileRequest = (RawfileRequest *)OH_ArkWebResourceRequest_GetUserData(request); if (rawfileRequest) { rawfileRequest->Stop(); } } // 设置SchemeHandler。 static napi_value SetSchemeHandler(napi_env env, napi_callback_info info) { OH_LOG_INFO(LOG_APP, "set scheme handler"); OH_ArkWeb_CreateSchemeHandler(&g_schemeHandler); OH_ArkWeb_CreateSchemeHandler(&g_schemeHandlerForSW); OH_ArkWebSchemeHandler_SetOnRequestStart(g_schemeHandler, OnURLRequestStart); OH_ArkWebSchemeHandler_SetOnRequestStop(g_schemeHandler, OnURLRequestStop); OH_ArkWebSchemeHandler_SetOnRequestStart(g_schemeHandlerForSW, OnURLRequestStart); OH_ArkWebSchemeHandler_SetOnRequestStop(g_schemeHandlerForSW, OnURLRequestStop); OH_ArkWeb_SetSchemeHandler("custom", "scheme-handler", g_schemeHandler); OH_ArkWeb_SetSchemeHandler("custom-csp-bypassing", "scheme-handler", g_schemeHandler); OH_ArkWeb_SetSchemeHandler("custom-isolated", "scheme-handler", g_schemeHandler); OH_ArkWeb_SetSchemeHandler("custom-local", "scheme-handler", g_schemeHandler); OH_ArkWeb_SetSchemeHandler("https", "scheme-handler", g_schemeHandler); OH_ArkWeb_SetSchemeHandler("http", "scheme-handler", g_schemeHandler); OH_ArkWebServiceWorker_SetSchemeHandler("https", g_schemeHandlerForSW); return nullptr; } static napi_value InitResourceManager(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value argv[2] = {nullptr}; napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); g_resourceManager = OH_ResourceManager_InitNativeResourceManager(env, argv[0]); return nullptr; } EXTERN_C_START static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor desc[] = { {"setSchemeHandler", nullptr, SetSchemeHandler, nullptr, nullptr, nullptr, napi_default, nullptr}, {"initResourceManager", nullptr, InitResourceManager, nullptr, nullptr, nullptr, napi_default, nullptr}, {"registerCustomSchemes", nullptr, RegisterCustomSchemes, nullptr, nullptr, nullptr, napi_default, nullptr} }; napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); return exports; } EXTERN_C_END static napi_module demoModule = { .nm_version = 1, .nm_flags = 0, .nm_filename = nullptr, .nm_register_func = Init, .nm_modname = "entry", .nm_priv = ((void*)0), .reserved = { 0 }, }; extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); } ``` main/cpp/CMakeLists.txt ```text # the minimum version of CMake. cmake_minimum_required(VERSION 3.4.1) project(schemehandler) set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) if(DEFINED PACKAGE_INFO_FILE) include(${PACKAGE_INFO_FILE}) endif() include_directories(${NATIVERENDER_ROOT_PATH} ${NATIVERENDER_ROOT_PATH}/include) add_library(entry SHARED rawfile_request.cpp hello.cpp) target_link_libraries(entry PUBLIC librawfile.z.so libace_napi.z.so libohweb.so libhilog_ndk.z.so) ``` main/cpp/types/index.d.ts ```ts export const registerCustomSchemes: () => void; export const setSchemeHandler: () => void; export const initResourceManager: (resmgr: resourceManager.ResourceManager) => void; ``` main/cpp/rawfile_request.h ```c++ #ifndef RAWFILE_REQUEST_H #define RAWFILE_REQUEST_H #include #include #include #include "web/arkweb_scheme_handler.h" #include "web/arkweb_net_error_list.h" class RawfileRequest { public: RawfileRequest(const ArkWeb_ResourceRequest *resourceRequest, const ArkWeb_ResourceHandler *resourceHandler, const NativeResourceManager* resourceManager); ~RawfileRequest(); void Start(); void Stop(); void ReadRawfileDataOnWorkerThread(); const ArkWeb_ResourceHandler *resourceHandler() { return resourceHandler_; } const ArkWeb_ResourceRequest *resourceRequest() { return resourceRequest_; } const NativeResourceManager *resourceManager() { return resourceManager_; } ArkWeb_Response *response() { return response_; } ArkWeb_HttpBodyStream *stream() { return stream_; } const std::string rawfilePath() { return rawfilePath_; } void DidReceiveResponse(); void DidReceiveData(const uint8_t *buffer, int64_t bufLen); void DidFinish(); void DidFailWithError(ArkWeb_NetError errorCode); private: const ArkWeb_ResourceRequest *resourceRequest_{nullptr}; const ArkWeb_ResourceHandler *resourceHandler_{nullptr}; const NativeResourceManager *resourceManager_{nullptr}; ArkWeb_Response *response_; bool stopped_{false}; std::string rawfilePath_; ArkWeb_HttpBodyStream *stream_{nullptr}; std::mutex mutex_; }; #endif // RAWFILE_REQUEST_H ``` main/cpp/rawfile_request.cpp ```c++ #include "rawfile_request.h" #include "threads.h" #include "hilog/log.h" #include "rawfile/raw_file.h" #include "rawfile/raw_file_manager.h" #undef LOG_TAG #define LOG_TAG "ss-handler" namespace { uint8_t buffer[1024]; cnd_t http_body_cnd; mtx_t http_body_mtx; // HttpBodyStream的读回调。 void ReadCallback(const ArkWeb_HttpBodyStream *httpBodyStream, uint8_t* buffer, int bytesRead) { OH_LOG_INFO(LOG_APP, "read http body back."); bool isEof = OH_ArkWebHttpBodyStream_IsEof(httpBodyStream); if (!isEof && bytesRead != 0) { memset(buffer, 0, 1000); OH_ArkWebHttpBodyStream_Read(httpBodyStream, buffer, 1000); } else { RawfileRequest *rawfileRequest = (RawfileRequest *)OH_ArkWebHttpBodyStream_GetUserData(httpBodyStream); if (rawfileRequest) { rawfileRequest->ReadRawfileDataOnWorkerThread(); cnd_signal(&http_body_cnd); } } } int ReadHttpBodyOnWorkerThread(void* userData) { memset(buffer, 0, 1000); ArkWeb_HttpBodyStream *httpBodyStream = (ArkWeb_HttpBodyStream *)userData; OH_ArkWebHttpBodyStream_Read(httpBodyStream, buffer, 1000); cnd_init(&http_body_cnd); mtx_init(&http_body_mtx, mtx_plain); cnd_wait(&http_body_cnd, &http_body_mtx); return 0; } int ReadRawfileOnWorkerThread(void* userData) { RawfileRequest * rawfileRequest = (RawfileRequest *)userData; if (rawfileRequest) { rawfileRequest->ReadRawfileDataOnWorkerThread(); } return 0; } // ArkWeb_HttpBodyStream的初始化回调。 void InitCallback(const ArkWeb_HttpBodyStream *httpBodyStream, ArkWeb_NetError result) { OH_LOG_INFO(LOG_APP, "init http body stream done %{public}d.", result); bool isChunked = OH_ArkWebHttpBodyStream_IsChunked(httpBodyStream); OH_LOG_INFO(LOG_APP, "http body stream is chunked %{public}d.", isChunked); thrd_t th; if (thrd_create(&th, ReadHttpBodyOnWorkerThread, (void *)httpBodyStream) != thrd_success) { OH_LOG_ERROR(LOG_APP, "create thread failed."); return; } if (thrd_detach(th) != thrd_success) { OH_LOG_ERROR(LOG_APP, "detach thread failed."); } } const int blockSize = 1024 * 8; } // namespace RawfileRequest::RawfileRequest(const ArkWeb_ResourceRequest *resourceRequest, const ArkWeb_ResourceHandler *resourceHandler, const NativeResourceManager* resourceManager) : resourceRequest_(resourceRequest), resourceHandler_(resourceHandler), resourceManager_(resourceManager) {} RawfileRequest::~RawfileRequest() {} void RawfileRequest::Start() { OH_LOG_INFO(LOG_APP, "start a rawfile request."); char* url; OH_ArkWebResourceRequest_GetUrl(resourceRequest_, &url); std::string urlStr(url); std::size_t position = urlStr.rfind('/'); if (position != std::string::npos) { rawfilePath_ = urlStr.substr(position + 1); } OH_ArkWeb_ReleaseString(url); OH_ArkWeb_CreateResponse(&response_); OH_ArkWebResourceRequest_GetHttpBodyStream(resourceRequest(), &stream_); if (stream_) { OH_LOG_ERROR(LOG_APP, "have http body stream"); OH_ArkWebHttpBodyStream_SetUserData(stream_, this); OH_ArkWebHttpBodyStream_SetReadCallback(stream_, ReadCallback); OH_ArkWebHttpBodyStream_Init(stream_, InitCallback); } else { thrd_t th; if (thrd_create(&th, ReadRawfileOnWorkerThread, (void *)this) != thrd_success) { OH_LOG_ERROR(LOG_APP, "create thread failed."); return; } if (thrd_detach(th) != thrd_success) { OH_LOG_ERROR(LOG_APP, "detach thread failed."); } } } // 在worker线程中读取rawfile,并通过ResourceHandler返回给Web内核。 void RawfileRequest::ReadRawfileDataOnWorkerThread() { OH_LOG_INFO(LOG_APP, "read rawfile in worker thread."); const struct UrlInfo { std::string resource; std::string mimeType; } urlInfos[] = { {"test.html", "text/html"}, {"video.html", "text/html"}, {"isolated.html", "text/html"}, {"csp_bypassing.html", "text/html"}, {"post_data.html", "text/html"}, {"chunked_post_stream.html", "text/html"}, {"local.html", "text/html"}, {"service_worker.html", "text/html"}, {"csp_script.js", "text/javascript"}, {"sw.js", "text/javascript"}, {"isolated_script.js", "text/javascript"}, {"local_script.js", "text/javascript"}, {"test.mp4", "video/mp4"}, {"xhr", "application/json"} }; if (!resourceManager()) { OH_LOG_ERROR(LOG_APP, "read rawfile error, resource manager is nullptr."); return; } RawFile *rawfile = OH_ResourceManager_OpenRawFile(resourceManager(), rawfilePath().c_str()); if (!rawfile) { OH_ArkWebResponse_SetStatus(response(), 404); } else { OH_ArkWebResponse_SetStatus(response(), 200); } for (auto &urlInfo : urlInfos) { if (urlInfo.resource == rawfilePath()) { OH_ArkWebResponse_SetMimeType(response(), urlInfo.mimeType.c_str()); break; } } OH_ArkWebResponse_SetCharset(response(), "UTF-8"); long len = OH_ResourceManager_GetRawFileSize(rawfile); OH_ArkWebResponse_SetHeaderByName(response(), "content-length", std::to_string(len).c_str(), false); DidReceiveResponse(); long consumed = 0; uint8_t buffer[blockSize]; while (true) { int ret = OH_ResourceManager_ReadRawFile(rawfile, buffer, blockSize); OH_LOG_INFO(LOG_APP, "read rawfile %{public}d bytes.", ret); if (ret == 0) { break; } consumed += ret; OH_ResourceManager_SeekRawFile(rawfile, consumed, 0); DidReceiveData(buffer, ret); memset(buffer, 0, blockSize); } OH_ResourceManager_CloseRawFile(rawfile); DidFinish(); } void RawfileRequest::Stop() { OH_LOG_INFO(LOG_APP, "stop the rawfile request."); std::lock_guard guard(mutex_); stopped_ = true; if (response_) { OH_ArkWeb_DestroyResponse(response_); } OH_ArkWebResourceRequest_Destroy(resourceRequest_); OH_ArkWebResourceHandler_Destroy(resourceHandler_); } void RawfileRequest::DidReceiveResponse() { OH_LOG_INFO(LOG_APP, "did receive response."); std::lock_guard guard(mutex_); if (!stopped_) { OH_ArkWebResourceHandler_DidReceiveResponse(resourceHandler_, response_); } } void RawfileRequest::DidReceiveData(const uint8_t *buffer, int64_t bufLen) { OH_LOG_INFO(LOG_APP, "did receive data."); std::lock_guard guard(mutex_); if (!stopped_) { OH_ArkWebResourceHandler_DidReceiveData(resourceHandler_, buffer, bufLen); } } void RawfileRequest::DidFinish() { OH_LOG_INFO(LOG_APP, "did finish."); std::lock_guard guard(mutex_); if (!stopped_) { OH_ArkWebResourceHandler_DidFinish(resourceHandler_); } } void RawfileRequest::DidFailWithError(ArkWeb_NetError errorCode) { OH_LOG_INFO(LOG_APP, "did finish with error %{public}d.", errorCode); if (!stopped_) { OH_ArkWebResourceHandler_DidFailWithError(resourceHandler_, errorCode); } } ``` main/resources/rawfile/test.html ```html

网络拦截测试demo

拦截视频资源请求,读取本地mp4文件
测试三方协议忽略csp检查,并成功拦截
测试拦截设置ISOLATED属性的三方协议
测试拦截设置LOCAL属性的三方协议
测试拦截service worker触发的请求
测试读取blob类型http body stream
测试读取chunked类型http body stream ``` main/resources/rawfile/cat.svg ``` ``` main/resources/rawfile/csp_bypassing.html ```html

scheme: custom-csp-bypassing

options: ARKWEB_SCHEME_OPTION_CSP_BYPASSING | ARKWEB_SCHEME_OPTION_STANDARD

``` main/resources/rawfile/csp_script.js ```js const body = document.body; const element = document.createElement('div'); element.textContent = 'csp_script.js bypass the csp rules'; body.appendChild(element); ``` main/resources/rawfile/isolated_script.js ```js const element = document.getElementById('isolated_test'); element.textContent = 'isolated_script.js not blocked'; ``` main/resources/rawfile/isolated.html ```html

scheme: custom-isolated

options: ARKWEB_SCHEME_OPTION_DISPLAY_ISOLATED

isolated_script.js 被拦截
``` main/resources/rawfile/local_script.js ```js const element = document.getElementById('local_test'); element.textContent = 'local_script.js not blocked.'; ``` main/resources/rawfile/local.html ```html

scheme: custom-local

options: ARKWEB_SCHEME_OPTION_LOCAL

local_script.js 被拦截
``` main/resources/rawfile/post_data.html ```html
test xhr post
test xhr put
``` main/resources/rawfile/service_worker.html ```html ``` main/resources/rawfile/sw.js ```js self.addEventListener('install', event => { console.log('v1 installing'); event.waitUntil( caches.open('static-v1').then(cache => cache.add('/cat.svg')) ); }); self.addEventListener('activate', event => { console.log("v1 now redy to handle fetches."); }); ``` main/resources/rawfile/video.html ```html ``` main/resources/rawfile/chunked_post_stream.html ```html
test post chunked http body.
``` main/resources/rawfile/xhr ``` {} ```