diff --git a/frameworks/js/napi/BUILD.gn b/frameworks/js/napi/BUILD.gn index 177afae0a3863434615832ffaf7fff79270aa151..c1a8986e49c4f8298ecc9c645ddcf668aca4194d 100644 --- a/frameworks/js/napi/BUILD.gn +++ b/frameworks/js/napi/BUILD.gn @@ -108,7 +108,6 @@ ohos_shared_library("http") { ] external_deps = common_external_deps - defines = [ "USE_CACHE=1" ] relative_install_dir = common_relative_install_dir part_name = common_part_name diff --git a/frameworks/js/napi/fetch/async_context/include/fetch_context.h b/frameworks/js/napi/fetch/async_context/include/fetch_context.h index a187aca7cb11cffa095b5a9d0dcc7a7d48f3dcc8..f087dc1755c67856aa1044679c7b5825aa86afcc 100644 --- a/frameworks/js/napi/fetch/async_context/include/fetch_context.h +++ b/frameworks/js/napi/fetch/async_context/include/fetch_context.h @@ -30,7 +30,7 @@ public: explicit FetchContext(napi_env env, EventManager *manager); - void ParseParams(napi_value *params, size_t paramsCount); + void ParseParams(napi_value *params, size_t paramsCount) override; [[nodiscard]] napi_value GetSuccessCallback() const; diff --git a/frameworks/js/napi/http/async_context/include/request_context.h b/frameworks/js/napi/http/async_context/include/request_context.h index c8f0754a2753fabc8f661dea94e131daa1807abe..ac9ccec4a29e97b35f76796b54ef039d56ccf553 100644 --- a/frameworks/js/napi/http/async_context/include/request_context.h +++ b/frameworks/js/napi/http/async_context/include/request_context.h @@ -28,15 +28,19 @@ public: RequestContext() = delete; - explicit RequestContext(napi_env env, EventManager *manager); + RequestContext(napi_env env, EventManager *manager); - void ParseParams(napi_value *params, size_t paramsCount); + void ParseParams(napi_value *params, size_t paramsCount) override; HttpRequestOptions options; HttpResponse response; + [[nodiscard]] bool IsUsingCache() const; + private: + bool usingCache_; + bool CheckParamsType(napi_value *params, size_t paramsCount); void ParseNumberOptions(napi_value optionsValue); diff --git a/frameworks/js/napi/http/async_context/src/request_context.cpp b/frameworks/js/napi/http/async_context/src/request_context.cpp index 040518ec0a4142400d0a1ac885424f8fb07cc1d5..218f40c5e5e12f37914d0d8b225192561764500f 100644 --- a/frameworks/js/napi/http/async_context/src/request_context.cpp +++ b/frameworks/js/napi/http/async_context/src/request_context.cpp @@ -30,7 +30,7 @@ static constexpr const int PARAM_URL_AND_OPTIONS_OR_CALLBACK = 2; static constexpr const int PARAM_URL_AND_OPTIONS_AND_CALLBACK = 3; namespace OHOS::NetStack { -RequestContext::RequestContext(napi_env env, EventManager *manager) : BaseContext(env, manager) {} +RequestContext::RequestContext(napi_env env, EventManager *manager) : BaseContext(env, manager), usingCache_(true) {} void RequestContext::ParseParams(napi_value *params, size_t paramsCount) { @@ -101,6 +101,13 @@ void RequestContext::ParseNumberOptions(napi_value optionsValue) options.SetConnectTimeout(HttpConstant::DEFAULT_CONNECT_TIMEOUT); } + if (NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_USING_CACHE)) { + napi_value value = NapiUtils::GetNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_USING_CACHE); + if (NapiUtils::GetValueType(GetEnv(), value) == napi_boolean) { + usingCache_ = NapiUtils::GetBooleanFromValue(GetEnv(), value); + } + } + if (NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_USING_PROTOCOL)) { napi_value value = NapiUtils::GetNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_USING_PROTOCOL); if (NapiUtils::GetValueType(GetEnv(), value) == napi_number) { @@ -243,4 +250,9 @@ void RequestContext::UrlAndOptions(napi_value urlValue, napi_value optionsValue) SetParseOK(ParseExtraData(optionsValue)); } + +bool RequestContext::IsUsingCache() const +{ + return usingCache_; +} } // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/http/async_work/include/http_async_work.h b/frameworks/js/napi/http/async_work/include/http_async_work.h index 01b974de0117124ce3632331f20d75b630692c3a..c1e59f323e351627447af1bf55cbb897e1cff754 100644 --- a/frameworks/js/napi/http/async_work/include/http_async_work.h +++ b/frameworks/js/napi/http/async_work/include/http_async_work.h @@ -29,6 +29,14 @@ public: static void ExecRequest(napi_env env, void *data); static void RequestCallback(napi_env env, napi_status status, void *data); + + static void ExecFlush(napi_env env, void *data); + + static void FlushCallback(napi_env env, napi_status status, void *data); + + static void ExecDelete(napi_env env, void *data); + + static void DeleteCallback(napi_env env, napi_status status, void *data); }; } // namespace OHOS::NetStack diff --git a/frameworks/js/napi/http/async_work/src/http_async_work.cpp b/frameworks/js/napi/http/async_work/src/http_async_work.cpp index 64b18a616d6d95534c72b9baf37b495f155a80f6..e89df42c9de44ea05839fd57f495bc322d47b0eb 100644 --- a/frameworks/js/napi/http/async_work/src/http_async_work.cpp +++ b/frameworks/js/napi/http/async_work/src/http_async_work.cpp @@ -29,4 +29,24 @@ void HttpAsyncWork::RequestCallback(napi_env env, napi_status status, void *data { BaseAsyncWork::AsyncWorkCallback(env, status, data); } + +void HttpAsyncWork::ExecFlush(napi_env env, void *data) +{ + BaseAsyncWork::ExecAsyncWork(env, data); +} + +void HttpAsyncWork::FlushCallback(napi_env env, napi_status status, void *data) +{ + BaseAsyncWork::AsyncWorkCallback(env, status, data); +} + +void HttpAsyncWork::ExecDelete(napi_env env, void *data) +{ + BaseAsyncWork::ExecAsyncWork(env, data); +} + +void HttpAsyncWork::DeleteCallback(napi_env env, napi_status status, void *data) +{ + BaseAsyncWork::AsyncWorkCallback(env, status, data); +} } // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/http/cache/cache_proxy/include/cache_proxy.h b/frameworks/js/napi/http/cache/cache_proxy/include/cache_proxy.h index 02d5a48b3775bc3622c01730670d6bce9b881d21..8ad7741e8eea7246afad2d51c73403fab6062061 100644 --- a/frameworks/js/napi/http/cache/cache_proxy/include/cache_proxy.h +++ b/frameworks/js/napi/http/cache/cache_proxy/include/cache_proxy.h @@ -29,9 +29,9 @@ class CacheProxy final { HttpCacheStrategy strategy_; - std::string MakeKey(); - public: + std::string key_; + CacheProxy() = delete; explicit CacheProxy(HttpRequestOptions &requestOptions); @@ -39,6 +39,14 @@ public: bool ReadResponseFromCache(HttpResponse &response); void WriteResponseToCache(const HttpResponse &response); + + static void RunCacheWithSize(size_t capacity); + + static void RunCache(); + + static void FlushCache(); + + static void StopCacheAndDelete(); }; } // namespace OHOS::NetStack #endif // COMMUNICATIONNETSTACK_CACHE_PROXY_H diff --git a/frameworks/js/napi/http/cache/cache_proxy/src/cache_proxy.cpp b/frameworks/js/napi/http/cache/cache_proxy/src/cache_proxy.cpp index a85275aaef9aae07a9abfde6f0571d1311a4d286..ec7f2ea38e9b21e0fc392aff3d9d79a1d186372b 100644 --- a/frameworks/js/napi/http/cache/cache_proxy/src/cache_proxy.cpp +++ b/frameworks/js/napi/http/cache/cache_proxy/src/cache_proxy.cpp @@ -13,50 +13,57 @@ * limitations under the License. */ +#include +#include +#include +#include + #include "base64_utils.h" #include "calculate_md5.h" #include "constant.h" -#if USE_CACHE #include "http_exec.h" -#endif #include "lru_cache_disk_handler.h" #include "netstack_common_utils.h" -#if USE_CACHE #include "netstack_log.h" #include "request_context.h" -#endif #include "cache_proxy.h" -static constexpr const char *CACHE_FILE = "/data/storage/el2/base/cache.json"; +static constexpr const char *CACHE_FILE = "/data/storage/el2/base/cache/cache.json"; +static constexpr const int WRITE_INTERVAL = 60; namespace OHOS::NetStack { -static LRUCacheDiskHandler DISK_LRU_CACHE(CACHE_FILE, MAX_DISK_CACHE_SIZE); // NOLINT(cert-err58-cpp) +std::mutex DISK_CACHE_MUTEX; +std::mutex CACHE_NEED_RUN_MUTEX; +std::atomic_bool CACHE_NEED_RUN(false); +std::atomic_bool CACHE_IS_RUNNING(false); +std::condition_variable CACHE_THREAD_CONDITION; +std::condition_variable CACHE_NEED_RUN_CONDITION; +static LRUCacheDiskHandler DISK_LRU_CACHE(CACHE_FILE, 0); // NOLINT(cert-err58-cpp) CacheProxy::CacheProxy(HttpRequestOptions &requestOptions) : requestOptions_(requestOptions), strategy_(requestOptions) { -} - -std::string CacheProxy::MakeKey() -{ - std::string str = requestOptions_.GetUrl() + HttpConstant::HTTP_LINE_SEPARATOR + - CommonUtils::ToLower(requestOptions_.GetMethod()) + HttpConstant::HTTP_LINE_SEPARATOR; - for (const auto &p : requestOptions_.GetHeader()) { + std::string str = requestOptions.GetUrl() + HttpConstant::HTTP_LINE_SEPARATOR + + CommonUtils::ToLower(requestOptions.GetMethod()) + HttpConstant::HTTP_LINE_SEPARATOR; + for (const auto &p : requestOptions.GetHeader()) { str += p.first + HttpConstant::HTTP_HEADER_SEPARATOR + p.second + HttpConstant::HTTP_LINE_SEPARATOR; } - str += std::to_string(requestOptions_.GetHttpVersion()); - return CalculateMD5(str); + str += std::to_string(requestOptions.GetHttpVersion()); + key_ = CalculateMD5(str); } bool CacheProxy::ReadResponseFromCache(HttpResponse &response) { -#if USE_CACHE + if (!CACHE_IS_RUNNING.load()) { + return false; + } + if (!strategy_.CouldUseCache()) { NETSTACK_LOGI("only GET/HEAD method or header has [Range] can use cache"); return false; } - auto responseFromCache = DISK_LRU_CACHE.Get(MakeKey()); + auto responseFromCache = DISK_LRU_CACHE.Get(key_); if (responseFromCache.empty()) { NETSTACK_LOGI("no cache with this request"); return false; @@ -66,6 +73,7 @@ bool CacheProxy::ReadResponseFromCache(HttpResponse &response) cachedResponse.SetResult(Base64::Decode(responseFromCache[HttpConstant::RESPONSE_KEY_RESULT])); cachedResponse.SetCookies(Base64::Decode(responseFromCache[HttpConstant::RESPONSE_KEY_COOKIES])); cachedResponse.SetResponseTime(Base64::Decode(responseFromCache[HttpConstant::RESPONSE_TIME])); + cachedResponse.SetRequestTime(Base64::Decode(responseFromCache[HttpConstant::REQUEST_TIME])); cachedResponse.SetResponseCode(static_cast(ResponseCode::OK)); cachedResponse.ParseHeaders(); @@ -79,7 +87,7 @@ bool CacheProxy::ReadResponseFromCache(HttpResponse &response) NETSTACK_LOGI("cache is STATE, we try to talk to the server"); RequestContext context(nullptr, nullptr); context.options = requestOptions_; - HttpExec::ExecRequest(&context); + HttpExec::RequestWithoutCache(&context); if (context.response.GetResponseCode() == static_cast(ResponseCode::NOT_MODIFIED)) { NETSTACK_LOGI("cache is NOT_MODIFIED, we use the cache"); response = cachedResponse; @@ -92,14 +100,14 @@ bool CacheProxy::ReadResponseFromCache(HttpResponse &response) } NETSTACK_LOGI("cache should not be used"); return false; -#else - return false; -#endif } void CacheProxy::WriteResponseToCache(const HttpResponse &response) { -#if USE_CACHE + if (!CACHE_IS_RUNNING.load()) { + return; + } + if (!strategy_.IsCacheable(response)) { NETSTACK_LOGI("do not cache this response"); return; @@ -109,8 +117,60 @@ void CacheProxy::WriteResponseToCache(const HttpResponse &response) cacheResponse[HttpConstant::RESPONSE_KEY_RESULT] = Base64::Encode(response.GetResult()); cacheResponse[HttpConstant::RESPONSE_KEY_COOKIES] = Base64::Encode(response.GetCookies()); cacheResponse[HttpConstant::RESPONSE_TIME] = Base64::Encode(response.GetResponseTime()); + cacheResponse[HttpConstant::REQUEST_TIME] = Base64::Encode(response.GetRequestTime()); + + DISK_LRU_CACHE.Put(key_, cacheResponse); +} + +void CacheProxy::RunCache() +{ + RunCacheWithSize(MAX_DISK_CACHE_SIZE); +} + +void CacheProxy::RunCacheWithSize(size_t capacity) +{ + if (CACHE_IS_RUNNING.load()) { + return; + } + DISK_LRU_CACHE.SetCapacity(capacity); + + CACHE_NEED_RUN.store(true); + // 从磁盘中读取缓存到内存里 + DISK_LRU_CACHE.ReadCacheFromJsonFile(); + // 起线程每一分钟将内存缓存持久化 + std::thread([]() { + CACHE_IS_RUNNING.store(true); + while (CACHE_NEED_RUN.load()) { + std::unique_lock lock(CACHE_NEED_RUN_MUTEX); + CACHE_NEED_RUN_CONDITION.wait_for(lock, std::chrono::seconds(WRITE_INTERVAL), + [] { return !CACHE_NEED_RUN.load(); }); + + DISK_LRU_CACHE.WriteCacheToJsonFile(); + } + + CACHE_IS_RUNNING.store(false); + CACHE_THREAD_CONDITION.notify_all(); + }).detach(); +} + +void CacheProxy::FlushCache() +{ + if (!CACHE_IS_RUNNING.load()) { + return; + } + DISK_LRU_CACHE.WriteCacheToJsonFile(); +} + +void CacheProxy::StopCacheAndDelete() +{ + if (!CACHE_IS_RUNNING.load()) { + return; + } + CACHE_NEED_RUN.store(false); + CACHE_NEED_RUN_CONDITION.notify_all(); - DISK_LRU_CACHE.Put(MakeKey(), cacheResponse); -#endif + std::unique_lock lock(DISK_CACHE_MUTEX); + CACHE_THREAD_CONDITION.wait(lock, [] { return !CACHE_IS_RUNNING.load(); }); + DISK_LRU_CACHE.Delete(); } } // namespace OHOS::NetStack diff --git a/frameworks/js/napi/http/cache/cache_strategy/include/http_cache_response.h b/frameworks/js/napi/http/cache/cache_strategy/include/http_cache_response.h index d441ffc27b5ac8f5e04b1daa4779db5f01f3ca63..3901b256ae1ed16a9126905ed16d98fc0ead0f64 100644 --- a/frameworks/js/napi/http/cache/cache_strategy/include/http_cache_response.h +++ b/frameworks/js/napi/http/cache/cache_strategy/include/http_cache_response.h @@ -74,6 +74,10 @@ public: void SetResponseTime(const std::string &responseTime); + void SetRequestTime(const std::string &requestTime); + + [[nodiscard]] time_t GetRequestTime() const; + private: void ParseCacheControl(const std::string &cacheControl); @@ -83,6 +87,7 @@ private: std::string etag_; std::string age_; std::string responseTime_; + std::string requestTime_; bool mustRevalidate_; bool noCache_; diff --git a/frameworks/js/napi/http/cache/cache_strategy/include/http_cache_strategy.h b/frameworks/js/napi/http/cache/cache_strategy/include/http_cache_strategy.h index 8185371b3883973b6e9296dbfef571ad69ea5603..07f1569e3a042724528ba465ee42d3df50e1f679 100644 --- a/frameworks/js/napi/http/cache/cache_strategy/include/http_cache_strategy.h +++ b/frameworks/js/napi/http/cache/cache_strategy/include/http_cache_strategy.h @@ -49,16 +49,14 @@ private: bool IsCacheable(const HttpCacheResponse &cacheResponse); - int64_t CacheResponseAgeMillis(int64_t sReqTime, - int64_t sRespTime, - int64_t nowTime, - int64_t sRespDate, - int64_t responseAge); + int64_t CacheResponseAgeMillis(); std::tuple GetFreshness(); int64_t ComputeFreshnessLifetimeMillis(); + int64_t ComputeFreshnessLifetimeSecondsInternal(); + void UpdateRequestHeader(const std::string &etag, const std::string &lastModified, const std::string &date); HttpRequestOptions &requestOptions_; diff --git a/frameworks/js/napi/http/cache/cache_strategy/src/http_cache_request.cpp b/frameworks/js/napi/http/cache/cache_strategy/src/http_cache_request.cpp index 6bb9601044dd30592061764ff288ede96d31e803..1c3dea8ce1ea78c9bfe1893f714e3543d3b2deec 100644 --- a/frameworks/js/napi/http/cache/cache_strategy/src/http_cache_request.cpp +++ b/frameworks/js/napi/http/cache/cache_strategy/src/http_cache_request.cpp @@ -22,8 +22,6 @@ namespace OHOS::NetStack { void HttpCacheRequest::ParseCacheControl(const std::string &cacheControl) { - NETSTACK_LOGI("--- ParseCacheControl start ---"); - auto vec = CommonUtils::Split(cacheControl, SPLIT); for (const auto &str : vec) { if (str == NO_CACHE) { @@ -48,14 +46,10 @@ void HttpCacheRequest::ParseCacheControl(const std::string &cacheControl) } } } - - NETSTACK_LOGI("--- ParseCacheControl end ---"); } void HttpCacheRequest::ParseRequestHeader(const std::map &requestHeader) { - NETSTACK_LOGI("--- HttpCacheRequest start ---"); - if (requestHeader.empty()) { return; } @@ -72,8 +66,6 @@ void HttpCacheRequest::ParseRequestHeader(const std::map &cacheResponseHeader) { - NETSTACK_LOGI("--- HttpCacheResponse start ---"); - if (cacheResponseHeader.empty()) { return; } @@ -82,8 +76,6 @@ void HttpCacheResponse::ParseCacheResponseHeader(const std::map(response.GetResponseCode())); cacheResponse_.SetResponseTime(response.GetResponseTime()); + cacheResponse_.SetRequestTime(response.GetRequestTime()); return RunStrategyInternal(response); } @@ -64,88 +65,120 @@ bool HttpCacheStrategy::IsCacheable(const HttpResponse &response) return IsCacheable(tempCacheResponse); } -int64_t HttpCacheStrategy::CacheResponseAgeMillis(int64_t sReqTime, - int64_t sRespTime, - int64_t nowTime, - int64_t sRespDate, - int64_t responseAge) +int64_t HttpCacheStrategy::CacheResponseAgeMillis() { - int64_t apparentReceivedAge = 0; + // 4.2.3. Calculating Age - if (sRespDate != INVALID_TIME) { - apparentReceivedAge = std::max(0, sRespTime - sRespDate); - } + /* The following data is used for the age calculation: - int64_t receivedAge = apparentReceivedAge; - if (responseAge != INVALID_TIME) { - receivedAge = std::max(apparentReceivedAge, responseAge); - } + age_value + The term "age_value" denotes the value of the Age header field (Section 5.1), in a form appropriate for arithmetic + operation; or 0, if not available. - int64_t responseDuration = sRespTime - sReqTime; + date_value + The term "date_value" denotes the value of the Date header field, in a form appropriate for arithmetic operations. + See Section 7.1.1.2 of [RFC7231] for the definition of the Date header field, and for requirements regarding + responses without it. - int64_t residentDuration = nowTime - sRespTime; + now + The term "now" means "the current value of the clock at the host performing the calculation". A host ought to use + NTP ([RFC5905]) or some similar protocol to synchronize its clocks to Coordinated Universal Time. - return (receivedAge + responseDuration + residentDuration) * CONVERT_TO_MILLISECONDS; -} + request_time + The current value of the clock at the host at the time the request resulting in the stored response was made. -int64_t HttpCacheStrategy::ComputeFreshnessLifetimeMillis() -{ - NETSTACK_LOGI("--- ComputeFreshnessLifetimeMillis start ---"); + response_time + The current value of the clock at the host at the time the response was received. + A response's age can be calculated in two entirely independent ways: - int64_t maxAge = cacheResponse_.GetMaxAgeSeconds(); - int64_t sMaxAge = cacheResponse_.GetSMaxAgeSeconds(); + the "apparent_age": response_time minus date_value, if the local clock is reasonably well synchronized to the origin + server's clock. If the result is negative, the result is replaced by zero. the "corrected_age_value", if all of the + caches along the response path implement HTTP/1.1. A cache MUST interpret this value relative to the time the + request was initiated, not the time that the response was received. apparent_age = max(0, response_time - + date_value); + + response_delay = response_time - request_time; + corrected_age_value = age_value + response_delay; + These are combined as + + corrected_initial_age = max(apparent_age, corrected_age_value); + unless the cache is confident in the value of the Age header field (e.g., because there are no HTTP/1.0 hops in the + Via header field), in which case the corrected_age_value MAY be used as the corrected_initial_age. + + The current_age of a stored response can then be calculated by adding the amount of time (in seconds) since the + stored response was last validated by the origin server to the corrected_initial_age. - NETSTACK_LOGI("maxAge=%{public}lld", static_cast(maxAge)); + resident_time = now - response_time; + current_age = corrected_initial_age + resident_time; */ - int64_t lifeTime = 0; + int64_t age = std::max(0, cacheResponse_.GetAgeSeconds()); + int64_t dateTime = std::max(0, cacheResponse_.GetDate()); + int64_t nowTime = std::max(0, HttpTime::GetNowTimeSeconds()); + int64_t requestTime = std::max(0, cacheResponse_.GetRequestTime()); + int64_t responseTime = std::max(0, cacheResponse_.GetResponseTime()); + NETSTACK_LOGI("CacheResponseAgeMillis: %{public}lld, %{public}lld, %{public}lld, %{public}lld, %{public}lld", + static_cast(age), static_cast(dateTime), static_cast(nowTime), + static_cast(requestTime), static_cast(responseTime)); + + int64_t apparentAge = std::max(0, responseTime - dateTime); + int64_t responseDelay = std::max(0, responseTime - requestTime); + int64_t correctedAgeValue = age + responseDelay; + int64_t correctedInitialAge = std::max(apparentAge, correctedAgeValue); + + int64_t residentTime = std::max(0, nowTime - responseTime); + + return (correctedInitialAge + residentTime) * CONVERT_TO_MILLISECONDS; +} + +int64_t HttpCacheStrategy::ComputeFreshnessLifetimeSecondsInternal() +{ + int64_t sMaxAge = cacheResponse_.GetSMaxAgeSeconds(); if (sMaxAge != INVALID_TIME) { // If the cache is shared and the s-maxage response directive (Section 5.2.2.9) is present, use its value - lifeTime = sMaxAge; - } else if (maxAge != INVALID_TIME) { + return sMaxAge; + } + + int64_t maxAge = cacheResponse_.GetMaxAgeSeconds(); + if (maxAge != INVALID_TIME) { // If the max-age response directive (Section 5.2.2.8) is present, use its value - NETSTACK_LOGI("--- ComputeFreshnessLifetimeMillis end ---"); - lifeTime = maxAge; - } else if (cacheResponse_.GetExpires() != INVALID_TIME) { + return maxAge; + } + + if (cacheResponse_.GetExpires() != INVALID_TIME) { // If the Expires response header field (Section 5.3) is present, use its value minus the value of the Date // response header field - int64_t servedMillis; + int64_t responseTime = cacheResponse_.GetResponseTime(); if (cacheResponse_.GetDate() != INVALID_TIME) { - servedMillis = cacheResponse_.GetDate(); - } else { - servedMillis = cacheResponse_.GetResponseTime(); - NETSTACK_LOGI("servedMillis=%{public}lld", static_cast(servedMillis)); + responseTime = cacheResponse_.GetDate(); } - NETSTACK_LOGI("getExpiresSeconds=%{public}lld", static_cast(cacheResponse_.GetExpires())); - int64_t delta = cacheResponse_.GetExpires() - servedMillis; - - NETSTACK_LOGI("delta=%{public}lld", static_cast(delta)); + int64_t delta = cacheResponse_.GetExpires() - responseTime; + return std::max(delta, 0); + } - NETSTACK_LOGI("--- ComputeFreshnessLifetimeMillis end ---"); - lifeTime = std::max(delta, 0); - } else if (cacheResponse_.GetLastModified() != INVALID_TIME) { + if (cacheResponse_.GetLastModified() != INVALID_TIME) { // 4.2.2. Calculating Heuristic Freshness - int64_t servedMillis; + int64_t requestTime = cacheRequest_.GetRequestTime(); if (cacheResponse_.GetDate() != INVALID_TIME) { - servedMillis = cacheResponse_.GetDate(); - } else { - servedMillis = cacheRequest_.GetRequestTime(); + requestTime = cacheResponse_.GetDate(); } - int64_t delta = servedMillis - cacheResponse_.GetLastModified(); + int64_t delta = requestTime - cacheResponse_.GetLastModified(); + return std::max(delta / DECIMAL, 0); + } - NETSTACK_LOGI("delta=%{public}lld", static_cast(delta)); + return 0; +} - NETSTACK_LOGI("--- ComputeFreshnessLifetimeMillis end ---"); - lifeTime = std::max(delta / DECIMAL, 0); - } +int64_t HttpCacheStrategy::ComputeFreshnessLifetimeMillis() +{ + int64_t lifeTime = ComputeFreshnessLifetimeSecondsInternal(); int64_t reqMaxAge = cacheRequest_.GetMaxAgeSeconds(); if (reqMaxAge != INVALID_TIME) { lifeTime = std::min(lifeTime, reqMaxAge); } - NETSTACK_LOGI("lifeTime=%{public}lld", static_cast(lifeTime)); - NETSTACK_LOGI("--- ComputeFreshnessLifetimeMillis end ---"); + NETSTACK_LOGI("lifeTime=%{public}lld", static_cast(lifeTime)); return lifeTime * CONVERT_TO_MILLISECONDS; } @@ -153,8 +186,6 @@ void HttpCacheStrategy::UpdateRequestHeader(const std::string &etag, const std::string &lastModified, const std::string &date) { - NETSTACK_LOGI("--- UpdateRequestHeader start ---"); - if (!etag.empty()) { requestOptions_.SetHeader(IF_NONE_MATCH, etag); } else if (!lastModified.empty()) { @@ -196,42 +227,30 @@ bool HttpCacheStrategy::IsCacheable(const HttpCacheResponse &cacheResponse) std::tuple HttpCacheStrategy::GetFreshness() { - int64_t ageMillis = - CacheResponseAgeMillis(cacheRequest_.GetRequestTime(), cacheResponse_.GetResponseTime(), - HttpTime::GetNowTimeSeconds(), cacheResponse_.GetDate(), cacheResponse_.GetAgeSeconds()); + int64_t ageMillis = CacheResponseAgeMillis(); int64_t lifeTime = ComputeFreshnessLifetimeMillis(); - int64_t minFreshMillis = 0; - minFreshMillis = cacheRequest_.GetMinFreshSeconds(); - if (minFreshMillis != INVALID_TIME) { - minFreshMillis *= CONVERT_TO_MILLISECONDS; - } + int64_t minFreshMillis = std::max(0, cacheRequest_.GetMinFreshSeconds() * CONVERT_TO_MILLISECONDS); + int64_t maxStaleMillis = 0; if (!cacheResponse_.IsMustRevalidate()) { - maxStaleMillis = cacheRequest_.GetMaxStaleSeconds(); + maxStaleMillis = std::max(0, cacheRequest_.GetMaxStaleSeconds() * CONVERT_TO_MILLISECONDS); } - if (maxStaleMillis != INVALID_TIME) { - maxStaleMillis *= CONVERT_TO_MILLISECONDS; - } - NETSTACK_LOGI("%{public}lld, %{public}lld, %{public}lld, %{public}lld", static_cast(ageMillis), - static_cast(minFreshMillis), static_cast(lifeTime), - static_cast(maxStaleMillis)); + NETSTACK_LOGI("GetFreshness: %{public}lld, %{public}lld, %{public}lld, %{public}lld", + static_cast(ageMillis), static_cast(minFreshMillis), + static_cast(lifeTime), static_cast(maxStaleMillis)); return {ageMillis, minFreshMillis, lifeTime, maxStaleMillis}; } CacheStatus HttpCacheStrategy::RunStrategyInternal(HttpResponse &response) { - NETSTACK_LOGI("request nocache = %{public}d", cacheRequest_.IsNoCache()); - if (cacheRequest_.IsNoCache()) { NETSTACK_LOGI("return DENY"); return DENY; } - NETSTACK_LOGI("response nocache = %{public}d", cacheResponse_.IsNoCache()); - if (cacheResponse_.IsNoCache()) { NETSTACK_LOGI("return STALE"); return STALE; @@ -255,18 +274,16 @@ CacheStatus HttpCacheStrategy::RunStrategyInternal(HttpResponse &response) auto [ageMillis, minFreshMillis, lifeTime, maxStaleMillis] = GetFreshness(); - NETSTACK_LOGI("nocache:%{public}d", cacheResponse_.IsNoCache()); if (ageMillis + minFreshMillis < lifeTime + maxStaleMillis) { if (ageMillis + minFreshMillis >= lifeTime) { - NETSTACK_LOGI("110 HttpURLConnection"); response.SetWarning("110 \"Response is STALE\""); } if (ageMillis > ONE_DAY_MILLISECONDS && cacheRequest_.GetMaxAgeSeconds() == INVALID_TIME && cacheResponse_.GetExpires() == INVALID_TIME) { - NETSTACK_LOGI("113 HttpURLConnection"); response.SetWarning("113 \"Heuristic expiration\""); } + NETSTACK_LOGI("return FRESH"); return FRESH; } @@ -274,7 +291,7 @@ CacheStatus HttpCacheStrategy::RunStrategyInternal(HttpResponse &response) // The cache has expired and the request needs to be re-initialized UpdateRequestHeader(cacheResponse_.GetEtag(), cacheResponse_.GetLastModifiedStr(), cacheResponse_.GetDateStr()); - NETSTACK_LOGI("---IsCacheUseful end---"); + NETSTACK_LOGI("return STALE"); return STALE; } } // namespace OHOS::NetStack diff --git a/frameworks/js/napi/http/cache/lru_cache/include/disk_handler.h b/frameworks/js/napi/http/cache/lru_cache/include/disk_handler.h index 400813b44fd8d2d8fd99a5da199968230c431a9e..094c511d8666e69a213c1468ec06b79e0ef60af8 100644 --- a/frameworks/js/napi/http/cache/lru_cache/include/disk_handler.h +++ b/frameworks/js/napi/http/cache/lru_cache/include/disk_handler.h @@ -16,6 +16,7 @@ #ifndef COMMUNICATIONNETSTACK_DISK_HANDLER_H #define COMMUNICATIONNETSTACK_DISK_HANDLER_H +#include #include #include "nocopyable.h" @@ -25,15 +26,19 @@ class DiskHandler final { public: DiskHandler() = delete; - DiskHandler(std::string fileName); + explicit DiskHandler(std::string fileName); void Write(const std::string &str); + void Delete(); + [[nodiscard]] std::string Read(); private: DISALLOW_COPY_AND_MOVE(DiskHandler); + std::mutex mutex_; + std::string fileName_; }; } // namespace OHOS::NetStack diff --git a/frameworks/js/napi/http/cache/lru_cache/include/lru_cache_disk_handler.h b/frameworks/js/napi/http/cache/lru_cache/include/lru_cache_disk_handler.h index f188cc6451559091f9b24b3eaf93aabf9c020c33..fe0edcb6824dc5fdb7549d01b6e82e48daf2e422 100644 --- a/frameworks/js/napi/http/cache/lru_cache/include/lru_cache_disk_handler.h +++ b/frameworks/js/napi/http/cache/lru_cache/include/lru_cache_disk_handler.h @@ -16,11 +16,14 @@ #ifndef COMMUNICATIONNETSTACK_LRU_CACHE_DISK_HANDLER_H #define COMMUNICATIONNETSTACK_LRU_CACHE_DISK_HANDLER_H +#include + #include "disk_handler.h" #include "lru_cache.h" #include "nocopyable.h" -static constexpr const int MAX_DISK_CACHE_SIZE = 1024 * 1024 * 5; +static constexpr const int MAX_DISK_CACHE_SIZE = 1024 * 1024 * 10; +static constexpr const int MIN_DISK_CACHE_SIZE = 1024 * 1024; namespace OHOS::NetStack { class LRUCacheDiskHandler { @@ -33,6 +36,10 @@ public: void ReadCacheFromJsonFile(); + void Delete(); + + void SetCapacity(size_t capacity); + std::unordered_map Get(const std::string &key); void Put(const std::string &key, const std::unordered_map &value); @@ -40,7 +47,7 @@ public: private: LRUCache cache_; DiskHandler diskHandler_; - size_t capacity_; + std::atomic capacity_; Json::Value ReadJsonValueFromFile(); diff --git a/frameworks/js/napi/http/cache/lru_cache/src/disk_handler.cpp b/frameworks/js/napi/http/cache/lru_cache/src/disk_handler.cpp index 8bbc76d58571571b7ac8324659dfde8b07f344fc..387e59f884dd64a50ac7890910b490c8867f9588 100644 --- a/frameworks/js/napi/http/cache/lru_cache/src/disk_handler.cpp +++ b/frameworks/js/napi/http/cache/lru_cache/src/disk_handler.cpp @@ -13,73 +13,45 @@ * limitations under the License. */ -#include "disk_handler.h" +#include +#include + #include "netstack_log.h" -#include -#include -#include -#include -#include -#include +#include "disk_handler.h" namespace OHOS::NetStack { DiskHandler::DiskHandler(std::string fileName) : fileName_(std::move(fileName)) {} void DiskHandler::Write(const std::string &str) { - int fd = open(fileName_.c_str(), O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR); - if (fd < 0) { - NETSTACK_LOGE("errmsg: Write open [%{public}d] %{public}s|\n", errno, strerror(errno)); + std::lock_guard guard(mutex_); + std::ofstream w(fileName_); + if (!w.is_open()) { return; } - - int ret = flock(fd, LOCK_NB | LOCK_EX); - if (ret < 0) { - NETSTACK_LOGE("errmsg: Write open [%{public}d] %{public}s|\n", errno, strerror(errno)); - close(fd); - return; - } - - if (write(fd, str.c_str(), str.size()) < 0) { - NETSTACK_LOGE("errmsg: Write open [%{public}d] %{public}s|\n", errno, strerror(errno)); - } - - flock(fd, LOCK_UN); - close(fd); + w << str; + w.close(); } std::string DiskHandler::Read() { - int fd = open(fileName_.c_str(), O_RDONLY); - if (fd < 0) { - NETSTACK_LOGE("errmsg: Read open [%{public}d] %{public}s|\n", errno, strerror(errno)); - return {}; - } - - int ret = flock(fd, LOCK_NB | LOCK_EX); - if (ret < 0) { - NETSTACK_LOGE("errmsg: Read flock [%{public}d] %{public}s|\n", errno, strerror(errno)); - close(fd); - return {}; - } - - struct stat buf = {0}; - if (fstat(fd, &buf) < 0 || buf.st_size <= 0) { - flock(fd, LOCK_UN); - close(fd); + std::lock_guard guard(mutex_); + std::ifstream r(fileName_); + if (!r.is_open()) { return {}; } + std::stringstream b; + b << r.rdbuf(); + r.close(); + return b.str(); +} - std::unique_ptr mem(new char[buf.st_size]); - if (read(fd, mem.get(), buf.st_size) < 0) { - NETSTACK_LOGE("errmsg: Read read [%{public}d] %{public}s|\n", errno, strerror(errno)); +void DiskHandler::Delete() +{ + std::lock_guard guard(mutex_); + if (remove(fileName_.c_str()) < 0) { + NETSTACK_LOGI("remove file error %{public}d", errno); } - - flock(fd, LOCK_UN); - close(fd); - std::string str; - str.append(mem.get(), buf.st_size); - return str; } } // namespace OHOS::NetStack diff --git a/frameworks/js/napi/http/cache/lru_cache/src/lru_cache_disk_handler.cpp b/frameworks/js/napi/http/cache/lru_cache/src/lru_cache_disk_handler.cpp index 4ea48793c7253b73606716d8b2de868240032f7f..546b3e27de24da16a11b3325e2b866d9e81f2a65 100644 --- a/frameworks/js/napi/http/cache/lru_cache/src/lru_cache_disk_handler.cpp +++ b/frameworks/js/napi/http/cache/lru_cache/src/lru_cache_disk_handler.cpp @@ -13,33 +13,29 @@ * limitations under the License. */ -#if USE_CACHE #include -#endif #include "netstack_log.h" #include "lru_cache_disk_handler.h" -#if USE_CACHE -static constexpr const int WRITE_INTERVAL = 60 * 1000; -#endif - namespace OHOS::NetStack { LRUCacheDiskHandler::LRUCacheDiskHandler(std::string fileName, size_t capacity) - : diskHandler_(std::move(fileName)), capacity_(std::min(MAX_DISK_CACHE_SIZE, capacity)) + : diskHandler_(std::move(fileName)), + capacity_(std::max(std::min(MAX_DISK_CACHE_SIZE, capacity), MIN_DISK_CACHE_SIZE)) +{ +} + +void LRUCacheDiskHandler::SetCapacity(size_t capacity) { -#if USE_CACHE - // 从磁盘中读取缓存到内存里 - ReadCacheFromJsonFile(); - // 起线程每一分钟讲内存缓存持久化 - std::thread([this]() { - while (true) { - std::this_thread::sleep_for(std::chrono::milliseconds(WRITE_INTERVAL)); - WriteCacheToJsonFile(); - } - }).detach(); -#endif + capacity_ = std::max(std::min(MAX_DISK_CACHE_SIZE, capacity), MIN_DISK_CACHE_SIZE); + WriteCacheToJsonFile(); +} + +void LRUCacheDiskHandler::Delete() +{ + cache_.Clear(); + diskHandler_.Delete(); } Json::Value LRUCacheDiskHandler::ReadJsonValueFromFile() diff --git a/frameworks/js/napi/http/constant/include/constant.h b/frameworks/js/napi/http/constant/include/constant.h index 2d446a13754c8d194bdba37dfa7182049fff593c..405b92d908025291ee7a1e229697ca3f5c817938 100644 --- a/frameworks/js/napi/http/constant/include/constant.h +++ b/frameworks/js/napi/http/constant/include/constant.h @@ -84,6 +84,7 @@ public: static const char *const PARAM_KEY_READ_TIMEOUT; static const char *const PARAM_KEY_CONNECT_TIMEOUT; static const char *const PARAM_KEY_USING_PROTOCOL; + static const char *const PARAM_KEY_USING_CACHE; static const char *const RESPONSE_KEY_RESULT; static const char *const RESPONSE_KEY_RESPONSE_CODE; diff --git a/frameworks/js/napi/http/constant/src/constant.cpp b/frameworks/js/napi/http/constant/src/constant.cpp index 4af07af90181c942e5cac5150b725c0a192f6b01..4adef4be62d6dabf48ec219374562eaa7db73bc4 100644 --- a/frameworks/js/napi/http/constant/src/constant.cpp +++ b/frameworks/js/napi/http/constant/src/constant.cpp @@ -34,6 +34,7 @@ const char *const HttpConstant::PARAM_KEY_HEADER = "header"; const char *const HttpConstant::PARAM_KEY_READ_TIMEOUT = "readTimeout"; const char *const HttpConstant::PARAM_KEY_CONNECT_TIMEOUT = "connectTimeout"; const char *const HttpConstant::PARAM_KEY_USING_PROTOCOL = "usingProtocol"; +const char *const HttpConstant::PARAM_KEY_USING_CACHE = "usingCache"; const char *const HttpConstant::RESPONSE_KEY_RESULT = "result"; const char *const HttpConstant::RESPONSE_KEY_RESPONSE_CODE = "responseCode"; diff --git a/frameworks/js/napi/http/http_exec/include/http_exec.h b/frameworks/js/napi/http/http_exec/include/http_exec.h index 2af91c7218142c68e95ca7f2e2f05ca00cba29ed..61a313fb6941d72eff867c4d045ad4cce5f5706c 100644 --- a/frameworks/js/napi/http/http_exec/include/http_exec.h +++ b/frameworks/js/napi/http/http_exec/include/http_exec.h @@ -25,6 +25,23 @@ #include "request_context.h" namespace OHOS::NetStack { +class HttpResponseCacheExec final { +public: + DISALLOW_COPY_AND_MOVE(HttpResponseCacheExec); + + HttpResponseCacheExec() = default; + + ~HttpResponseCacheExec() = default; + + static bool ExecFlush(BaseContext *context); + + static napi_value FlushCallback(BaseContext *context); + + static bool ExecDelete(BaseContext *context); + + static napi_value DeleteCallback(BaseContext *context); +}; + class HttpExec final { public: DISALLOW_COPY_AND_MOVE(HttpExec); @@ -33,6 +50,8 @@ public: ~HttpExec() = default; + static bool RequestWithoutCache(RequestContext *context); + static bool ExecRequest(RequestContext *context); static napi_value RequestCallback(RequestContext *context); diff --git a/frameworks/js/napi/http/http_exec/src/http_exec.cpp b/frameworks/js/napi/http/http_exec/src/http_exec.cpp index 24c02df7849cc5fa06a8c792ebf8d31afba8968b..b41fa88fff87652a472baeee89c8c610224cc7ce 100644 --- a/frameworks/js/napi/http/http_exec/src/http_exec.cpp +++ b/frameworks/js/napi/http/http_exec/src/http_exec.cpp @@ -66,14 +66,8 @@ std::mutex HttpExec::mutex_; bool HttpExec::initialized_ = false; -bool HttpExec::ExecRequest(RequestContext *context) +bool HttpExec::RequestWithoutCache(RequestContext *context) { - context->options.SetRequestTime(HttpTime::GetNowTimeGMT()); - CacheProxy proxy(context->options); - if (proxy.ReadResponseFromCache(context->response)) { - return true; - } - if (!initialized_) { NETSTACK_LOGE("curl not init"); return false; @@ -100,6 +94,7 @@ bool HttpExec::ExecRequest(RequestContext *context) return false; } + context->response.SetRequestTime(HttpTime::GetNowTimeGMT()); NETSTACK_CURL_EASY_PERFORM(handle.get(), context); context->response.SetResponseTime(HttpTime::GetNowTimeGMT()); @@ -121,6 +116,22 @@ bool HttpExec::ExecRequest(RequestContext *context) context->response.SetResponseCode(responseCode); context->response.ParseHeaders(); + + return true; +} + +bool HttpExec::ExecRequest(RequestContext *context) +{ + context->options.SetRequestTime(HttpTime::GetNowTimeGMT()); + CacheProxy proxy(context->options); + if (context->IsUsingCache() && proxy.ReadResponseFromCache(context->response)) { + return true; + } + + if (!RequestWithoutCache(context)) { + return false; + } + proxy.WriteResponseToCache(context->response); return true; @@ -357,4 +368,28 @@ bool HttpExec::IsUnReserved(unsigned char in) } return false; } + +bool HttpResponseCacheExec::ExecFlush(BaseContext *context) +{ + (void)context; + CacheProxy::FlushCache(); + return true; +} + +napi_value HttpResponseCacheExec::FlushCallback(BaseContext *context) +{ + return NapiUtils::GetUndefined(context->GetEnv()); +} + +bool HttpResponseCacheExec::ExecDelete(BaseContext *context) +{ + (void)context; + CacheProxy::StopCacheAndDelete(); + return true; +} + +napi_value HttpResponseCacheExec::DeleteCallback(BaseContext *context) +{ + return NapiUtils::GetUndefined(context->GetEnv()); +} } // namespace OHOS::NetStack diff --git a/frameworks/js/napi/http/http_module/include/http_module.h b/frameworks/js/napi/http/http_module/include/http_module.h index 26e452768f25499bfd32b08f86c9862060c7458e..3a67e53955b73a255c00f5258e84fe2d80905441 100644 --- a/frameworks/js/napi/http/http_module/include/http_module.h +++ b/frameworks/js/napi/http/http_module/include/http_module.h @@ -21,6 +21,15 @@ namespace OHOS::NetStack { class HttpModuleExports { public: + class HttpResponseCache { + public: + static constexpr const char *FUNCTION_FLUSH = "flush"; + static constexpr const char *FUNCTION_DELETE = "delete"; + + static napi_value Flush(napi_env env, napi_callback_info info); + static napi_value Delete(napi_env env, napi_callback_info info); + }; + class HttpRequest { public: static constexpr const char *FUNCTION_REQUEST = "request"; @@ -37,18 +46,24 @@ public: }; static constexpr const char *FUNCTION_CREATE_HTTP = "createHttp"; + static constexpr const char *FUNCTION_CREATE_HTTP_RESPONSE_CACHE = "createHttpResponseCache"; static constexpr const char *INTERFACE_REQUEST_METHOD = "RequestMethod"; static constexpr const char *INTERFACE_RESPONSE_CODE = "ResponseCode"; static constexpr const char *INTERFACE_HTTP_REQUEST = "HttpRequest"; static constexpr const char *INTERFACE_HTTP_PROTOCOL = "HttpProtocol"; + static constexpr const char *INTERFACE_HTTP_RESPONSE_CACHE = "HttpResponseCache"; static napi_value InitHttpModule(napi_env env, napi_value exports); private: static napi_value CreateHttp(napi_env env, napi_callback_info info); + static napi_value CreateHttpResponseCache(napi_env env, napi_callback_info info); + static void DefineHttpRequestClass(napi_env env, napi_value exports); + static void DefineHttpResponseCacheClass(napi_env env, napi_value exports); + static void InitHttpProperties(napi_env env, napi_value exports); static void InitRequestMethod(napi_env env, napi_value exports); diff --git a/frameworks/js/napi/http/http_module/src/http_module.cpp b/frameworks/js/napi/http/http_module/src/http_module.cpp index c963de43add9b75a640653dd03db00595f1242a5..a32168ee11cdb317f853307d10619d8f0ddd2796 100644 --- a/frameworks/js/napi/http/http_module/src/http_module.cpp +++ b/frameworks/js/napi/http/http_module/src/http_module.cpp @@ -15,6 +15,7 @@ #include "http_module.h" +#include "cache_proxy.h" #include "constant.h" #include "event_list.h" #include "http_async_work.h" @@ -33,12 +34,17 @@ static constexpr const char *REQUEST_ASYNC_WORK_NAME = "ExecRequest"; +static constexpr const char *FLUSH_ASYNC_WORK_NAME = "ExecFlush"; + +static constexpr const char *DELETE_ASYNC_WORK_NAME = "ExecDelete"; + static constexpr const char *HTTP_MODULE_NAME = "net.http"; namespace OHOS::NetStack { napi_value HttpModuleExports::InitHttpModule(napi_env env, napi_value exports) { DefineHttpRequestClass(env, exports); + DefineHttpResponseCacheClass(env, exports); InitHttpProperties(env, exports); return exports; @@ -52,6 +58,24 @@ napi_value HttpModuleExports::CreateHttp(napi_env env, napi_callback_info info) }); } +napi_value HttpModuleExports::CreateHttpResponseCache(napi_env env, napi_callback_info info) +{ + napi_value thisVal = nullptr; + size_t paramsCount = MAX_PARAM_NUM; + napi_value params[MAX_PARAM_NUM] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr)); + if (paramsCount != 1 || NapiUtils::GetValueType(env, params[0]) != napi_number) { + CacheProxy::RunCache(); + } else { + size_t size = NapiUtils::GetUint32FromValue(env, params[0]); + CacheProxy::RunCacheWithSize(size); + } + + return ModuleTemplate::NewInstanceNoManager(env, info, INTERFACE_HTTP_RESPONSE_CACHE, [](napi_env, void *, void *) { + NETSTACK_LOGI("http response cache handle is finalized"); + }); +} + void HttpModuleExports::DefineHttpRequestClass(napi_env env, napi_value exports) { std::initializer_list properties = { @@ -64,10 +88,20 @@ void HttpModuleExports::DefineHttpRequestClass(napi_env env, napi_value exports) ModuleTemplate::DefineClass(env, exports, properties, INTERFACE_HTTP_REQUEST); } +void HttpModuleExports::DefineHttpResponseCacheClass(napi_env env, napi_value exports) +{ + std::initializer_list properties = { + DECLARE_NAPI_FUNCTION(HttpResponseCache::FUNCTION_FLUSH, HttpResponseCache::Flush), + DECLARE_NAPI_FUNCTION(HttpResponseCache::FUNCTION_DELETE, HttpResponseCache::Delete), + }; + ModuleTemplate::DefineClass(env, exports, properties, INTERFACE_HTTP_RESPONSE_CACHE); +} + void HttpModuleExports::InitHttpProperties(napi_env env, napi_value exports) { std::initializer_list properties = { DECLARE_NAPI_FUNCTION(FUNCTION_CREATE_HTTP, CreateHttp), + DECLARE_NAPI_FUNCTION(FUNCTION_CREATE_HTTP_RESPONSE_CACHE, CreateHttpResponseCache), }; NapiUtils::DefineProperties(env, exports, properties); @@ -183,6 +217,18 @@ napi_value HttpModuleExports::HttpRequest::Off(napi_env env, napi_callback_info return ModuleTemplate::Off(env, info, {ON_HEADER_RECEIVE}); } +napi_value HttpModuleExports::HttpResponseCache::Flush(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::Interface(env, info, FLUSH_ASYNC_WORK_NAME, nullptr, HttpAsyncWork::ExecFlush, + HttpAsyncWork::FlushCallback); +} + +napi_value HttpModuleExports::HttpResponseCache::Delete(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::Interface(env, info, DELETE_ASYNC_WORK_NAME, nullptr, HttpAsyncWork::ExecDelete, + HttpAsyncWork::DeleteCallback); +} + static napi_module g_httpModule = { .nm_version = 1, .nm_flags = 0, diff --git a/frameworks/js/napi/http/options/include/http_response.h b/frameworks/js/napi/http/options/include/http_response.h index bd32efd2278dd0f595ab888c5c4d216ba350ae47..464ff895c52422de5cfaa14444192bf0263796a2 100644 --- a/frameworks/js/napi/http/options/include/http_response.h +++ b/frameworks/js/napi/http/options/include/http_response.h @@ -56,6 +56,10 @@ public: [[nodiscard]] const std::string &GetResponseTime() const; + void SetRequestTime(const std::string &time); + + [[nodiscard]] const std::string &GetRequestTime() const; + void SetWarning(const std::string &val); private: @@ -70,6 +74,8 @@ private: std::string cookies_; std::string responseTime_; + + std::string requestTime_; }; } // namespace OHOS::NetStack diff --git a/frameworks/js/napi/http/options/src/http_response.cpp b/frameworks/js/napi/http/options/src/http_response.cpp index 738f94c4b5d51e4c2905bb6c91371bd6c520cd85..12253b64c523b30e7bb4f13e7839cb38f2ebdbb5 100644 --- a/frameworks/js/napi/http/options/src/http_response.cpp +++ b/frameworks/js/napi/http/options/src/http_response.cpp @@ -110,6 +110,16 @@ const std::string &HttpResponse::GetResponseTime() const return responseTime_; } +void HttpResponse::SetRequestTime(const std::string &time) +{ + requestTime_ = time; +} + +const std::string &HttpResponse::GetRequestTime() const +{ + return requestTime_; +} + void HttpResponse::SetWarning(const std::string &val) { header_[WARNING] = val; diff --git a/frameworks/js/napi/socket/async_context/include/bind_context.h b/frameworks/js/napi/socket/async_context/include/bind_context.h index 7c43029be6826fd065bc7a17877edc4a6f9a95b3..c66e5862df4ca66fdd92412163efc5b2cb08f413 100644 --- a/frameworks/js/napi/socket/async_context/include/bind_context.h +++ b/frameworks/js/napi/socket/async_context/include/bind_context.h @@ -30,7 +30,7 @@ public: explicit BindContext(napi_env env, EventManager *manager); - void ParseParams(napi_value *params, size_t paramsCount); + void ParseParams(napi_value *params, size_t paramsCount) override; [[nodiscard]] int GetSocketFd() const; diff --git a/frameworks/js/napi/socket/async_context/include/common_context.h b/frameworks/js/napi/socket/async_context/include/common_context.h index 8260aa8bf3b307783c3ca35ff631b30d49d5164d..42b40197c05f884e2068444d0f458c88385229ac 100644 --- a/frameworks/js/napi/socket/async_context/include/common_context.h +++ b/frameworks/js/napi/socket/async_context/include/common_context.h @@ -31,7 +31,7 @@ public: explicit CommonContext(napi_env env, EventManager *manager); - void ParseParams(napi_value *params, size_t paramsCount); + void ParseParams(napi_value *params, size_t paramsCount) override; [[nodiscard]] int GetSocketFd() const; diff --git a/frameworks/js/napi/socket/async_context/include/connect_context.h b/frameworks/js/napi/socket/async_context/include/connect_context.h index e2aa2ba77906ed4ed9324157fcdb4b89a77f248c..f880d1f03509175d25df3159a5ad53cef5222b3a 100644 --- a/frameworks/js/napi/socket/async_context/include/connect_context.h +++ b/frameworks/js/napi/socket/async_context/include/connect_context.h @@ -29,7 +29,7 @@ public: explicit ConnectContext(napi_env env, EventManager *manager); - void ParseParams(napi_value *params, size_t paramsCount); + void ParseParams(napi_value *params, size_t paramsCount) override; [[nodiscard]] int GetSocketFd() const; diff --git a/frameworks/js/napi/socket/async_context/include/tcp_extra_context.h b/frameworks/js/napi/socket/async_context/include/tcp_extra_context.h index ea63ca1b4d99af1a13f0c85c1de6829c876b4065..61ba477308867d92f7e3cfd9a930a5449ddb5d8a 100644 --- a/frameworks/js/napi/socket/async_context/include/tcp_extra_context.h +++ b/frameworks/js/napi/socket/async_context/include/tcp_extra_context.h @@ -29,7 +29,7 @@ public: explicit TcpSetExtraOptionsContext(napi_env env, EventManager *manager); - void ParseParams(napi_value *params, size_t paramsCount); + void ParseParams(napi_value *params, size_t paramsCount) override; [[nodiscard]] int GetSocketFd() const; diff --git a/frameworks/js/napi/socket/async_context/include/tcp_send_context.h b/frameworks/js/napi/socket/async_context/include/tcp_send_context.h index ec6f6faefa92d8c8d779b6f8bf8ebc62a2f1769d..ff810239987705f4ef33fac99b175bd0a2b7bf86 100644 --- a/frameworks/js/napi/socket/async_context/include/tcp_send_context.h +++ b/frameworks/js/napi/socket/async_context/include/tcp_send_context.h @@ -29,7 +29,7 @@ public: explicit TcpSendContext(napi_env env, EventManager *manager); - void ParseParams(napi_value *params, size_t paramsCount); + void ParseParams(napi_value *params, size_t paramsCount) override; [[nodiscard]] int GetSocketFd() const; diff --git a/frameworks/js/napi/socket/async_context/include/udp_extra_context.h b/frameworks/js/napi/socket/async_context/include/udp_extra_context.h index b0995644b1e02f8d7a417bae5435f4356eca15fc..99e958a85edb6d289cb1f872444fb7592befc459 100644 --- a/frameworks/js/napi/socket/async_context/include/udp_extra_context.h +++ b/frameworks/js/napi/socket/async_context/include/udp_extra_context.h @@ -29,7 +29,7 @@ public: explicit UdpSetExtraOptionsContext(napi_env env, EventManager *manager); - void ParseParams(napi_value *params, size_t paramsCount); + void ParseParams(napi_value *params, size_t paramsCount) override; [[nodiscard]] int GetSocketFd() const; diff --git a/frameworks/js/napi/socket/async_context/include/udp_send_context.h b/frameworks/js/napi/socket/async_context/include/udp_send_context.h index c8e3d1a15bbe38b94fd995f5aa946928ad0a2c54..661a0534fe73028af87771e55623bbe9abf919d2 100644 --- a/frameworks/js/napi/socket/async_context/include/udp_send_context.h +++ b/frameworks/js/napi/socket/async_context/include/udp_send_context.h @@ -29,7 +29,7 @@ public: explicit UdpSendContext(napi_env env, EventManager *manager); - void ParseParams(napi_value *params, size_t paramsCount); + void ParseParams(napi_value *params, size_t paramsCount) override; [[nodiscard]] int GetSocketFd() const; diff --git a/frameworks/js/napi/websocket/async_context/include/close_context.h b/frameworks/js/napi/websocket/async_context/include/close_context.h index 8baf8b14d4d3b088d9becc0f2f11ea76070225ca..3bb8253d8689589c1e696a763e2819118168d8f9 100644 --- a/frameworks/js/napi/websocket/async_context/include/close_context.h +++ b/frameworks/js/napi/websocket/async_context/include/close_context.h @@ -30,7 +30,7 @@ public: explicit CloseContext(napi_env env, EventManager *manager); - void ParseParams(napi_value *params, size_t paramsCount); + void ParseParams(napi_value *params, size_t paramsCount) override; uint32_t code; diff --git a/frameworks/js/napi/websocket/async_context/include/connect_context.h b/frameworks/js/napi/websocket/async_context/include/connect_context.h index 63733f6d802fa6df682b99010cb8c6e1f040174a..ddb0b08eea64c9c3b0770228b79cf3becc318b7c 100644 --- a/frameworks/js/napi/websocket/async_context/include/connect_context.h +++ b/frameworks/js/napi/websocket/async_context/include/connect_context.h @@ -34,7 +34,7 @@ public: ~ConnectContext() override; - void ParseParams(napi_value *params, size_t paramsCount); + void ParseParams(napi_value *params, size_t paramsCount) override; std::string url; diff --git a/frameworks/js/napi/websocket/async_context/include/send_context.h b/frameworks/js/napi/websocket/async_context/include/send_context.h index 4dcf4b08201cca3975b286941573b0585638688e..f054d282827065204df60a4d1b2848e008a9786e 100644 --- a/frameworks/js/napi/websocket/async_context/include/send_context.h +++ b/frameworks/js/napi/websocket/async_context/include/send_context.h @@ -31,7 +31,7 @@ public: explicit SendContext(napi_env env, EventManager *manager); - void ParseParams(napi_value *params, size_t paramsCount); + void ParseParams(napi_value *params, size_t paramsCount) override; void *data; diff --git a/test/napi/http/CMakeLists.txt b/test/napi/http/CMakeLists.txt index 39d0168817ff49f75f9f235a4f3cfda90fb84fd1..3b2cb3c192c5621846426bf3562decc4f0289a89 100644 --- a/test/napi/http/CMakeLists.txt +++ b/test/napi/http/CMakeLists.txt @@ -75,5 +75,4 @@ add_compile_definitions(NETSTACK_PROXY_URL_PORT="xxxx:xxxx") add_compile_definitions(NETSTACK_PROXY_TYPE=CURLPROXY_HTTP) add_compile_definitions(NETSTACK_PROXY_PASS="xxxx:xxxx") add_compile_definitions(SERVER_IP="x.x.x.x") -add_compile_definitions(USE_CACHE=1) set(CMAKE_CXX_FLAGS -g) diff --git a/test/unittest/http/cache/HttpCacheStrategyTest.cpp b/test/unittest/http/cache/HttpCacheStrategyTest.cpp index 123717f4340dbf1a8f73b79ce21754a1f5c20893..1f20f45bd34062f5b4fd43928a5ce112cefe847d 100644 --- a/test/unittest/http/cache/HttpCacheStrategyTest.cpp +++ b/test/unittest/http/cache/HttpCacheStrategyTest.cpp @@ -363,7 +363,7 @@ HWTEST_F(HttpCacheStrategyTest, CompareNumber_6, testing::ext::TestSize.Level1) CacheStatus status = cacheStrategy.RunStrategy(response); NETSTACK_LOGI("status = %{public}d", status); - EXPECT_EQ(status, 0); + EXPECT_EQ(status, STALE); } HWTEST_F(HttpCacheStrategyTest, CompareNumber_7, testing::ext::TestSize.Level1) @@ -384,7 +384,7 @@ HWTEST_F(HttpCacheStrategyTest, CompareNumber_7, testing::ext::TestSize.Level1) CacheStatus status = cacheStrategy.RunStrategy(response); NETSTACK_LOGI("status = %{public}d", status); - EXPECT_EQ(status, 0); + EXPECT_EQ(status, STALE); } HWTEST_F(HttpCacheStrategyTest, CompareNumber_8, testing::ext::TestSize.Level1) @@ -407,7 +407,7 @@ HWTEST_F(HttpCacheStrategyTest, CompareNumber_8, testing::ext::TestSize.Level1) CacheStatus status = cacheStrategy.RunStrategy(response); NETSTACK_LOGI("status = %{public}d", status); - EXPECT_EQ(status, 0); + EXPECT_EQ(status, STALE); } HWTEST_F(HttpCacheStrategyTest, CompareNumber_9, testing::ext::TestSize.Level1) diff --git a/utils/base_context/include/netstack_base_context.h b/utils/base_context/include/netstack_base_context.h index 24f617fa2b0b48219ce7430681ad34c0ed79e516..5b28e95e366e082c1fb42c8110d82a265ab78768 100644 --- a/utils/base_context/include/netstack_base_context.h +++ b/utils/base_context/include/netstack_base_context.h @@ -76,6 +76,8 @@ public: [[nodiscard]] EventManager *GetManager() const; + virtual void ParseParams(napi_value *params, size_t paramsCount); + protected: EventManager *manager_; diff --git a/utils/base_context/src/netstack_base_context.cpp b/utils/base_context/src/netstack_base_context.cpp index 20162d60320dc2419e93117e22a23c4082758f6e..cf84080925f4dcfe097c2b98ea8e8d1a6f2e6a9c 100644 --- a/utils/base_context/src/netstack_base_context.cpp +++ b/utils/base_context/src/netstack_base_context.cpp @@ -156,4 +156,21 @@ EventManager *BaseContext::GetManager() const { return manager_; } + +void BaseContext::ParseParams(napi_value *params, size_t paramsCount) +{ + if (paramsCount != 0 && paramsCount != 1) { + return; + } + + if (paramsCount == 1 && NapiUtils::GetValueType(env_, params[0]) != napi_function) { + return; + } + + if (paramsCount == 1) { + SetParseOK(SetCallback(params[0]) == napi_ok); + return; + } + SetParseOK(true); +} } // namespace OHOS::NetStack \ No newline at end of file diff --git a/utils/module_template/include/netstack_module_template.h b/utils/module_template/include/netstack_module_template.h index 3a3626f01a8966698c6d6733ce740575c6b7d264..ddf5db207c590524576cf31fa45cf85dec26cb53 100644 --- a/utils/module_template/include/netstack_module_template.h +++ b/utils/module_template/include/netstack_module_template.h @@ -104,5 +104,7 @@ void DefineClass(napi_env env, const std::string &className); napi_value NewInstance(napi_env env, napi_callback_info info, const std::string &className, Finalizer finalizer); + +napi_value NewInstanceNoManager(napi_env env, napi_callback_info info, const std::string &name, Finalizer finalizer); } // namespace OHOS::NetStack::ModuleTemplate #endif /* COMMUNICATIONNETSTACK_NETSTACK_MODULE_TEMPLATE_H */ diff --git a/utils/module_template/src/netstack_module_template.cpp b/utils/module_template/src/netstack_module_template.cpp index 3c4b6325054ce6edd72b8c8cdc66994abe7d396c..19722c259e03932139001be81efd68cfa6a3128b 100644 --- a/utils/module_template/src/netstack_module_template.cpp +++ b/utils/module_template/src/netstack_module_template.cpp @@ -154,4 +154,20 @@ napi_value NewInstance(napi_env env, napi_callback_info info, const std::string return result; } + +napi_value NewInstanceNoManager(napi_env env, napi_callback_info info, const std::string &name, Finalizer finalizer) +{ + napi_value thisVal = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVal, nullptr)); + + napi_value jsConstructor = NapiUtils::GetNamedProperty(env, thisVal, name); + if (NapiUtils::GetValueType(env, jsConstructor) == napi_undefined) { + return nullptr; + } + + napi_value result = nullptr; + NAPI_CALL(env, napi_new_instance(env, jsConstructor, 0, nullptr, &result)); + + return result; +} } // namespace OHOS::NetStack::ModuleTemplate \ No newline at end of file diff --git a/utils/napi_utils/include/netstack_napi_utils.h b/utils/napi_utils/include/netstack_napi_utils.h index 720eae3067e6ef80d2fa035d30971871012b8394..74e174c49c9c93a1f565a77e93b7fe6e43881c21 100644 --- a/utils/napi_utils/include/netstack_napi_utils.h +++ b/utils/napi_utils/include/netstack_napi_utils.h @@ -94,6 +94,8 @@ void SetBooleanProperty(napi_env env, napi_value object, const std::string &name napi_value GetBoolean(napi_env env, bool value); +bool GetBooleanFromValue(napi_env env, napi_value value); + /* define properties */ void DefineProperties(napi_env env, napi_value object, diff --git a/utils/napi_utils/src/netstack_napi_utils.cpp b/utils/napi_utils/src/netstack_napi_utils.cpp index 77abd6540eedbea087392866d4db28a6e9791506..b1708fa0682d8604b78718f670757bade0f71463 100644 --- a/utils/napi_utils/src/netstack_napi_utils.cpp +++ b/utils/napi_utils/src/netstack_napi_utils.cpp @@ -308,6 +308,13 @@ napi_value GetBoolean(napi_env env, bool value) return jsValue; } +bool GetBooleanFromValue(napi_env env, napi_value value) +{ + bool ret = false; + NAPI_CALL_BASE(env, napi_get_value_bool(env, value, &ret), false); + return ret; +} + /* define properties */ void DefineProperties(napi_env env, napi_value object,