通过 网络拦截接口 对Web组件发出的请求进行拦截,并可以为被拦截的请求提供自定义的响应头以及响应体。
为Web组件设置网络拦截器
为指定的Web组件或者ServiceWorker设置ArkWeb_SchemeHandler,当Web内核发出相应scheme请求的时候,会触发ArkWeb_SchemeHandler的回调。需要在Web组件初始化之后设置网络拦截器。
当请求开始的时候会回调ArkWeb_OnRequestStart,请求结束的时候会回调ArkWeb_OnRequestStop。
如果想要拦截Web组件发出的第一个请求,可以通过 initializeWebEngine 对Web组件提前进行初始化,然后设置拦截器进行拦截。
// 创建一个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);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
也可以拦截非Web组件内置scheme的请求。
// 创建一个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);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
设置自定义scheme需要遵循的规则
如果要拦截自定义scheme的请求,需要提前将自定义scheme注册到Web内核。需要在Web组件初始化之前进行注册,Web组件初始化后再注册会失败。
// 注册“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);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
由于注册scheme需要在Web组件初始化之前进行注册,而网络拦截器需要在Web组件初始化之后设置,建议在EntryAbility的onCreate中调用c++接口注册scheme。
scheme注册完毕后,通过 initializeWebEngine 对Web组件进行初始化,初始化完成后再设置网络拦截器。
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();
}
...
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
获取被拦截请求的请求信息
通过OH_ArkWebResourceRequest_*接口获取被拦截请求的信息。可以获取url、method、referrer、headers、resourceType等信息。
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);
...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
支持获取PUT/POST类请求的上传数据。数据类型支持BYTES、FILE、BLOB和CHUNKED。
// 获取被拦截请求的上传数据。
OH_ArkWebResourceRequest_GetHttpBodyStream(resourceRequest(), &stream_);
// 设置读取上传数据的读回调。
OH_ArkWebHttpBodyStream_SetReadCallback(stream_, ReadCallback);
// 初始化ArkWeb_HttpBodyStream,其它OH_ArkWebHttpBodyStream*函数需要在初始化进行调用。
OH_ArkWebHttpBodyStream_Init(stream_, InitCallback);
- 1
- 2
- 3
- 4
- 5
- 6
为被拦截的请求提供自定义的响应体
Web组件的网络拦截支持在worker线程以流的方式为被拦截的请求提供自定义的响应体。也可以以特定的 网络错误码 结束当前被拦截的请求。
// 为被拦截的请求创建一个响应头。
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);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
完整示例
使用DevEco Studio创建一个默认的Native C++工程,需要提前准备一个mp4文件,命名为test.mp4,将test.mp4放到main/resources/rawfile下。
main/ets/pages/index.ets
import testNapi from 'libentry.so';
import { webview } from '@kit.ArkWeb';
import { resourceManager } from '@kit.LocalizationKit';
@Entry
@Component
struct Index {
mycontroller: web_webview.WebviewController = new web_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%')
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
main/ets/entryability/EntryAbility.ets
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 {
}
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
main/cpp/hello.cpp
#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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
main/cpp/CMakeLists.txt
# 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)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
main/cpp/types/index.d.ts
export const registerCustomSchemes: () => void;
export const setSchemeHandler: () => void;
export const initResourceManager: (resmgr: resourceManager.ResourceManager) => void;
- 1
- 2
- 3
main/cpp/rawfile_request.h
#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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
main/cpp/rawfile_request.cpp
#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);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
main/resources/rawfile/test.html
网络拦截测试demo
拦截视频资源请求,读取本地mp4文件
测试三方协议忽略csp检查,并成功拦截
测试拦截设置ISOLATED属性的三方协议
测试拦截设置LOCAL属性的三方协议
测试拦截service worker触发的请求
测试读取blob类型http body stream
测试读取chunked类型http body stream
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
main/resources/rawfile/cat.svg
- 1
main/resources/rawfile/csp_bypassing.html
scheme: custom-csp-bypassing
options: ARKWEB_SCHEME_OPTION_CSP_BYPASSING | ARKWEB_SCHEME_OPTION_STANDARD
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
main/resources/rawfile/csp_script.js
const body = document.body;
const element = document.createElement('div');
element.textContent = 'csp_script.js bypass the csp rules';
body.appendChild(element);
- 1
- 2
- 3
- 4
main/resources/rawfile/isolated_script.js
const element = document.getElementById('isolated_test');
element.textContent = 'isolated_script.js not blocked';
- 1
- 2
main/resources/rawfile/isolated.html
scheme: custom-isolated
options: ARKWEB_SCHEME_OPTION_DISPLAY_ISOLATED
isolated_script.js 被拦截
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
main/resources/rawfile/local_script.js
const element = document.getElementById('local_test');
element.textContent = 'local_script.js not blocked.';
- 1
- 2
main/resources/rawfile/local.html
scheme: custom-local
options: ARKWEB_SCHEME_OPTION_LOCAL
local_script.js 被拦截
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
main/resources/rawfile/post_data.html
test xhr post
test xhr put
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
main/resources/rawfile/service_worker.html
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
main/resources/rawfile/sw.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.");
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
main/resources/rawfile/video.html
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
main/resources/rawfile/chunked_post_stream.html
test post chunked http body.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
main/resources/rawfile/xhr
{}
- 1
总是还有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以要有一份实用的鸿蒙(HarmonyOS NEXT)学习路线与学习文档用来跟着学习是非常有必要的。
针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。
本路线共分为四个阶段:
第一阶段:鸿蒙初中级开发必备技能
第二阶段:鸿蒙南北双向高工技能基础:gitee.com/MNxiaona/733GH
第三阶段:应用开发中高级就业技术
第四阶段:全网首发-工业级南向设备开发就业技术:gitee.com/MNxiaona/733GH
《鸿蒙 (Harmony OS)开发学习手册》(共计892页)
如何快速入门?
1.基本概念
2.构建第一个ArkTS应用
3.……
开发基础知识:gitee.com/MNxiaona/733GH
1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……
基于ArkTS 开发
1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……
鸿蒙开发面试真题(含参考答案):gitee.com/MNxiaona/733GH
鸿蒙入门教学视频:
美团APP实战开发教学:gitee.com/MNxiaona/733GH
写在最后
- 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing?,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:
gitee.com/MNxiaona/733GH



评论记录:
回复评论: