1 /*
2 * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "http_module.h"
17
18 #include "constant.h"
19 #include "event_list.h"
20 #include "http_async_work.h"
21 #include "http_exec.h"
22 #include "netstack_log.h"
23 #include "netstack_module_template.h"
24
25 #define DECLARE_RESPONSE_CODE(code) \
26 DECLARE_NAPI_STATIC_PROPERTY(#code, NapiUtils::CreateUint32(env, static_cast<uint32_t>(ResponseCode::code)))
27
28 #define DECLARE_REQUEST_METHOD(method) \
29 DECLARE_NAPI_STATIC_PROPERTY(HttpConstant::method, NapiUtils::CreateStringUtf8(env, HttpConstant::method))
30
31 static constexpr const char *REQUEST_ASYNC_WORK_NAME = "ExecRequest";
32
33 static constexpr const char *HTTP_MODULE_NAME = "net.http";
34
35 namespace OHOS::NetStack {
InitHttpModule(napi_env env,napi_value exports)36 napi_value HttpModuleExports::InitHttpModule(napi_env env, napi_value exports)
37 {
38 DefineHttpRequestClass(env, exports);
39 InitHttpProperties(env, exports);
40
41 return exports;
42 }
43
CreateHttp(napi_env env,napi_callback_info info)44 napi_value HttpModuleExports::CreateHttp(napi_env env, napi_callback_info info)
45 {
46 return ModuleTemplate::NewInstance(env, info, INTERFACE_HTTP_REQUEST, [](napi_env, void *data, void *) {
47 NETSTACK_LOGI("http request handle is finalized");
48 (void)data;
49 });
50 }
51
DefineHttpRequestClass(napi_env env,napi_value exports)52 void HttpModuleExports::DefineHttpRequestClass(napi_env env, napi_value exports)
53 {
54 std::initializer_list<napi_property_descriptor> properties = {
55 DECLARE_NAPI_FUNCTION(HttpRequest::FUNCTION_REQUEST, HttpRequest::Request),
56 DECLARE_NAPI_FUNCTION(HttpRequest::FUNCTION_DESTROY, HttpRequest::Destroy),
57 DECLARE_NAPI_FUNCTION(HttpRequest::FUNCTION_ON, HttpRequest::On),
58 DECLARE_NAPI_FUNCTION(HttpRequest::FUNCTION_ONCE, HttpRequest::Once),
59 DECLARE_NAPI_FUNCTION(HttpRequest::FUNCTION_OFF, HttpRequest::Off),
60 };
61 ModuleTemplate::DefineClass(env, exports, properties, INTERFACE_HTTP_REQUEST);
62 }
63
InitHttpProperties(napi_env env,napi_value exports)64 void HttpModuleExports::InitHttpProperties(napi_env env, napi_value exports)
65 {
66 std::initializer_list<napi_property_descriptor> properties = {
67 DECLARE_NAPI_FUNCTION(FUNCTION_CREATE_HTTP, CreateHttp),
68 };
69 NapiUtils::DefineProperties(env, exports, properties);
70
71 InitRequestMethod(env, exports);
72 InitResponseCode(env, exports);
73 }
74
InitRequestMethod(napi_env env,napi_value exports)75 void HttpModuleExports::InitRequestMethod(napi_env env, napi_value exports)
76 {
77 std::initializer_list<napi_property_descriptor> properties = {
78 DECLARE_REQUEST_METHOD(HTTP_METHOD_OPTIONS), DECLARE_REQUEST_METHOD(HTTP_METHOD_GET),
79 DECLARE_REQUEST_METHOD(HTTP_METHOD_HEAD), DECLARE_REQUEST_METHOD(HTTP_METHOD_POST),
80 DECLARE_REQUEST_METHOD(HTTP_METHOD_PUT), DECLARE_REQUEST_METHOD(HTTP_METHOD_DELETE),
81 DECLARE_REQUEST_METHOD(HTTP_METHOD_TRACE), DECLARE_REQUEST_METHOD(HTTP_METHOD_CONNECT),
82 };
83
84 napi_value requestMethod = NapiUtils::CreateObject(env);
85 NapiUtils::DefineProperties(env, requestMethod, properties);
86
87 NapiUtils::SetNamedProperty(env, exports, INTERFACE_REQUEST_METHOD, requestMethod);
88 }
89
InitResponseCode(napi_env env,napi_value exports)90 void HttpModuleExports::InitResponseCode(napi_env env, napi_value exports)
91 {
92 std::initializer_list<napi_property_descriptor> properties = {
93 DECLARE_RESPONSE_CODE(OK),
94 DECLARE_RESPONSE_CODE(CREATED),
95 DECLARE_RESPONSE_CODE(ACCEPTED),
96 DECLARE_RESPONSE_CODE(NOT_AUTHORITATIVE),
97 DECLARE_RESPONSE_CODE(NO_CONTENT),
98 DECLARE_RESPONSE_CODE(RESET),
99 DECLARE_RESPONSE_CODE(PARTIAL),
100 DECLARE_RESPONSE_CODE(MULT_CHOICE),
101 DECLARE_RESPONSE_CODE(MOVED_PERM),
102 DECLARE_RESPONSE_CODE(MOVED_TEMP),
103 DECLARE_RESPONSE_CODE(SEE_OTHER),
104 DECLARE_RESPONSE_CODE(NOT_MODIFIED),
105 DECLARE_RESPONSE_CODE(USE_PROXY),
106 DECLARE_RESPONSE_CODE(BAD_REQUEST),
107 DECLARE_RESPONSE_CODE(UNAUTHORIZED),
108 DECLARE_RESPONSE_CODE(PAYMENT_REQUIRED),
109 DECLARE_RESPONSE_CODE(FORBIDDEN),
110 DECLARE_RESPONSE_CODE(NOT_FOUND),
111 DECLARE_RESPONSE_CODE(BAD_METHOD),
112 DECLARE_RESPONSE_CODE(NOT_ACCEPTABLE),
113 DECLARE_RESPONSE_CODE(PROXY_AUTH),
114 DECLARE_RESPONSE_CODE(CLIENT_TIMEOUT),
115 DECLARE_RESPONSE_CODE(CONFLICT),
116 DECLARE_RESPONSE_CODE(GONE),
117 DECLARE_RESPONSE_CODE(LENGTH_REQUIRED),
118 DECLARE_RESPONSE_CODE(PRECON_FAILED),
119 DECLARE_RESPONSE_CODE(ENTITY_TOO_LARGE),
120 DECLARE_RESPONSE_CODE(REQ_TOO_LONG),
121 DECLARE_RESPONSE_CODE(UNSUPPORTED_TYPE),
122 DECLARE_RESPONSE_CODE(INTERNAL_ERROR),
123 DECLARE_RESPONSE_CODE(NOT_IMPLEMENTED),
124 DECLARE_RESPONSE_CODE(BAD_GATEWAY),
125 DECLARE_RESPONSE_CODE(UNAVAILABLE),
126 DECLARE_RESPONSE_CODE(GATEWAY_TIMEOUT),
127 DECLARE_RESPONSE_CODE(VERSION),
128 };
129
130 napi_value responseCode = NapiUtils::CreateObject(env);
131 NapiUtils::DefineProperties(env, responseCode, properties);
132
133 NapiUtils::SetNamedProperty(env, exports, INTERFACE_RESPONSE_CODE, responseCode);
134 }
135
Request(napi_env env,napi_callback_info info)136 napi_value HttpModuleExports::HttpRequest::Request(napi_env env, napi_callback_info info)
137 {
138 return ModuleTemplate::Interface<RequestContext>(
139 env, info, REQUEST_ASYNC_WORK_NAME,
140 [](napi_env, napi_value, RequestContext *) -> bool { return HttpExec::Initialize(); },
141 HttpAsyncWork::ExecRequest, HttpAsyncWork::RequestCallback);
142 }
143
Destroy(napi_env env,napi_callback_info info)144 napi_value HttpModuleExports::HttpRequest::Destroy(napi_env env, napi_callback_info info)
145 {
146 (void)env;
147 (void)info;
148
149 return NapiUtils::GetUndefined(env);
150 }
151
On(napi_env env,napi_callback_info info)152 napi_value HttpModuleExports::HttpRequest::On(napi_env env, napi_callback_info info)
153 {
154 ModuleTemplate::On(env, info, {ON_HEADERS_RECEIVE}, false);
155 return ModuleTemplate::On(env, info, {ON_HEADER_RECEIVE}, true);
156 }
157
Once(napi_env env,napi_callback_info info)158 napi_value HttpModuleExports::HttpRequest::Once(napi_env env, napi_callback_info info)
159 {
160 return ModuleTemplate::Once(env, info, {ON_HEADER_RECEIVE, ON_HEADERS_RECEIVE}, false);
161 }
162
Off(napi_env env,napi_callback_info info)163 napi_value HttpModuleExports::HttpRequest::Off(napi_env env, napi_callback_info info)
164 {
165 ModuleTemplate::Off(env, info, {ON_HEADERS_RECEIVE});
166 return ModuleTemplate::Off(env, info, {ON_HEADER_RECEIVE});
167 }
168
169 static napi_module g_httpModule = {
170 .nm_version = 1,
171 .nm_flags = 0,
172 .nm_filename = nullptr,
173 .nm_register_func = HttpModuleExports::InitHttpModule,
174 .nm_modname = HTTP_MODULE_NAME,
175 .nm_priv = nullptr,
176 .reserved = {nullptr},
177 };
178
RegisterHttpModule(void)179 extern "C" __attribute__((constructor)) void RegisterHttpModule(void)
180 {
181 napi_module_register(&g_httpModule);
182 }
183 } // namespace OHOS::NetStack
184