uws-react-native 0.0.1-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (315) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +84 -0
  3. package/UwsReactNative.podspec +71 -0
  4. package/android/build.gradle.kts +138 -0
  5. package/android/src/main/AndroidManifest.xml +2 -0
  6. package/android/src/main/java/id/sufeni/oss/uwsreactnative/UwsReactNativePackage.kt +18 -0
  7. package/apple/OnLoad.mm +17 -0
  8. package/cpp/CMakeLists.txt +154 -0
  9. package/cpp/UwsReactNativeModule.cpp +191 -0
  10. package/cpp/UwsReactNativeModule.h +30 -0
  11. package/cpp/app/AppHost.h +37 -0
  12. package/cpp/app/AppRunner.h +88 -0
  13. package/cpp/app/CMakeLists.txt +39 -0
  14. package/cpp/app/HttpRequestObject.h +173 -0
  15. package/cpp/app/HttpResponseObject.h +623 -0
  16. package/cpp/app/RecognizedString.h +71 -0
  17. package/cpp/app/TemplatedAppObject.h +472 -0
  18. package/cpp/bridging/ArrayBuffer.h +150 -0
  19. package/cpp/bridging/CMakeLists.txt +34 -0
  20. package/cpp/jsi/Buffer.h +91 -0
  21. package/cpp/jsi/CMakeLists.txt +34 -0
  22. package/cpp/uSockets/bsd.c +767 -0
  23. package/cpp/uSockets/context.c +524 -0
  24. package/cpp/uSockets/crypto/openssl.c +858 -0
  25. package/cpp/uSockets/crypto/sni_tree.cpp +218 -0
  26. package/cpp/uSockets/eventing/asio.cpp +475 -0
  27. package/cpp/uSockets/eventing/epoll_kqueue.c +458 -0
  28. package/cpp/uSockets/eventing/gcd.c +278 -0
  29. package/cpp/uSockets/eventing/libuv.c +305 -0
  30. package/cpp/uSockets/internal/eventing/asio.h +45 -0
  31. package/cpp/uSockets/internal/eventing/epoll_kqueue.h +67 -0
  32. package/cpp/uSockets/internal/eventing/gcd.h +40 -0
  33. package/cpp/uSockets/internal/eventing/libuv.h +45 -0
  34. package/cpp/uSockets/internal/internal.h +224 -0
  35. package/cpp/uSockets/internal/loop_data.h +38 -0
  36. package/cpp/uSockets/internal/networking/bsd.h +109 -0
  37. package/cpp/uSockets/io_uring/internal.h +98 -0
  38. package/cpp/uSockets/io_uring/io_context.c +302 -0
  39. package/cpp/uSockets/io_uring/io_loop.c +422 -0
  40. package/cpp/uSockets/io_uring/io_socket.c +139 -0
  41. package/cpp/uSockets/libusockets.h +350 -0
  42. package/cpp/uSockets/loop.c +396 -0
  43. package/cpp/uSockets/quic.c +1071 -0
  44. package/cpp/uSockets/quic.h +68 -0
  45. package/cpp/uSockets/socket.c +231 -0
  46. package/cpp/uSockets/udp.c +151 -0
  47. package/cpp/uWebSockets/uWebSockets/App.h +676 -0
  48. package/cpp/uWebSockets/uWebSockets/AsyncSocket.h +376 -0
  49. package/cpp/uWebSockets/uWebSockets/AsyncSocketData.h +94 -0
  50. package/cpp/uWebSockets/uWebSockets/BloomFilter.h +83 -0
  51. package/cpp/uWebSockets/uWebSockets/CachingApp.h +115 -0
  52. package/cpp/uWebSockets/uWebSockets/ChunkedEncoding.h +237 -0
  53. package/cpp/uWebSockets/uWebSockets/ClientApp.h +36 -0
  54. package/cpp/uWebSockets/uWebSockets/Http3App.h +140 -0
  55. package/cpp/uWebSockets/uWebSockets/Http3Context.h +157 -0
  56. package/cpp/uWebSockets/uWebSockets/Http3ContextData.h +21 -0
  57. package/cpp/uWebSockets/uWebSockets/Http3Request.h +22 -0
  58. package/cpp/uWebSockets/uWebSockets/Http3Response.h +120 -0
  59. package/cpp/uWebSockets/uWebSockets/Http3ResponseData.h +25 -0
  60. package/cpp/uWebSockets/uWebSockets/HttpContext.h +521 -0
  61. package/cpp/uWebSockets/uWebSockets/HttpContextData.h +60 -0
  62. package/cpp/uWebSockets/uWebSockets/HttpErrors.h +53 -0
  63. package/cpp/uWebSockets/uWebSockets/HttpParser.h +747 -0
  64. package/cpp/uWebSockets/uWebSockets/HttpResponse.h +605 -0
  65. package/cpp/uWebSockets/uWebSockets/HttpResponseData.h +123 -0
  66. package/cpp/uWebSockets/uWebSockets/HttpRouter.h +384 -0
  67. package/cpp/uWebSockets/uWebSockets/LocalCluster.h +64 -0
  68. package/cpp/uWebSockets/uWebSockets/Loop.h +238 -0
  69. package/cpp/uWebSockets/uWebSockets/LoopData.h +113 -0
  70. package/cpp/uWebSockets/uWebSockets/MessageParser.h +64 -0
  71. package/cpp/uWebSockets/uWebSockets/MoveOnlyFunction.h +389 -0
  72. package/cpp/uWebSockets/uWebSockets/Multipart.h +231 -0
  73. package/cpp/uWebSockets/uWebSockets/PerMessageDeflate.h +303 -0
  74. package/cpp/uWebSockets/uWebSockets/ProxyParser.h +187 -0
  75. package/cpp/uWebSockets/uWebSockets/QueryParser.h +120 -0
  76. package/cpp/uWebSockets/uWebSockets/TopicTree.h +364 -0
  77. package/cpp/uWebSockets/uWebSockets/Utilities.h +66 -0
  78. package/cpp/uWebSockets/uWebSockets/WebSocket.h +407 -0
  79. package/cpp/uWebSockets/uWebSockets/WebSocketContext.h +436 -0
  80. package/cpp/uWebSockets/uWebSockets/WebSocketContextData.h +109 -0
  81. package/cpp/uWebSockets/uWebSockets/WebSocketData.h +86 -0
  82. package/cpp/uWebSockets/uWebSockets/WebSocketExtensions.h +256 -0
  83. package/cpp/uWebSockets/uWebSockets/WebSocketHandshake.h +145 -0
  84. package/cpp/uWebSockets/uWebSockets/WebSocketProtocol.h +525 -0
  85. package/lib/commonjs/_internal/native-modules/NativeReactNativeUws.js +12 -0
  86. package/lib/commonjs/_internal/native-modules/NativeReactNativeUws.js.map +1 -0
  87. package/lib/commonjs/index.js +28 -0
  88. package/lib/commonjs/index.js.map +1 -0
  89. package/lib/commonjs/modules/App.js +17 -0
  90. package/lib/commonjs/modules/App.js.map +1 -0
  91. package/lib/commonjs/modules/CompressOptions.js +103 -0
  92. package/lib/commonjs/modules/CompressOptions.js.map +1 -0
  93. package/lib/commonjs/modules/EnvironmentVariables.js +17 -0
  94. package/lib/commonjs/modules/EnvironmentVariables.js.map +1 -0
  95. package/lib/commonjs/modules/ListenOptions.js +12 -0
  96. package/lib/commonjs/modules/ListenOptions.js.map +1 -0
  97. package/lib/commonjs/modules/SSLApp.js +15 -0
  98. package/lib/commonjs/modules/SSLApp.js.map +1 -0
  99. package/lib/commonjs/modules/getParts.js +28 -0
  100. package/lib/commonjs/modules/getParts.js.map +1 -0
  101. package/lib/commonjs/modules/index.js +61 -0
  102. package/lib/commonjs/modules/index.js.map +1 -0
  103. package/lib/commonjs/modules/us_listen_socket_close.js +21 -0
  104. package/lib/commonjs/modules/us_listen_socket_close.js.map +1 -0
  105. package/lib/commonjs/modules/us_socket_local_port.js +22 -0
  106. package/lib/commonjs/modules/us_socket_local_port.js.map +1 -0
  107. package/lib/commonjs/package.json +1 -0
  108. package/lib/commonjs/types/AppDescriptor.js +2 -0
  109. package/lib/commonjs/types/AppDescriptor.js.map +1 -0
  110. package/lib/commonjs/types/AppOptions.js +2 -0
  111. package/lib/commonjs/types/AppOptions.js.map +1 -0
  112. package/lib/commonjs/types/HttpRequest.js +6 -0
  113. package/lib/commonjs/types/HttpRequest.js.map +1 -0
  114. package/lib/commonjs/types/HttpResponse.js +6 -0
  115. package/lib/commonjs/types/HttpResponse.js.map +1 -0
  116. package/lib/commonjs/types/HttpRouterOptions.js +2 -0
  117. package/lib/commonjs/types/HttpRouterOptions.js.map +1 -0
  118. package/lib/commonjs/types/MultipartField.js +2 -0
  119. package/lib/commonjs/types/MultipartField.js.map +1 -0
  120. package/lib/commonjs/types/RecognizedString.js +2 -0
  121. package/lib/commonjs/types/RecognizedString.js.map +1 -0
  122. package/lib/commonjs/types/TemplatedApp.js +6 -0
  123. package/lib/commonjs/types/TemplatedApp.js.map +1 -0
  124. package/lib/commonjs/types/WebSocket.js +6 -0
  125. package/lib/commonjs/types/WebSocket.js.map +1 -0
  126. package/lib/commonjs/types/WebSocketBehaviour.js +139 -0
  127. package/lib/commonjs/types/WebSocketBehaviour.js.map +1 -0
  128. package/lib/commonjs/types/index.js +2 -0
  129. package/lib/commonjs/types/index.js.map +1 -0
  130. package/lib/commonjs/types/us_listen_socket.js +2 -0
  131. package/lib/commonjs/types/us_listen_socket.js.map +1 -0
  132. package/lib/commonjs/types/us_socket.js +2 -0
  133. package/lib/commonjs/types/us_socket.js.map +1 -0
  134. package/lib/commonjs/types/us_socket_context_t.js +2 -0
  135. package/lib/commonjs/types/us_socket_context_t.js.map +1 -0
  136. package/lib/module/_internal/native-modules/NativeReactNativeUws.js +10 -0
  137. package/lib/module/_internal/native-modules/NativeReactNativeUws.js.map +1 -0
  138. package/lib/module/index.js +5 -0
  139. package/lib/module/index.js.map +1 -0
  140. package/lib/module/modules/App.js +12 -0
  141. package/lib/module/modules/App.js.map +1 -0
  142. package/lib/module/modules/CompressOptions.js +103 -0
  143. package/lib/module/modules/CompressOptions.js.map +1 -0
  144. package/lib/module/modules/EnvironmentVariables.js +13 -0
  145. package/lib/module/modules/EnvironmentVariables.js.map +1 -0
  146. package/lib/module/modules/ListenOptions.js +8 -0
  147. package/lib/module/modules/ListenOptions.js.map +1 -0
  148. package/lib/module/modules/SSLApp.js +15 -0
  149. package/lib/module/modules/SSLApp.js.map +1 -0
  150. package/lib/module/modules/getParts.js +23 -0
  151. package/lib/module/modules/getParts.js.map +1 -0
  152. package/lib/module/modules/index.js +11 -0
  153. package/lib/module/modules/index.js.map +1 -0
  154. package/lib/module/modules/us_listen_socket_close.js +17 -0
  155. package/lib/module/modules/us_listen_socket_close.js.map +1 -0
  156. package/lib/module/modules/us_socket_local_port.js +18 -0
  157. package/lib/module/modules/us_socket_local_port.js.map +1 -0
  158. package/lib/module/package.json +1 -0
  159. package/lib/module/types/AppDescriptor.js +2 -0
  160. package/lib/module/types/AppDescriptor.js.map +1 -0
  161. package/lib/module/types/AppOptions.js +2 -0
  162. package/lib/module/types/AppOptions.js.map +1 -0
  163. package/lib/module/types/HttpRequest.js +4 -0
  164. package/lib/module/types/HttpRequest.js.map +1 -0
  165. package/lib/module/types/HttpResponse.js +4 -0
  166. package/lib/module/types/HttpResponse.js.map +1 -0
  167. package/lib/module/types/HttpRouterOptions.js +2 -0
  168. package/lib/module/types/HttpRouterOptions.js.map +1 -0
  169. package/lib/module/types/MultipartField.js +2 -0
  170. package/lib/module/types/MultipartField.js.map +1 -0
  171. package/lib/module/types/RecognizedString.js +2 -0
  172. package/lib/module/types/RecognizedString.js.map +1 -0
  173. package/lib/module/types/TemplatedApp.js +4 -0
  174. package/lib/module/types/TemplatedApp.js.map +1 -0
  175. package/lib/module/types/WebSocket.js +4 -0
  176. package/lib/module/types/WebSocket.js.map +1 -0
  177. package/lib/module/types/WebSocketBehaviour.js +139 -0
  178. package/lib/module/types/WebSocketBehaviour.js.map +1 -0
  179. package/lib/module/types/index.js +2 -0
  180. package/lib/module/types/index.js.map +1 -0
  181. package/lib/module/types/us_listen_socket.js +2 -0
  182. package/lib/module/types/us_listen_socket.js.map +1 -0
  183. package/lib/module/types/us_socket.js +2 -0
  184. package/lib/module/types/us_socket.js.map +1 -0
  185. package/lib/module/types/us_socket_context_t.js +2 -0
  186. package/lib/module/types/us_socket_context_t.js.map +1 -0
  187. package/lib/typescript/commonjs/_internal/native-modules/NativeReactNativeUws.d.ts +22 -0
  188. package/lib/typescript/commonjs/_internal/native-modules/NativeReactNativeUws.d.ts.map +1 -0
  189. package/lib/typescript/commonjs/index.d.ts +3 -0
  190. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  191. package/lib/typescript/commonjs/modules/App.d.ts +7 -0
  192. package/lib/typescript/commonjs/modules/App.d.ts.map +1 -0
  193. package/lib/typescript/commonjs/modules/CompressOptions.d.ts +1 -0
  194. package/lib/typescript/commonjs/modules/CompressOptions.d.ts.map +1 -0
  195. package/lib/typescript/commonjs/modules/EnvironmentVariables.d.ts +16 -0
  196. package/lib/typescript/commonjs/modules/EnvironmentVariables.d.ts.map +1 -0
  197. package/lib/typescript/commonjs/modules/ListenOptions.d.ts +5 -0
  198. package/lib/typescript/commonjs/modules/ListenOptions.d.ts.map +1 -0
  199. package/lib/typescript/commonjs/modules/SSLApp.d.ts +1 -0
  200. package/lib/typescript/commonjs/modules/SSLApp.d.ts.map +1 -0
  201. package/lib/typescript/commonjs/modules/getParts.d.ts +6 -0
  202. package/lib/typescript/commonjs/modules/getParts.d.ts.map +1 -0
  203. package/lib/typescript/commonjs/modules/index.d.ts +6 -0
  204. package/lib/typescript/commonjs/modules/index.d.ts.map +1 -0
  205. package/lib/typescript/commonjs/modules/us_listen_socket_close.d.ts +5 -0
  206. package/lib/typescript/commonjs/modules/us_listen_socket_close.d.ts.map +1 -0
  207. package/lib/typescript/commonjs/modules/us_socket_local_port.d.ts +5 -0
  208. package/lib/typescript/commonjs/modules/us_socket_local_port.d.ts.map +1 -0
  209. package/lib/typescript/commonjs/package.json +1 -0
  210. package/lib/typescript/commonjs/types/AppDescriptor.d.ts +8 -0
  211. package/lib/typescript/commonjs/types/AppDescriptor.d.ts.map +1 -0
  212. package/lib/typescript/commonjs/types/AppOptions.d.ts +17 -0
  213. package/lib/typescript/commonjs/types/AppOptions.d.ts.map +1 -0
  214. package/lib/typescript/commonjs/types/HttpRequest.d.ts +54 -0
  215. package/lib/typescript/commonjs/types/HttpRequest.d.ts.map +1 -0
  216. package/lib/typescript/commonjs/types/HttpResponse.d.ts +169 -0
  217. package/lib/typescript/commonjs/types/HttpResponse.d.ts.map +1 -0
  218. package/lib/typescript/commonjs/types/HttpRouterOptions.d.ts +24 -0
  219. package/lib/typescript/commonjs/types/HttpRouterOptions.d.ts.map +1 -0
  220. package/lib/typescript/commonjs/types/MultipartField.d.ts +7 -0
  221. package/lib/typescript/commonjs/types/MultipartField.d.ts.map +1 -0
  222. package/lib/typescript/commonjs/types/RecognizedString.d.ts +10 -0
  223. package/lib/typescript/commonjs/types/RecognizedString.d.ts.map +1 -0
  224. package/lib/typescript/commonjs/types/TemplatedApp.d.ts +108 -0
  225. package/lib/typescript/commonjs/types/TemplatedApp.d.ts.map +1 -0
  226. package/lib/typescript/commonjs/types/WebSocket.d.ts +96 -0
  227. package/lib/typescript/commonjs/types/WebSocket.d.ts.map +1 -0
  228. package/lib/typescript/commonjs/types/WebSocketBehaviour.d.ts +1 -0
  229. package/lib/typescript/commonjs/types/WebSocketBehaviour.d.ts.map +1 -0
  230. package/lib/typescript/commonjs/types/index.d.ts +6 -0
  231. package/lib/typescript/commonjs/types/index.d.ts.map +1 -0
  232. package/lib/typescript/commonjs/types/us_listen_socket.d.ts +7 -0
  233. package/lib/typescript/commonjs/types/us_listen_socket.d.ts.map +1 -0
  234. package/lib/typescript/commonjs/types/us_socket.d.ts +7 -0
  235. package/lib/typescript/commonjs/types/us_socket.d.ts.map +1 -0
  236. package/lib/typescript/commonjs/types/us_socket_context_t.d.ts +7 -0
  237. package/lib/typescript/commonjs/types/us_socket_context_t.d.ts.map +1 -0
  238. package/lib/typescript/module/_internal/native-modules/NativeReactNativeUws.d.ts +22 -0
  239. package/lib/typescript/module/_internal/native-modules/NativeReactNativeUws.d.ts.map +1 -0
  240. package/lib/typescript/module/index.d.ts +3 -0
  241. package/lib/typescript/module/index.d.ts.map +1 -0
  242. package/lib/typescript/module/modules/App.d.ts +7 -0
  243. package/lib/typescript/module/modules/App.d.ts.map +1 -0
  244. package/lib/typescript/module/modules/CompressOptions.d.ts +1 -0
  245. package/lib/typescript/module/modules/CompressOptions.d.ts.map +1 -0
  246. package/lib/typescript/module/modules/EnvironmentVariables.d.ts +16 -0
  247. package/lib/typescript/module/modules/EnvironmentVariables.d.ts.map +1 -0
  248. package/lib/typescript/module/modules/ListenOptions.d.ts +5 -0
  249. package/lib/typescript/module/modules/ListenOptions.d.ts.map +1 -0
  250. package/lib/typescript/module/modules/SSLApp.d.ts +1 -0
  251. package/lib/typescript/module/modules/SSLApp.d.ts.map +1 -0
  252. package/lib/typescript/module/modules/getParts.d.ts +6 -0
  253. package/lib/typescript/module/modules/getParts.d.ts.map +1 -0
  254. package/lib/typescript/module/modules/index.d.ts +6 -0
  255. package/lib/typescript/module/modules/index.d.ts.map +1 -0
  256. package/lib/typescript/module/modules/us_listen_socket_close.d.ts +5 -0
  257. package/lib/typescript/module/modules/us_listen_socket_close.d.ts.map +1 -0
  258. package/lib/typescript/module/modules/us_socket_local_port.d.ts +5 -0
  259. package/lib/typescript/module/modules/us_socket_local_port.d.ts.map +1 -0
  260. package/lib/typescript/module/package.json +1 -0
  261. package/lib/typescript/module/types/AppDescriptor.d.ts +8 -0
  262. package/lib/typescript/module/types/AppDescriptor.d.ts.map +1 -0
  263. package/lib/typescript/module/types/AppOptions.d.ts +17 -0
  264. package/lib/typescript/module/types/AppOptions.d.ts.map +1 -0
  265. package/lib/typescript/module/types/HttpRequest.d.ts +54 -0
  266. package/lib/typescript/module/types/HttpRequest.d.ts.map +1 -0
  267. package/lib/typescript/module/types/HttpResponse.d.ts +169 -0
  268. package/lib/typescript/module/types/HttpResponse.d.ts.map +1 -0
  269. package/lib/typescript/module/types/HttpRouterOptions.d.ts +24 -0
  270. package/lib/typescript/module/types/HttpRouterOptions.d.ts.map +1 -0
  271. package/lib/typescript/module/types/MultipartField.d.ts +7 -0
  272. package/lib/typescript/module/types/MultipartField.d.ts.map +1 -0
  273. package/lib/typescript/module/types/RecognizedString.d.ts +10 -0
  274. package/lib/typescript/module/types/RecognizedString.d.ts.map +1 -0
  275. package/lib/typescript/module/types/TemplatedApp.d.ts +108 -0
  276. package/lib/typescript/module/types/TemplatedApp.d.ts.map +1 -0
  277. package/lib/typescript/module/types/WebSocket.d.ts +96 -0
  278. package/lib/typescript/module/types/WebSocket.d.ts.map +1 -0
  279. package/lib/typescript/module/types/WebSocketBehaviour.d.ts +1 -0
  280. package/lib/typescript/module/types/WebSocketBehaviour.d.ts.map +1 -0
  281. package/lib/typescript/module/types/index.d.ts +6 -0
  282. package/lib/typescript/module/types/index.d.ts.map +1 -0
  283. package/lib/typescript/module/types/us_listen_socket.d.ts +7 -0
  284. package/lib/typescript/module/types/us_listen_socket.d.ts.map +1 -0
  285. package/lib/typescript/module/types/us_socket.d.ts +7 -0
  286. package/lib/typescript/module/types/us_socket.d.ts.map +1 -0
  287. package/lib/typescript/module/types/us_socket_context_t.d.ts +7 -0
  288. package/lib/typescript/module/types/us_socket_context_t.d.ts.map +1 -0
  289. package/lib/typescript/tsconfig.tsbuildinfo +1 -0
  290. package/package.json +62 -0
  291. package/src/_internal/native-modules/NativeUwsReactNative.ts +40 -0
  292. package/src/index.ts +2 -0
  293. package/src/modules/App.ts +14 -0
  294. package/src/modules/CompressOptions.ts +101 -0
  295. package/src/modules/EnvironmentVariables.ts +16 -0
  296. package/src/modules/ListenOptions.ts +4 -0
  297. package/src/modules/SSLApp.ts +13 -0
  298. package/src/modules/getParts.ts +29 -0
  299. package/src/modules/index.ts +8 -0
  300. package/src/modules/us_listen_socket_close.ts +15 -0
  301. package/src/modules/us_socket_local_port.ts +16 -0
  302. package/src/types/AppDescriptor.ts +7 -0
  303. package/src/types/AppOptions.ts +22 -0
  304. package/src/types/HttpRequest.ts +74 -0
  305. package/src/types/HttpResponse.ts +309 -0
  306. package/src/types/HttpRouterOptions.ts +24 -0
  307. package/src/types/MultipartField.ts +6 -0
  308. package/src/types/RecognizedString.ts +11 -0
  309. package/src/types/TemplatedApp.ts +285 -0
  310. package/src/types/WebSocket.ts +147 -0
  311. package/src/types/WebSocketBehaviour.ts +137 -0
  312. package/src/types/index.ts +12 -0
  313. package/src/types/us_listen_socket.ts +6 -0
  314. package/src/types/us_socket.ts +6 -0
  315. package/src/types/us_socket_context_t.ts +6 -0
@@ -0,0 +1,605 @@
1
+ /*
2
+ * Authored by Alex Hultman, 2018-2025.
3
+ * Intellectual property of third-party.
4
+
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #ifndef UWS_HTTPRESPONSE_H
19
+ #define UWS_HTTPRESPONSE_H
20
+
21
+ /* An HttpResponse is the channel on which you send back a response */
22
+
23
+ #include "AsyncSocket.h"
24
+ #include "HttpResponseData.h"
25
+ #include "HttpContext.h"
26
+ #include "HttpContextData.h"
27
+ #include "Utilities.h"
28
+
29
+ #include "WebSocketExtensions.h"
30
+ #include "WebSocketHandshake.h"
31
+ #include "WebSocket.h"
32
+ #include "WebSocketContextData.h"
33
+
34
+ #include "MoveOnlyFunction.h"
35
+
36
+ /* todo: tryWrite is missing currently, only send smaller segments with write */
37
+
38
+ namespace uWS {
39
+
40
+ /* Some pre-defined status constants to use with writeStatus */
41
+ static const char *HTTP_200_OK = "200 OK";
42
+
43
+ /* The general timeout for HTTP sockets */
44
+ static const int HTTP_TIMEOUT_S = 10;
45
+
46
+ template <bool SSL>
47
+ struct HttpResponse : public AsyncSocket<SSL> {
48
+ /* Solely used for getHttpResponseData() */
49
+ template <bool> friend struct TemplatedApp;
50
+ typedef AsyncSocket<SSL> Super;
51
+ private:
52
+ HttpResponseData<SSL> *getHttpResponseData() {
53
+ return (HttpResponseData<SSL> *) Super::getAsyncSocketData();
54
+ }
55
+
56
+ /* Write an unsigned 32-bit integer in hex */
57
+ void writeUnsignedHex(unsigned int value) {
58
+ /* Buf really only needs to be 8 long but building with
59
+ * -mavx2, GCC still wants to overstep it so made it 16 */
60
+ char buf[16];
61
+ int length = utils::u32toaHex(value, buf);
62
+
63
+ /* For now we do this copy */
64
+ Super::write(buf, length);
65
+ }
66
+
67
+ /* Write an unsigned 64-bit integer */
68
+ void writeUnsigned64(uint64_t value) {
69
+ char buf[20];
70
+ int length = utils::u64toa(value, buf);
71
+
72
+ /* For now we do this copy */
73
+ Super::write(buf, length);
74
+ }
75
+
76
+ /* Called only once per request */
77
+ void writeMark() {
78
+ /* Date is always written */
79
+ writeHeader("Date", std::string_view(((LoopData *) us_loop_ext(us_socket_context_loop(SSL, (us_socket_context(SSL, (us_socket_t *) this)))))->date, 29));
80
+
81
+ /* You can disable this altogether */
82
+ #ifndef UWS_HTTPRESPONSE_NO_WRITEMARK
83
+ if (!Super::getLoopData()->noMark) {
84
+ /* We only expose major version */
85
+ writeHeader("uWebSockets", "20");
86
+ }
87
+ #endif
88
+ }
89
+
90
+ /* Returns true on success, indicating that it might be feasible to write more data.
91
+ * Will start timeout if stream reaches totalSize or write failure. */
92
+ bool internalEnd(std::string_view data, uintmax_t totalSize, bool optional, bool allowContentLength = true, bool closeConnection = false) {
93
+ /* Write status if not already done */
94
+ writeStatus(HTTP_200_OK);
95
+
96
+ /* If no total size given then assume this chunk is everything */
97
+ if (!totalSize) {
98
+ totalSize = data.length();
99
+ }
100
+
101
+ HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
102
+
103
+ /* In some cases, such as when refusing huge data we want to close the connection when drained */
104
+ if (closeConnection) {
105
+
106
+ /* HTTP 1.1 must send this back unless the client already sent it to us.
107
+ * It is a connection close when either of the two parties say so but the
108
+ * one party must tell the other one so.
109
+ *
110
+ * This check also serves to limit writing the header only once. */
111
+ if ((httpResponseData->state & HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE) == 0) {
112
+ writeHeader("Connection", "close");
113
+ }
114
+
115
+ httpResponseData->state |= HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE;
116
+ }
117
+
118
+ if (httpResponseData->state & HttpResponseData<SSL>::HTTP_WRITE_CALLED) {
119
+
120
+ /* We do not have tryWrite-like functionalities, so ignore optional in this path */
121
+
122
+ /* Do not allow sending 0 chunk here */
123
+ if (data.length()) {
124
+ Super::write("\r\n", 2);
125
+ writeUnsignedHex((unsigned int) data.length());
126
+ Super::write("\r\n", 2);
127
+
128
+ /* Ignoring optional for now */
129
+ Super::write(data.data(), (int) data.length());
130
+ }
131
+
132
+ /* Terminating 0 chunk */
133
+ Super::write("\r\n0\r\n\r\n", 7);
134
+
135
+ httpResponseData->markDone();
136
+
137
+ /* We need to check if we should close this socket here now */
138
+ if (!Super::isCorked()) {
139
+ if (httpResponseData->state & HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE) {
140
+ if ((httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) == 0) {
141
+ if (((AsyncSocket<SSL> *) this)->getBufferedAmount() == 0) {
142
+ ((AsyncSocket<SSL> *) this)->shutdown();
143
+ /* We need to force close after sending FIN since we want to hinder
144
+ * clients from keeping to send their huge data */
145
+ ((AsyncSocket<SSL> *) this)->close();
146
+ return true;
147
+ }
148
+ }
149
+ }
150
+ }
151
+
152
+ /* tryEnd can never fail when in chunked mode, since we do not have tryWrite (yet), only write */
153
+ Super::timeout(HTTP_TIMEOUT_S);
154
+ return true;
155
+ } else {
156
+ /* Write content-length on first call */
157
+ if (!(httpResponseData->state & HttpResponseData<SSL>::HTTP_END_CALLED)) {
158
+ /* Write mark, this propagates to WebSockets too */
159
+ writeMark();
160
+
161
+ /* WebSocket upgrades does not allow content-length */
162
+ if (allowContentLength) {
163
+ /* Even zero is a valid content-length */
164
+ Super::write("Content-Length: ", 16);
165
+ writeUnsigned64(totalSize);
166
+ Super::write("\r\n\r\n", 4);
167
+ } else {
168
+ Super::write("\r\n", 2);
169
+ }
170
+
171
+ /* Mark end called */
172
+ httpResponseData->state |= HttpResponseData<SSL>::HTTP_END_CALLED;
173
+ }
174
+
175
+ /* Even if we supply no new data to write, its failed boolean is useful to know
176
+ * if it failed to drain any prior failed header writes */
177
+
178
+ /* Write as much as possible without causing backpressure */
179
+ size_t written = 0;
180
+ bool failed = false;
181
+ while (written < data.length() && !failed) {
182
+ /* uSockets only deals with int sizes, so pass chunks of max signed int size */
183
+ auto writtenFailed = Super::write(data.data() + written, (int) std::min<size_t>(data.length() - written, INT_MAX), optional);
184
+
185
+ written += (size_t) writtenFailed.first;
186
+ failed = writtenFailed.second;
187
+ }
188
+
189
+ httpResponseData->offset += written;
190
+
191
+ /* Success is when we wrote the entire thing without any failures */
192
+ bool success = written == data.length() && !failed;
193
+
194
+ /* If we are now at the end, start a timeout. Also start a timeout if we failed. */
195
+ if (!success || httpResponseData->offset == totalSize) {
196
+ Super::timeout(HTTP_TIMEOUT_S);
197
+ }
198
+
199
+ /* Remove onAborted, onWritable function and mark done if we reach the end, or if we were given no data (faked size like in HEAD response) */
200
+ /* I need to figure out if this line should rather be simply httpResponseData->offset == data.length() */
201
+ /* No that can't be right, tryEnd with fake length should not complete the response even if the smaller chunk wrote in one go */
202
+ /* Possibly need to separate endWithoutBody and tryEnd with fake length into two separate calls with a boolean that explicitly marks isHeadOnly */
203
+ if (httpResponseData->offset == totalSize || !data.length()) {
204
+ httpResponseData->markDone();
205
+
206
+ /* We need to check if we should close this socket here now */
207
+ if (!Super::isCorked()) {
208
+ if (httpResponseData->state & HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE) {
209
+ if ((httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) == 0) {
210
+ if (((AsyncSocket<SSL> *) this)->getBufferedAmount() == 0) {
211
+ ((AsyncSocket<SSL> *) this)->shutdown();
212
+ /* We need to force close after sending FIN since we want to hinder
213
+ * clients from keeping to send their huge data */
214
+ ((AsyncSocket<SSL> *) this)->close();
215
+ }
216
+ }
217
+ }
218
+ }
219
+ }
220
+
221
+ return success;
222
+ }
223
+ }
224
+
225
+ public:
226
+ /* If we have proxy support; returns the proxed source address as reported by the proxy. */
227
+ #ifdef UWS_WITH_PROXY
228
+ std::string_view getProxiedRemoteAddress() {
229
+ return getHttpResponseData()->proxyParser.getSourceAddress();
230
+ }
231
+
232
+ std::string_view getProxiedRemoteAddressAsText() {
233
+ return Super::addressAsText(getProxiedRemoteAddress());
234
+ }
235
+
236
+ unsigned int getProxiedRemotePort() {
237
+ return getHttpResponseData()->proxyParser.getSourcePort();
238
+ }
239
+ #endif
240
+
241
+ /* Manually upgrade to WebSocket. Typically called in upgrade handler. Immediately calls open handler.
242
+ * NOTE: Will invalidate 'this' as socket might change location in memory. Throw away after use. */
243
+ template <typename UserData>
244
+ void upgrade(UserData &&userData, std::string_view secWebSocketKey, std::string_view secWebSocketProtocol,
245
+ std::string_view secWebSocketExtensions,
246
+ struct us_socket_context_t *webSocketContext) {
247
+
248
+ /* Extract needed parameters from WebSocketContextData */
249
+ WebSocketContextData<SSL, UserData> *webSocketContextData = (WebSocketContextData<SSL, UserData> *) us_socket_context_ext(SSL, webSocketContext);
250
+
251
+ /* Note: OpenSSL can be used here to speed this up somewhat */
252
+ char secWebSocketAccept[29] = {};
253
+ WebSocketHandshake::generate(secWebSocketKey.data(), secWebSocketAccept);
254
+
255
+ writeStatus("101 Switching Protocols")
256
+ ->writeHeader("Upgrade", "websocket")
257
+ ->writeHeader("Connection", "Upgrade")
258
+ ->writeHeader("Sec-WebSocket-Accept", secWebSocketAccept);
259
+
260
+ /* Select first subprotocol if present */
261
+ if (secWebSocketProtocol.length()) {
262
+ writeHeader("Sec-WebSocket-Protocol", secWebSocketProtocol.substr(0, secWebSocketProtocol.find(',')));
263
+ }
264
+
265
+ /* Negotiate compression */
266
+ bool perMessageDeflate = false;
267
+ CompressOptions compressOptions = CompressOptions::DISABLED;
268
+ if (secWebSocketExtensions.length() && webSocketContextData->compression != DISABLED) {
269
+
270
+ /* Make sure to map SHARED_DECOMPRESSOR to windowBits = 0, not 1 */
271
+ int wantedInflationWindow = 0;
272
+ if ((webSocketContextData->compression & CompressOptions::_DECOMPRESSOR_MASK) != CompressOptions::SHARED_DECOMPRESSOR) {
273
+ wantedInflationWindow = (webSocketContextData->compression & CompressOptions::_DECOMPRESSOR_MASK) >> 8;
274
+ }
275
+
276
+ /* Map from selected compressor (this automatically maps SHARED_COMPRESSOR to windowBits 0, not 1) */
277
+ int wantedCompressionWindow = (webSocketContextData->compression & CompressOptions::_COMPRESSOR_MASK) >> 4;
278
+
279
+ auto [negCompression, negCompressionWindow, negInflationWindow, negResponse] =
280
+ negotiateCompression(true, wantedCompressionWindow, wantedInflationWindow,
281
+ secWebSocketExtensions);
282
+
283
+ if (negCompression) {
284
+ perMessageDeflate = true;
285
+
286
+ /* Map from negotiated windowBits to compressor and decompressor */
287
+ if (negCompressionWindow == 0) {
288
+ compressOptions = CompressOptions::SHARED_COMPRESSOR;
289
+ } else {
290
+ compressOptions = (CompressOptions) ((uint32_t) (negCompressionWindow << 4)
291
+ | (uint32_t) (negCompressionWindow - 7));
292
+
293
+ /* If we are dedicated and have the 3kb then correct any 4kb to 3kb,
294
+ * (they both share the windowBits = 9) */
295
+ if (webSocketContextData->compression & DEDICATED_COMPRESSOR_3KB) {
296
+ compressOptions = DEDICATED_COMPRESSOR_3KB;
297
+ }
298
+ }
299
+
300
+ /* Here we modify the above compression with negotiated decompressor */
301
+ if (negInflationWindow == 0) {
302
+ compressOptions = CompressOptions(compressOptions | CompressOptions::SHARED_DECOMPRESSOR);
303
+ } else {
304
+ compressOptions = CompressOptions(compressOptions | (negInflationWindow << 8));
305
+ }
306
+
307
+ writeHeader("Sec-WebSocket-Extensions", negResponse);
308
+ }
309
+ }
310
+
311
+ internalEnd({nullptr, 0}, 0, false, false);
312
+
313
+ /* Grab the httpContext from res */
314
+ HttpContext<SSL> *httpContext = (HttpContext<SSL> *) us_socket_context(SSL, (struct us_socket_t *) this);
315
+
316
+ /* Move any backpressure out of HttpResponse */
317
+ BackPressure backpressure(std::move(((AsyncSocketData<SSL> *) getHttpResponseData())->buffer));
318
+
319
+ /* Destroy HttpResponseData */
320
+ getHttpResponseData()->~HttpResponseData();
321
+
322
+ /* Before we adopt and potentially change socket, check if we are corked */
323
+ bool wasCorked = Super::isCorked();
324
+
325
+ /* Adopting a socket invalidates it, do not rely on it directly to carry any data */
326
+ WebSocket<SSL, true, UserData> *webSocket = (WebSocket<SSL, true, UserData> *) us_socket_context_adopt_socket(SSL,
327
+ (us_socket_context_t *) webSocketContext, (us_socket_t *) this, sizeof(WebSocketData) + sizeof(UserData));
328
+
329
+ /* For whatever reason we were corked, update cork to the new socket */
330
+ if (wasCorked) {
331
+ webSocket->AsyncSocket<SSL>::corkUnchecked();
332
+ }
333
+
334
+ /* Initialize websocket with any moved backpressure intact */
335
+ webSocket->init(perMessageDeflate, compressOptions, std::move(backpressure));
336
+
337
+ /* We should only mark this if inside the parser; if upgrading "async" we cannot set this */
338
+ HttpContextData<SSL> *httpContextData = httpContext->getSocketContextData();
339
+ if (httpContextData->isParsingHttp) {
340
+ /* We need to tell the Http parser that we changed socket */
341
+ httpContextData->upgradedWebSocket = webSocket;
342
+ }
343
+
344
+ /* Arm maxLifetime timeout */
345
+ us_socket_long_timeout(SSL, (us_socket_t *) webSocket, webSocketContextData->maxLifetime);
346
+
347
+ /* Arm idleTimeout */
348
+ us_socket_timeout(SSL, (us_socket_t *) webSocket, webSocketContextData->idleTimeoutComponents.first);
349
+
350
+ /* Move construct the UserData right before calling open handler */
351
+ new (webSocket->getUserData()) UserData(std::move(userData));
352
+
353
+ /* Emit open event and start the timeout */
354
+ if (webSocketContextData->openHandler) {
355
+ webSocketContextData->openHandler(webSocket);
356
+ }
357
+ }
358
+
359
+ /* Immediately terminate this Http response */
360
+ using Super::close;
361
+
362
+ /* See AsyncSocket */
363
+ using Super::getRemoteAddress;
364
+ using Super::getRemoteAddressAsText;
365
+ using Super::getRemotePort;
366
+ using Super::getNativeHandle;
367
+
368
+ /* Throttle reads and writes */
369
+ HttpResponse *pause() {
370
+ Super::pause();
371
+ Super::timeout(0);
372
+ return this;
373
+ }
374
+
375
+ HttpResponse *resume() {
376
+ Super::resume();
377
+ Super::timeout(HTTP_TIMEOUT_S);
378
+ return this;
379
+ }
380
+
381
+ /* Note: Headers are not checked in regards to timeout.
382
+ * We only check when you actively push data or end the request */
383
+
384
+ /* Write 100 Continue, can be done any amount of times */
385
+ HttpResponse *writeContinue() {
386
+ Super::write("HTTP/1.1 100 Continue\r\n\r\n", 25);
387
+ return this;
388
+ }
389
+
390
+ /* Write the HTTP status */
391
+ HttpResponse *writeStatus(std::string_view status) {
392
+ HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
393
+
394
+ /* Do not allow writing more than one status */
395
+ if (httpResponseData->state & HttpResponseData<SSL>::HTTP_STATUS_CALLED) {
396
+ return this;
397
+ }
398
+
399
+ /* Update status */
400
+ httpResponseData->state |= HttpResponseData<SSL>::HTTP_STATUS_CALLED;
401
+
402
+ Super::write("HTTP/1.1 ", 9);
403
+ Super::write(status.data(), (int) status.length());
404
+ Super::write("\r\n", 2);
405
+ return this;
406
+ }
407
+
408
+ /* Write an HTTP header with string value */
409
+ HttpResponse *writeHeader(std::string_view key, std::string_view value) {
410
+ writeStatus(HTTP_200_OK);
411
+
412
+ Super::write(key.data(), (int) key.length());
413
+ Super::write(": ", 2);
414
+ Super::write(value.data(), (int) value.length());
415
+ Super::write("\r\n", 2);
416
+ return this;
417
+ }
418
+
419
+ /* Write an HTTP header with unsigned int value */
420
+ HttpResponse *writeHeader(std::string_view key, uint64_t value) {
421
+ writeStatus(HTTP_200_OK);
422
+
423
+ Super::write(key.data(), (int) key.length());
424
+ Super::write(": ", 2);
425
+ writeUnsigned64(value);
426
+ Super::write("\r\n", 2);
427
+ return this;
428
+ }
429
+
430
+ /* End without a body (no content-length) or end with a spoofed content-length. */
431
+ void endWithoutBody(std::optional<size_t> reportedContentLength = std::nullopt, bool closeConnection = false) {
432
+ if (reportedContentLength.has_value()) {
433
+ internalEnd({nullptr, 0}, reportedContentLength.value(), false, true, closeConnection);
434
+ } else {
435
+ internalEnd({nullptr, 0}, 0, false, false, closeConnection);
436
+ }
437
+ }
438
+
439
+ /* End the response with an optional data chunk. Always starts a timeout. */
440
+ void end(std::string_view data = {}, bool closeConnection = false) {
441
+ internalEnd(data, data.length(), false, true, closeConnection);
442
+ }
443
+
444
+ /* Try and end the response. Returns [true, true] on success.
445
+ * Starts a timeout in some cases. Returns [ok, hasResponded] */
446
+ std::pair<bool, bool> tryEnd(std::string_view data, uintmax_t totalSize = 0, bool closeConnection = false) {
447
+ bool ok = internalEnd(data, totalSize, true, true, closeConnection);
448
+ return {ok, hasResponded()};
449
+ }
450
+
451
+ /* Write parts of the response in chunking fashion. Starts timeout if failed. */
452
+ bool write(std::string_view data) {
453
+ writeStatus(HTTP_200_OK);
454
+
455
+ /* Do not allow sending 0 chunks, they mark end of response */
456
+ if (!data.length()) {
457
+ /* If you called us, then according to you it was fine to call us so it's fine to still call us */
458
+ return true;
459
+ }
460
+
461
+ HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
462
+
463
+ if (!(httpResponseData->state & HttpResponseData<SSL>::HTTP_WRITE_CALLED)) {
464
+ /* Write mark on first call to write */
465
+ writeMark();
466
+
467
+ writeHeader("Transfer-Encoding", "chunked");
468
+ httpResponseData->state |= HttpResponseData<SSL>::HTTP_WRITE_CALLED;
469
+ }
470
+
471
+ Super::write("\r\n", 2);
472
+ writeUnsignedHex((unsigned int) data.length());
473
+ Super::write("\r\n", 2);
474
+
475
+ auto [written, failed] = Super::write(data.data(), (int) data.length());
476
+ if (failed) {
477
+ Super::timeout(HTTP_TIMEOUT_S);
478
+ }
479
+
480
+ /* If we did not fail the write, accept more */
481
+ return !failed;
482
+ }
483
+
484
+ /* Get the current byte write offset for this Http response */
485
+ uintmax_t getWriteOffset() {
486
+ HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
487
+
488
+ return httpResponseData->offset;
489
+ }
490
+
491
+ /* Get the remaining body length if set via content-length, UINT64_MAX if transfer-encoding is chunked, or 0 if no body */
492
+ uint64_t maxRemainingBodyLength() {
493
+ HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
494
+
495
+ return httpResponseData->maxRemainingBodyLength();
496
+ }
497
+
498
+ /* If you are messing around with sendfile you might want to override the offset. */
499
+ void overrideWriteOffset(uintmax_t offset) {
500
+ HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
501
+
502
+ httpResponseData->offset = offset;
503
+ }
504
+
505
+ /* Checking if we have fully responded and are ready for another request */
506
+ bool hasResponded() {
507
+ HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
508
+
509
+ return !(httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING);
510
+ }
511
+
512
+ /* Corks the response if possible. Leaves already corked socket be. */
513
+ HttpResponse *cork(MoveOnlyFunction<void()> &&handler) {
514
+ if (!Super::isCorked() && Super::canCork()) {
515
+ LoopData *loopData = Super::getLoopData();
516
+ Super::cork();
517
+ handler();
518
+
519
+ /* The only way we could possibly have changed the corked socket during handler call, would be if
520
+ * the HTTP socket was upgraded to WebSocket and caused a realloc. Because of this we cannot use "this"
521
+ * from here downwards. The corking is done with corkUnchecked() in upgrade. It steals cork. */
522
+ auto *newCorkedSocket = loopData->corkedSocket;
523
+
524
+ /* If nobody is corked, it means most probably that large amounts of data has
525
+ * been written and the cork buffer has already been sent off and uncorked.
526
+ * We are done here, if that is the case. */
527
+ if (!newCorkedSocket) {
528
+ return this;
529
+ }
530
+
531
+ /* Timeout on uncork failure, since most writes will succeed while corked */
532
+ auto [written, failed] = static_cast<Super *>(newCorkedSocket)->uncork();
533
+
534
+ /* If we are no longer an HTTP socket then early return the new "this".
535
+ * We don't want to even overwrite timeout as it is set in upgrade already. */
536
+ if (this != newCorkedSocket) {
537
+ return static_cast<HttpResponse *>(newCorkedSocket);
538
+ }
539
+
540
+ if (failed) {
541
+ /* For now we only have one single timeout so let's use it */
542
+ /* This behavior should equal the behavior in HttpContext when uncorking fails */
543
+ Super::timeout(HTTP_TIMEOUT_S);
544
+ }
545
+
546
+ /* If we have no backbuffer and we are connection close and we responded fully then close */
547
+ HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
548
+ if (httpResponseData->state & HttpResponseData<SSL>::HTTP_CONNECTION_CLOSE) {
549
+ if ((httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) == 0) {
550
+ if (((AsyncSocket<SSL> *) this)->getBufferedAmount() == 0) {
551
+ ((AsyncSocket<SSL> *) this)->shutdown();
552
+ /* We need to force close after sending FIN since we want to hinder
553
+ * clients from keeping to send their huge data */
554
+ ((AsyncSocket<SSL> *) this)->close();
555
+ }
556
+ }
557
+ }
558
+ } else {
559
+ /* We are already corked, or can't cork so let's just call the handler */
560
+ handler();
561
+ }
562
+
563
+ return this;
564
+ }
565
+
566
+ /* Attach handler for writable HTTP response */
567
+ HttpResponse *onWritable(MoveOnlyFunction<bool(uintmax_t)> &&handler) {
568
+ HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
569
+
570
+ httpResponseData->onWritable = std::move(handler);
571
+ return this;
572
+ }
573
+
574
+ /* Attach handler for aborted HTTP request */
575
+ HttpResponse *onAborted(MoveOnlyFunction<void()> &&handler) {
576
+ HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
577
+
578
+ httpResponseData->onAborted = std::move(handler);
579
+ return this;
580
+ }
581
+
582
+ /* Attach a read handler for data sent. Will be called with FIN set true if last segment. */
583
+ void onData(MoveOnlyFunction<void(std::string_view, bool)> &&handler) {
584
+ if (handler) {
585
+ onDataV2([handler = std::move(handler)](std::string_view chunk, uint64_t maxRemainingBodyLength) mutable {
586
+ handler(chunk, maxRemainingBodyLength == 0);
587
+ });
588
+ } else {
589
+ onDataV2(nullptr);
590
+ }
591
+ }
592
+
593
+ /* Attach a read handler for data sent. Will be called with maxRemainingBodyLength. maxRemainingBodyLength == 0 is the same as isLast. */
594
+ void onDataV2(MoveOnlyFunction<void(std::string_view, uint64_t)> &&handler) {
595
+ HttpResponseData<SSL> *data = getHttpResponseData();
596
+ data->inStream = std::move(handler);
597
+
598
+ /* Always reset this counter here */
599
+ data->received_bytes_per_timeout = 0;
600
+ }
601
+ };
602
+
603
+ }
604
+
605
+ #endif // UWS_HTTPRESPONSE_H