diff --git a/frameworks/js/napi/http/BUILD.gn b/frameworks/js/napi/http/BUILD.gn index 3fd834027eb9a761033402ee2c4426e3b4637d6c..8005893d39eb3730bb0d7efc02ff362eaf51c9e5 100644 --- a/frameworks/js/napi/http/BUILD.gn +++ b/frameworks/js/napi/http/BUILD.gn @@ -85,6 +85,7 @@ ohos_shared_library("http") { external_deps = [ "c_utils:utils", "hiviewdfx_hilog_native:libhilog", + "init:libbegetutil", "napi:ace_napi", ] } 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 a13a24735ad9d5ef3d72e692ff2f6af98058393f..21b60482bddee6c603235ab609b877bf7ac4085b 100644 --- a/frameworks/js/napi/http/async_context/include/request_context.h +++ b/frameworks/js/napi/http/async_context/include/request_context.h @@ -63,6 +63,8 @@ private: bool ParseExtraData(napi_value optionsValue); + void ParseUsingHttpProxy(napi_value optionsValue); + bool GetRequestBody(napi_value extraData); void UrlAndOptions(napi_value urlValue, 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 f44d60ab3b1dd575542d8fffa9b74396fa9193c4..4473e1796a7e7b35d13e2f5d35d7adfaeb68be90 100644 --- a/frameworks/js/napi/http/async_context/src/request_context.cpp +++ b/frameworks/js/napi/http/async_context/src/request_context.cpp @@ -225,6 +225,44 @@ bool RequestContext::ParseExtraData(napi_value optionsValue) return false; } +void RequestContext::ParseUsingHttpProxy(napi_value optionsValue) +{ + if (!NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_USING_HTTP_PROXY)) { + NETSTACK_LOGI("Do not use http proxy"); + return; + } + napi_value httpProxyValue = + NapiUtils::GetNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_USING_HTTP_PROXY); + napi_valuetype type = NapiUtils::GetValueType(GetEnv(), httpProxyValue); + if (type == napi_boolean) { + bool usingProxy = NapiUtils::GetBooleanFromValue(GetEnv(), httpProxyValue); + UsingHttpProxyType usingType = usingProxy ? UsingHttpProxyType::USE_DEFAULT : UsingHttpProxyType::NOT_USE; + options.SetUsingHttpProxyType(usingType); + return; + } + if (type != napi_object) { + return; + } + std::string host = NapiUtils::GetStringPropertyUtf8(GetEnv(), httpProxyValue, HttpConstant::HTTP_PROXY_KEY_HOST); + int32_t port = NapiUtils::GetInt32Property(GetEnv(), httpProxyValue, HttpConstant::HTTP_PROXY_KEY_PORT); + std::string exclusionList; + if (NapiUtils::HasNamedProperty(GetEnv(), httpProxyValue, HttpConstant::HTTP_PROXY_KEY_EXCLUSION_LIST)) { + napi_value exclusionListValue = + NapiUtils::GetNamedProperty(GetEnv(), httpProxyValue, HttpConstant::HTTP_PROXY_KEY_EXCLUSION_LIST); + uint32_t listLength = NapiUtils::GetArrayLength(GetEnv(), exclusionListValue); + for (uint32_t index = 0; index < listLength; ++index) { + napi_value exclusionValue = NapiUtils::GetArrayElement(GetEnv(), exclusionListValue, index); + std::string exclusion = NapiUtils::GetStringFromValueUtf8(GetEnv(), exclusionValue); + if (index != 0) { + exclusionList = exclusionList + HttpConstant::HTTP_PROXY_EXCLUSIONS_SEPARATOR; + } + exclusionList += exclusion; + } + } + options.SetSpecifiedHttpProxy(host, port, exclusionList); + options.SetUsingHttpProxyType(UsingHttpProxyType::USE_SPECIFIED); +} + bool RequestContext::GetRequestBody(napi_value extraData) { /* if body is empty, return false, or curl will wait for body */ @@ -274,6 +312,7 @@ void RequestContext::UrlAndOptions(napi_value urlValue, napi_value optionsValue) ParseHeader(optionsValue); ParseNumberOptions(optionsValue); + ParseUsingHttpProxy(optionsValue); /* parse extra data here to recover header */ diff --git a/frameworks/js/napi/http/constant/include/constant.h b/frameworks/js/napi/http/constant/include/constant.h index 8f997196433d6e960ca2c28a7102dbdfcebbe5fd..01628cc6a18e7971d251507211599687f13f0f0a 100644 --- a/frameworks/js/napi/http/constant/include/constant.h +++ b/frameworks/js/napi/http/constant/include/constant.h @@ -105,6 +105,12 @@ public: static const char *const PARAM_KEY_USING_CACHE; static const char *const PARAM_KEY_EXPECT_DATA_TYPE; static const char *const PARAM_KEY_PRIORITY; + static const char *const PARAM_KEY_USING_HTTP_PROXY; + + static const char *const HTTP_PROXY_KEY_HOST; + static const char *const HTTP_PROXY_KEY_PORT; + static const char *const HTTP_PROXY_KEY_EXCLUSION_LIST; + static const char *const HTTP_PROXY_EXCLUSIONS_SEPARATOR; 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 d1fe54a989c049e6a95cf94676648337683430e6..5309bf8637539f32599d353c11abfd0861d2de25 100644 --- a/frameworks/js/napi/http/constant/src/constant.cpp +++ b/frameworks/js/napi/http/constant/src/constant.cpp @@ -39,6 +39,12 @@ const char *const HttpConstant::PARAM_KEY_USING_PROTOCOL = "usingProtocol"; const char *const HttpConstant::PARAM_KEY_USING_CACHE = "usingCache"; const char *const HttpConstant::PARAM_KEY_EXPECT_DATA_TYPE = "expectDataType"; const char *const HttpConstant::PARAM_KEY_PRIORITY = "priority"; +const char *const HttpConstant::PARAM_KEY_USING_HTTP_PROXY = "usingProxy"; + +const char *const HttpConstant::HTTP_PROXY_KEY_HOST = "host"; +const char *const HttpConstant::HTTP_PROXY_KEY_PORT = "port"; +const char *const HttpConstant::HTTP_PROXY_KEY_EXCLUSION_LIST = "parsedExclusionList"; +const char *const HttpConstant::HTTP_PROXY_EXCLUSIONS_SEPARATOR = ","; 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 b4f7533adabff513b63359d39837b3297821a1c2..9bb1f960317f226ea5af348f031018cb09987d43 100644 --- a/frameworks/js/napi/http/http_exec/include/http_exec.h +++ b/frameworks/js/napi/http/http_exec/include/http_exec.h @@ -103,6 +103,8 @@ private: static void ReadRespond(); + static void GetGlobalHttpProxyInfo(std::string &host, int32_t &port, std::string &exclusions); + struct StaticVariable { StaticVariable() : curlMulti(nullptr), initialized(false), runThread(true) {} 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 545e857c9c97f3bb489dd320df00a55be15c00ed..bb53faf4b3bb10dd91eeb5d4c2e82c0ed92592d8 100644 --- a/frameworks/js/napi/http/http_exec/src/http_exec.cpp +++ b/frameworks/js/napi/http/http_exec/src/http_exec.cpp @@ -19,6 +19,13 @@ #include #include +#ifndef WINDOWS_PLATFORM +#ifndef MAC_PLATFORM +#include "parameter.h" +#endif +#endif + +#include "base64_utils.h" #include "cache_proxy.h" #include "constant.h" #include "event_list.h" @@ -46,6 +53,13 @@ namespace OHOS::NetStack { static constexpr size_t MAX_LIMIT = 5 * 1024 * 1024; static constexpr int CURL_TIMEOUT_MS = 100; static constexpr int CURL_HANDLE_NUM = 10; +static constexpr int32_t SYSPARA_MAX_SIZE = 128; +static constexpr const char *DEFAULT_HTTP_PROXY_HOST = "NONE"; +static constexpr const char *DEFAULT_HTTP_PROXY_PORT = "0"; +static constexpr const char *DEFAULT_HTTP_PROXY_EXCLUSION_LIST = "NONE"; +static constexpr const char *HTTP_PROXY_HOST_KEY = "persist.netmanager_base.http_proxy.host"; +static constexpr const char *HTTP_PROXY_PORT_KEY = "persist.netmanager_base.http_proxy.port"; +static constexpr const char *HTTP_PROXY_EXCLUSIONS_KEY = "persist.netmanager_base.http_proxy.exclusion_list"; bool HttpExec::AddCurlHandle(CURL *handle, RequestContext *context) { if (handle == nullptr || staticVariable_.curlMulti == nullptr) { @@ -347,6 +361,33 @@ void HttpExec::ReadRespond() } } +void HttpExec::GetGlobalHttpProxyInfo(std::string &host, int32_t &port, std::string &exclusions) +{ +#ifndef WINDOWS_PLATFORM +#ifndef MAC_PLATFORM + char httpProxyHost[SYSPARA_MAX_SIZE] = {0}; + char httpProxyPort[SYSPARA_MAX_SIZE] = {0}; + char httpProxyExclusions[SYSPARA_MAX_SIZE] = {0}; + GetParameter(HTTP_PROXY_HOST_KEY, DEFAULT_HTTP_PROXY_HOST, httpProxyHost, sizeof(httpProxyHost)); + GetParameter(HTTP_PROXY_PORT_KEY, DEFAULT_HTTP_PROXY_PORT, httpProxyPort, sizeof(httpProxyPort)); + GetParameter(HTTP_PROXY_EXCLUSIONS_KEY, DEFAULT_HTTP_PROXY_EXCLUSION_LIST, httpProxyExclusions, + sizeof(httpProxyExclusions)); + + host = Base64::Decode(httpProxyHost); + if (host == DEFAULT_HTTP_PROXY_HOST) { + host = std::string(); + } + + exclusions = httpProxyExclusions; + if (exclusions == DEFAULT_HTTP_PROXY_EXCLUSION_LIST) { + exclusions = std::string(); + } + + port = std::atoi(httpProxyPort); +#endif +#endif +} + bool HttpExec::Initialize() { std::lock_guard lock(staticVariable_.mutex); @@ -402,14 +443,25 @@ bool HttpExec::SetOption(CURL *curl, RequestContext *context, struct curl_slist /* first #undef CURL_DISABLE_COOKIES in curl config */ NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_COOKIEFILE, "", context); -#if NETSTACK_USE_PROXY - NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_PROXY, NETSTACK_PROXY_URL_PORT, context); - NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_PROXYTYPE, NETSTACK_PROXY_TYPE, context); - NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_HTTPPROXYTUNNEL, 1L, context); + std::string host, exclusions; + int32_t port = 0; + if (context->options.GetUsingHttpProxyType() == UsingHttpProxyType::USE_DEFAULT) { + GetGlobalHttpProxyInfo(host, port, exclusions); + } else if (context->options.GetUsingHttpProxyType() == UsingHttpProxyType::USE_SPECIFIED) { + context->options.GetSpecifiedHttpProxy(host, port, exclusions); + } + if (!host.empty()) { + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_PROXY, host.c_str(), context); + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_PROXYPORT, port, context); + if (!exclusions.empty()) { + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_NOPROXY, exclusions.c_str(), context); + } + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP, context); + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_HTTPPROXYTUNNEL, 1L, context); + } #ifdef NETSTACK_PROXY_PASS NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_PROXYUSERPWD, NETSTACK_PROXY_PASS, context); #endif // NETSTACK_PROXY_PASS -#endif // NETSTACK_USE_PROXY #if NO_SSL_CERTIFICATION // in real life, you should buy a ssl certification and rename it to /etc/ssl/cert.pem diff --git a/frameworks/js/napi/http/options/include/http_request_options.h b/frameworks/js/napi/http/options/include/http_request_options.h index 81ac421a6658c1703b99e00deb1f6a0eee3c7fb2..c93d43535bdf66325a039c6340b94f2085950178 100644 --- a/frameworks/js/napi/http/options/include/http_request_options.h +++ b/frameworks/js/napi/http/options/include/http_request_options.h @@ -28,6 +28,12 @@ enum class HttpProtocol { HTTP_NONE, // default choose by curl }; +enum class UsingHttpProxyType { + NOT_USE, + USE_DEFAULT, + USE_SPECIFIED, +}; + class HttpRequestOptions final { public: HttpRequestOptions(); @@ -48,6 +54,10 @@ public: void SetHttpDataType(HttpDataType dataType); + void SetUsingHttpProxyType(UsingHttpProxyType type); + + void SetSpecifiedHttpProxy(const std::string &host, int32_t port, const std::string &exclusionList); + [[nodiscard]] const std::string &GetUrl() const; [[nodiscard]] const std::string &GetMethod() const; @@ -72,6 +82,10 @@ public: [[nodiscard]] uint32_t GetPriority() const; + [[nodiscard]] UsingHttpProxyType GetUsingHttpProxyType() const; + + void GetSpecifiedHttpProxy(std::string &host, int32_t &port, std::string &exclusionList); + private: std::string url_; @@ -92,6 +106,14 @@ private: HttpDataType dataType_; uint32_t priority_; + + UsingHttpProxyType usingHttpProxyType_; + + std::string httpProxyHost_; + + int32_t httpProxyPort_; + + std::string httpProxyExclusions_; }; } // namespace OHOS::NetStack diff --git a/frameworks/js/napi/http/options/src/http_request_options.cpp b/frameworks/js/napi/http/options/src/http_request_options.cpp index 96f8fd4141e6f5422779b1d90d17796bb7d02b46..9e4198beea2f34646a92d3e8d11c97a15cb0d9ef 100644 --- a/frameworks/js/napi/http/options/src/http_request_options.cpp +++ b/frameworks/js/napi/http/options/src/http_request_options.cpp @@ -30,7 +30,9 @@ HttpRequestOptions::HttpRequestOptions() connectTimeout_(HttpConstant::DEFAULT_CONNECT_TIMEOUT), usingProtocol_(HttpProtocol::HTTP_NONE), dataType_(HttpDataType::NO_DATA_TYPE), - priority_(0) + priority_(0), + usingHttpProxyType_(UsingHttpProxyType::NOT_USE), + httpProxyPort_(0) { header_[CommonUtils::ToLower(HttpConstant::HTTP_CONTENT_TYPE)] = HttpConstant::HTTP_CONTENT_TYPE_JSON; // default } @@ -148,4 +150,28 @@ uint32_t HttpRequestOptions::GetPriority() const { return priority_; } + +void HttpRequestOptions::SetUsingHttpProxyType(UsingHttpProxyType type) +{ + usingHttpProxyType_ = type; +} + +UsingHttpProxyType HttpRequestOptions::GetUsingHttpProxyType() const +{ + return usingHttpProxyType_; +} + +void HttpRequestOptions::SetSpecifiedHttpProxy(const std::string &host, int32_t port, const std::string &exclusionList) +{ + httpProxyHost_ = host; + httpProxyPort_ = port; + httpProxyExclusions_ = exclusionList; +} + +void HttpRequestOptions::GetSpecifiedHttpProxy(std::string &host, int32_t &port, std::string &exclusionList) +{ + host = httpProxyHost_; + port = httpProxyPort_; + exclusionList = httpProxyExclusions_; +} } // namespace OHOS::NetStack \ No newline at end of file diff --git a/interfaces/kits/js/@ohos.net.http.d.ts b/interfaces/kits/js/@ohos.net.http.d.ts index 66da78c597fbbfaecaf330566b68145b9ff972b1..0d6fc61d3b6667851f433aa43d709be96fc27243 100644 --- a/interfaces/kits/js/@ohos.net.http.d.ts +++ b/interfaces/kits/js/@ohos.net.http.d.ts @@ -14,6 +14,7 @@ */ import {AsyncCallback, Callback} from "./basic"; +import connection from "./@ohos.net.connection"; /** * Provides http related APIs. @@ -22,6 +23,7 @@ import {AsyncCallback, Callback} from "./basic"; * @syscap SystemCapability.Communication.NetStack */ declare namespace http { + type HttpProxy = connection.HttpProxy; /** * Creates an HTTP request task. */ @@ -67,6 +69,13 @@ declare namespace http { * @since 9 */ usingProtocol?: HttpProtocol; // default is automatically specified by the system. + /** + * If this parameter is set as type of boolean, the system will use default proxy or not use proxy. + * If this parameter is set as type of HttpProxy, the system will use the specified HttpProxy. + * + * @since 10 + */ + usingProxy?: boolean | HttpProxy; // default is false. } export interface HttpRequest {