@push.rocks/smartproxy 20.0.1 → 21.1.0

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 (164) hide show
  1. package/changelog.md +26 -0
  2. package/dist_ts/core/utils/proxy-protocol.d.ts +5 -17
  3. package/dist_ts/core/utils/proxy-protocol.js +13 -97
  4. package/dist_ts/core/utils/websocket-utils.d.ts +6 -7
  5. package/dist_ts/core/utils/websocket-utils.js +10 -66
  6. package/dist_ts/detection/detectors/http-detector-v2.d.ts +33 -0
  7. package/dist_ts/detection/detectors/http-detector-v2.js +87 -0
  8. package/dist_ts/detection/detectors/http-detector.d.ts +33 -0
  9. package/dist_ts/detection/detectors/http-detector.js +89 -0
  10. package/dist_ts/detection/detectors/quick-detector.d.ts +28 -0
  11. package/dist_ts/detection/detectors/quick-detector.js +131 -0
  12. package/dist_ts/detection/detectors/routing-extractor.d.ts +28 -0
  13. package/dist_ts/detection/detectors/routing-extractor.js +122 -0
  14. package/dist_ts/detection/detectors/tls-detector-v2.d.ts +33 -0
  15. package/dist_ts/detection/detectors/tls-detector-v2.js +80 -0
  16. package/dist_ts/detection/detectors/tls-detector.d.ts +33 -0
  17. package/dist_ts/detection/detectors/tls-detector.js +106 -0
  18. package/dist_ts/detection/index.d.ts +17 -0
  19. package/dist_ts/detection/index.js +22 -0
  20. package/dist_ts/detection/models/detection-types.d.ts +87 -0
  21. package/dist_ts/detection/models/detection-types.js +5 -0
  22. package/dist_ts/detection/models/interfaces.d.ts +97 -0
  23. package/dist_ts/detection/models/interfaces.js +5 -0
  24. package/dist_ts/detection/protocol-detector-v2.d.ts +46 -0
  25. package/dist_ts/detection/protocol-detector-v2.js +116 -0
  26. package/dist_ts/detection/protocol-detector.d.ts +74 -0
  27. package/dist_ts/detection/protocol-detector.js +173 -0
  28. package/dist_ts/detection/utils/buffer-utils.d.ts +61 -0
  29. package/dist_ts/detection/utils/buffer-utils.js +127 -0
  30. package/dist_ts/detection/utils/fragment-manager.d.ts +31 -0
  31. package/dist_ts/detection/utils/fragment-manager.js +53 -0
  32. package/dist_ts/detection/utils/parser-utils.d.ts +42 -0
  33. package/dist_ts/detection/utils/parser-utils.js +63 -0
  34. package/dist_ts/index.d.ts +2 -1
  35. package/dist_ts/index.js +3 -2
  36. package/dist_ts/protocols/common/fragment-handler.d.ts +73 -0
  37. package/dist_ts/protocols/common/fragment-handler.js +117 -0
  38. package/dist_ts/protocols/common/index.d.ts +7 -0
  39. package/dist_ts/protocols/common/index.js +8 -0
  40. package/dist_ts/protocols/common/types.d.ts +68 -0
  41. package/dist_ts/protocols/common/types.js +7 -0
  42. package/dist_ts/protocols/http/constants.d.ts +119 -0
  43. package/dist_ts/protocols/http/constants.js +200 -0
  44. package/dist_ts/protocols/http/index.d.ts +7 -0
  45. package/dist_ts/protocols/http/index.js +8 -0
  46. package/dist_ts/protocols/http/parser.d.ts +58 -0
  47. package/dist_ts/protocols/http/parser.js +184 -0
  48. package/dist_ts/protocols/http/types.d.ts +62 -0
  49. package/dist_ts/protocols/http/types.js +5 -0
  50. package/dist_ts/protocols/index.d.ts +11 -0
  51. package/dist_ts/protocols/index.js +12 -0
  52. package/dist_ts/protocols/proxy/index.d.ts +6 -0
  53. package/dist_ts/protocols/proxy/index.js +7 -0
  54. package/dist_ts/protocols/proxy/parser.d.ts +44 -0
  55. package/dist_ts/protocols/proxy/parser.js +153 -0
  56. package/dist_ts/protocols/proxy/types.d.ts +47 -0
  57. package/dist_ts/protocols/proxy/types.js +6 -0
  58. package/dist_ts/protocols/tls/alerts/index.d.ts +4 -0
  59. package/dist_ts/protocols/tls/alerts/index.js +5 -0
  60. package/dist_ts/protocols/tls/alerts/tls-alert.d.ts +150 -0
  61. package/dist_ts/protocols/tls/alerts/tls-alert.js +226 -0
  62. package/dist_ts/protocols/tls/constants.d.ts +122 -0
  63. package/dist_ts/protocols/tls/constants.js +135 -0
  64. package/dist_ts/protocols/tls/index.d.ts +12 -0
  65. package/dist_ts/protocols/tls/index.js +27 -0
  66. package/dist_ts/protocols/tls/parser.d.ts +53 -0
  67. package/dist_ts/protocols/tls/parser.js +294 -0
  68. package/dist_ts/protocols/tls/sni/client-hello-parser.d.ts +100 -0
  69. package/dist_ts/protocols/tls/sni/client-hello-parser.js +463 -0
  70. package/dist_ts/protocols/tls/sni/index.d.ts +5 -0
  71. package/dist_ts/protocols/tls/sni/index.js +6 -0
  72. package/dist_ts/protocols/tls/sni/sni-extraction.d.ts +58 -0
  73. package/dist_ts/protocols/tls/sni/sni-extraction.js +275 -0
  74. package/dist_ts/protocols/tls/types.d.ts +65 -0
  75. package/dist_ts/protocols/tls/types.js +5 -0
  76. package/dist_ts/protocols/tls/utils/index.d.ts +4 -0
  77. package/dist_ts/protocols/tls/utils/index.js +5 -0
  78. package/dist_ts/protocols/tls/utils/tls-utils.d.ts +158 -0
  79. package/dist_ts/protocols/tls/utils/tls-utils.js +187 -0
  80. package/dist_ts/protocols/websocket/constants.d.ts +55 -0
  81. package/dist_ts/protocols/websocket/constants.js +58 -0
  82. package/dist_ts/protocols/websocket/index.d.ts +7 -0
  83. package/dist_ts/protocols/websocket/index.js +8 -0
  84. package/dist_ts/protocols/websocket/types.d.ts +47 -0
  85. package/dist_ts/protocols/websocket/types.js +5 -0
  86. package/dist_ts/protocols/websocket/utils.d.ts +25 -0
  87. package/dist_ts/protocols/websocket/utils.js +103 -0
  88. package/dist_ts/proxies/http-proxy/models/http-types.d.ts +25 -27
  89. package/dist_ts/proxies/http-proxy/models/http-types.js +24 -44
  90. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +5 -0
  91. package/dist_ts/proxies/smart-proxy/models/route-types.js +1 -1
  92. package/dist_ts/proxies/smart-proxy/route-connection-handler.js +81 -61
  93. package/dist_ts/proxies/smart-proxy/tls-manager.js +2 -1
  94. package/dist_ts/proxies/smart-proxy/utils/index.d.ts +1 -2
  95. package/dist_ts/proxies/smart-proxy/utils/index.js +3 -4
  96. package/dist_ts/proxies/smart-proxy/utils/route-helpers.d.ts +112 -8
  97. package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +231 -76
  98. package/dist_ts/tls/index.d.ts +5 -7
  99. package/dist_ts/tls/index.js +8 -11
  100. package/dist_ts/tls/sni/client-hello-parser.js +3 -2
  101. package/dist_ts/tls/sni/sni-handler.js +4 -4
  102. package/dist_ts/tls/utils/tls-utils.d.ts +1 -110
  103. package/dist_ts/tls/utils/tls-utils.js +4 -116
  104. package/package.json +17 -8
  105. package/readme.md +471 -2345
  106. package/readme.plan.md +0 -0
  107. package/ts/core/utils/proxy-protocol.ts +14 -131
  108. package/ts/core/utils/websocket-utils.ts +12 -60
  109. package/ts/detection/detectors/http-detector.ts +114 -0
  110. package/ts/detection/detectors/quick-detector.ts +148 -0
  111. package/ts/detection/detectors/routing-extractor.ts +147 -0
  112. package/ts/detection/detectors/tls-detector.ts +120 -0
  113. package/ts/detection/index.ts +25 -0
  114. package/ts/detection/models/detection-types.ts +102 -0
  115. package/ts/detection/models/interfaces.ts +115 -0
  116. package/ts/detection/protocol-detector.ts +230 -0
  117. package/ts/detection/utils/buffer-utils.ts +141 -0
  118. package/ts/detection/utils/fragment-manager.ts +64 -0
  119. package/ts/detection/utils/parser-utils.ts +77 -0
  120. package/ts/index.ts +3 -2
  121. package/ts/protocols/common/fragment-handler.ts +163 -0
  122. package/ts/protocols/common/index.ts +8 -0
  123. package/ts/protocols/common/types.ts +76 -0
  124. package/ts/protocols/http/constants.ts +219 -0
  125. package/ts/protocols/http/index.ts +8 -0
  126. package/ts/protocols/http/parser.ts +219 -0
  127. package/ts/protocols/http/types.ts +70 -0
  128. package/ts/protocols/index.ts +12 -0
  129. package/ts/protocols/proxy/index.ts +7 -0
  130. package/ts/protocols/proxy/parser.ts +183 -0
  131. package/ts/protocols/proxy/types.ts +53 -0
  132. package/ts/{tls → protocols/tls}/alerts/tls-alert.ts +1 -1
  133. package/ts/protocols/tls/index.ts +37 -0
  134. package/ts/protocols/tls/sni/index.ts +6 -0
  135. package/ts/{tls → protocols/tls}/utils/tls-utils.ts +1 -1
  136. package/ts/protocols/websocket/constants.ts +60 -0
  137. package/ts/protocols/websocket/index.ts +8 -0
  138. package/ts/protocols/websocket/types.ts +53 -0
  139. package/ts/protocols/websocket/utils.ts +98 -0
  140. package/ts/proxies/http-proxy/models/http-types.ts +29 -46
  141. package/ts/proxies/smart-proxy/models/interfaces.ts +7 -1
  142. package/ts/proxies/smart-proxy/models/route-types.ts +0 -1
  143. package/ts/proxies/smart-proxy/route-connection-handler.ts +91 -68
  144. package/ts/proxies/smart-proxy/tls-manager.ts +1 -0
  145. package/ts/proxies/smart-proxy/utils/index.ts +2 -13
  146. package/ts/proxies/smart-proxy/utils/route-helpers.ts +323 -86
  147. package/ts/tls/index.ts +8 -12
  148. package/ts/tls/sni/sni-handler.ts +3 -3
  149. package/ts/forwarding/config/forwarding-types.ts +0 -76
  150. package/ts/forwarding/config/index.ts +0 -26
  151. package/ts/forwarding/factory/forwarding-factory.ts +0 -189
  152. package/ts/forwarding/factory/index.ts +0 -5
  153. package/ts/forwarding/handlers/base-handler.ts +0 -155
  154. package/ts/forwarding/handlers/http-handler.ts +0 -163
  155. package/ts/forwarding/handlers/https-passthrough-handler.ts +0 -185
  156. package/ts/forwarding/handlers/https-terminate-to-http-handler.ts +0 -312
  157. package/ts/forwarding/handlers/https-terminate-to-https-handler.ts +0 -297
  158. package/ts/forwarding/handlers/index.ts +0 -9
  159. package/ts/forwarding/index.ts +0 -35
  160. package/ts/proxies/smart-proxy/utils/route-patterns.ts +0 -403
  161. /package/ts/{tls → protocols/tls}/alerts/index.ts +0 -0
  162. /package/ts/{tls → protocols/tls}/sni/client-hello-parser.ts +0 -0
  163. /package/ts/{tls → protocols/tls}/sni/sni-extraction.ts +0 -0
  164. /package/ts/{tls → protocols/tls}/utils/index.ts +0 -0
@@ -0,0 +1,219 @@
1
+ /**
2
+ * HTTP Protocol Constants
3
+ */
4
+
5
+ /**
6
+ * HTTP methods
7
+ */
8
+ export const HTTP_METHODS = [
9
+ 'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS', 'CONNECT', 'TRACE'
10
+ ] as const;
11
+
12
+ export type THttpMethod = typeof HTTP_METHODS[number];
13
+
14
+ /**
15
+ * HTTP version strings
16
+ */
17
+ export const HTTP_VERSIONS = ['HTTP/1.0', 'HTTP/1.1', 'HTTP/2', 'HTTP/3'] as const;
18
+
19
+ export type THttpVersion = typeof HTTP_VERSIONS[number];
20
+
21
+ /**
22
+ * HTTP status codes
23
+ */
24
+ export enum HttpStatus {
25
+ // 1xx Informational
26
+ CONTINUE = 100,
27
+ SWITCHING_PROTOCOLS = 101,
28
+ PROCESSING = 102,
29
+ EARLY_HINTS = 103,
30
+
31
+ // 2xx Success
32
+ OK = 200,
33
+ CREATED = 201,
34
+ ACCEPTED = 202,
35
+ NON_AUTHORITATIVE_INFORMATION = 203,
36
+ NO_CONTENT = 204,
37
+ RESET_CONTENT = 205,
38
+ PARTIAL_CONTENT = 206,
39
+ MULTI_STATUS = 207,
40
+ ALREADY_REPORTED = 208,
41
+ IM_USED = 226,
42
+
43
+ // 3xx Redirection
44
+ MULTIPLE_CHOICES = 300,
45
+ MOVED_PERMANENTLY = 301,
46
+ FOUND = 302,
47
+ SEE_OTHER = 303,
48
+ NOT_MODIFIED = 304,
49
+ USE_PROXY = 305,
50
+ TEMPORARY_REDIRECT = 307,
51
+ PERMANENT_REDIRECT = 308,
52
+
53
+ // 4xx Client Error
54
+ BAD_REQUEST = 400,
55
+ UNAUTHORIZED = 401,
56
+ PAYMENT_REQUIRED = 402,
57
+ FORBIDDEN = 403,
58
+ NOT_FOUND = 404,
59
+ METHOD_NOT_ALLOWED = 405,
60
+ NOT_ACCEPTABLE = 406,
61
+ PROXY_AUTHENTICATION_REQUIRED = 407,
62
+ REQUEST_TIMEOUT = 408,
63
+ CONFLICT = 409,
64
+ GONE = 410,
65
+ LENGTH_REQUIRED = 411,
66
+ PRECONDITION_FAILED = 412,
67
+ PAYLOAD_TOO_LARGE = 413,
68
+ URI_TOO_LONG = 414,
69
+ UNSUPPORTED_MEDIA_TYPE = 415,
70
+ RANGE_NOT_SATISFIABLE = 416,
71
+ EXPECTATION_FAILED = 417,
72
+ IM_A_TEAPOT = 418,
73
+ MISDIRECTED_REQUEST = 421,
74
+ UNPROCESSABLE_ENTITY = 422,
75
+ LOCKED = 423,
76
+ FAILED_DEPENDENCY = 424,
77
+ TOO_EARLY = 425,
78
+ UPGRADE_REQUIRED = 426,
79
+ PRECONDITION_REQUIRED = 428,
80
+ TOO_MANY_REQUESTS = 429,
81
+ REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
82
+ UNAVAILABLE_FOR_LEGAL_REASONS = 451,
83
+
84
+ // 5xx Server Error
85
+ INTERNAL_SERVER_ERROR = 500,
86
+ NOT_IMPLEMENTED = 501,
87
+ BAD_GATEWAY = 502,
88
+ SERVICE_UNAVAILABLE = 503,
89
+ GATEWAY_TIMEOUT = 504,
90
+ HTTP_VERSION_NOT_SUPPORTED = 505,
91
+ VARIANT_ALSO_NEGOTIATES = 506,
92
+ INSUFFICIENT_STORAGE = 507,
93
+ LOOP_DETECTED = 508,
94
+ NOT_EXTENDED = 510,
95
+ NETWORK_AUTHENTICATION_REQUIRED = 511,
96
+ }
97
+
98
+ /**
99
+ * HTTP status text mapping
100
+ */
101
+ export const HTTP_STATUS_TEXT: Record<HttpStatus, string> = {
102
+ // 1xx
103
+ [HttpStatus.CONTINUE]: 'Continue',
104
+ [HttpStatus.SWITCHING_PROTOCOLS]: 'Switching Protocols',
105
+ [HttpStatus.PROCESSING]: 'Processing',
106
+ [HttpStatus.EARLY_HINTS]: 'Early Hints',
107
+
108
+ // 2xx
109
+ [HttpStatus.OK]: 'OK',
110
+ [HttpStatus.CREATED]: 'Created',
111
+ [HttpStatus.ACCEPTED]: 'Accepted',
112
+ [HttpStatus.NON_AUTHORITATIVE_INFORMATION]: 'Non-Authoritative Information',
113
+ [HttpStatus.NO_CONTENT]: 'No Content',
114
+ [HttpStatus.RESET_CONTENT]: 'Reset Content',
115
+ [HttpStatus.PARTIAL_CONTENT]: 'Partial Content',
116
+ [HttpStatus.MULTI_STATUS]: 'Multi-Status',
117
+ [HttpStatus.ALREADY_REPORTED]: 'Already Reported',
118
+ [HttpStatus.IM_USED]: 'IM Used',
119
+
120
+ // 3xx
121
+ [HttpStatus.MULTIPLE_CHOICES]: 'Multiple Choices',
122
+ [HttpStatus.MOVED_PERMANENTLY]: 'Moved Permanently',
123
+ [HttpStatus.FOUND]: 'Found',
124
+ [HttpStatus.SEE_OTHER]: 'See Other',
125
+ [HttpStatus.NOT_MODIFIED]: 'Not Modified',
126
+ [HttpStatus.USE_PROXY]: 'Use Proxy',
127
+ [HttpStatus.TEMPORARY_REDIRECT]: 'Temporary Redirect',
128
+ [HttpStatus.PERMANENT_REDIRECT]: 'Permanent Redirect',
129
+
130
+ // 4xx
131
+ [HttpStatus.BAD_REQUEST]: 'Bad Request',
132
+ [HttpStatus.UNAUTHORIZED]: 'Unauthorized',
133
+ [HttpStatus.PAYMENT_REQUIRED]: 'Payment Required',
134
+ [HttpStatus.FORBIDDEN]: 'Forbidden',
135
+ [HttpStatus.NOT_FOUND]: 'Not Found',
136
+ [HttpStatus.METHOD_NOT_ALLOWED]: 'Method Not Allowed',
137
+ [HttpStatus.NOT_ACCEPTABLE]: 'Not Acceptable',
138
+ [HttpStatus.PROXY_AUTHENTICATION_REQUIRED]: 'Proxy Authentication Required',
139
+ [HttpStatus.REQUEST_TIMEOUT]: 'Request Timeout',
140
+ [HttpStatus.CONFLICT]: 'Conflict',
141
+ [HttpStatus.GONE]: 'Gone',
142
+ [HttpStatus.LENGTH_REQUIRED]: 'Length Required',
143
+ [HttpStatus.PRECONDITION_FAILED]: 'Precondition Failed',
144
+ [HttpStatus.PAYLOAD_TOO_LARGE]: 'Payload Too Large',
145
+ [HttpStatus.URI_TOO_LONG]: 'URI Too Long',
146
+ [HttpStatus.UNSUPPORTED_MEDIA_TYPE]: 'Unsupported Media Type',
147
+ [HttpStatus.RANGE_NOT_SATISFIABLE]: 'Range Not Satisfiable',
148
+ [HttpStatus.EXPECTATION_FAILED]: 'Expectation Failed',
149
+ [HttpStatus.IM_A_TEAPOT]: "I'm a teapot",
150
+ [HttpStatus.MISDIRECTED_REQUEST]: 'Misdirected Request',
151
+ [HttpStatus.UNPROCESSABLE_ENTITY]: 'Unprocessable Entity',
152
+ [HttpStatus.LOCKED]: 'Locked',
153
+ [HttpStatus.FAILED_DEPENDENCY]: 'Failed Dependency',
154
+ [HttpStatus.TOO_EARLY]: 'Too Early',
155
+ [HttpStatus.UPGRADE_REQUIRED]: 'Upgrade Required',
156
+ [HttpStatus.PRECONDITION_REQUIRED]: 'Precondition Required',
157
+ [HttpStatus.TOO_MANY_REQUESTS]: 'Too Many Requests',
158
+ [HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE]: 'Request Header Fields Too Large',
159
+ [HttpStatus.UNAVAILABLE_FOR_LEGAL_REASONS]: 'Unavailable For Legal Reasons',
160
+
161
+ // 5xx
162
+ [HttpStatus.INTERNAL_SERVER_ERROR]: 'Internal Server Error',
163
+ [HttpStatus.NOT_IMPLEMENTED]: 'Not Implemented',
164
+ [HttpStatus.BAD_GATEWAY]: 'Bad Gateway',
165
+ [HttpStatus.SERVICE_UNAVAILABLE]: 'Service Unavailable',
166
+ [HttpStatus.GATEWAY_TIMEOUT]: 'Gateway Timeout',
167
+ [HttpStatus.HTTP_VERSION_NOT_SUPPORTED]: 'HTTP Version Not Supported',
168
+ [HttpStatus.VARIANT_ALSO_NEGOTIATES]: 'Variant Also Negotiates',
169
+ [HttpStatus.INSUFFICIENT_STORAGE]: 'Insufficient Storage',
170
+ [HttpStatus.LOOP_DETECTED]: 'Loop Detected',
171
+ [HttpStatus.NOT_EXTENDED]: 'Not Extended',
172
+ [HttpStatus.NETWORK_AUTHENTICATION_REQUIRED]: 'Network Authentication Required',
173
+ };
174
+
175
+ /**
176
+ * Common HTTP headers
177
+ */
178
+ export const HTTP_HEADERS = {
179
+ // Request headers
180
+ HOST: 'host',
181
+ USER_AGENT: 'user-agent',
182
+ ACCEPT: 'accept',
183
+ ACCEPT_LANGUAGE: 'accept-language',
184
+ ACCEPT_ENCODING: 'accept-encoding',
185
+ AUTHORIZATION: 'authorization',
186
+ CACHE_CONTROL: 'cache-control',
187
+ CONNECTION: 'connection',
188
+ CONTENT_TYPE: 'content-type',
189
+ CONTENT_LENGTH: 'content-length',
190
+ COOKIE: 'cookie',
191
+
192
+ // Response headers
193
+ SET_COOKIE: 'set-cookie',
194
+ LOCATION: 'location',
195
+ SERVER: 'server',
196
+ DATE: 'date',
197
+ EXPIRES: 'expires',
198
+ LAST_MODIFIED: 'last-modified',
199
+ ETAG: 'etag',
200
+
201
+ // CORS headers
202
+ ACCESS_CONTROL_ALLOW_ORIGIN: 'access-control-allow-origin',
203
+ ACCESS_CONTROL_ALLOW_METHODS: 'access-control-allow-methods',
204
+ ACCESS_CONTROL_ALLOW_HEADERS: 'access-control-allow-headers',
205
+
206
+ // Security headers
207
+ STRICT_TRANSPORT_SECURITY: 'strict-transport-security',
208
+ X_CONTENT_TYPE_OPTIONS: 'x-content-type-options',
209
+ X_FRAME_OPTIONS: 'x-frame-options',
210
+ X_XSS_PROTECTION: 'x-xss-protection',
211
+ CONTENT_SECURITY_POLICY: 'content-security-policy',
212
+ } as const;
213
+
214
+ /**
215
+ * Get HTTP status text
216
+ */
217
+ export function getStatusText(status: HttpStatus): string {
218
+ return HTTP_STATUS_TEXT[status] || 'Unknown';
219
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * HTTP Protocol Module
3
+ * Generic HTTP protocol knowledge and parsing utilities
4
+ */
5
+
6
+ export * from './constants.js';
7
+ export * from './types.js';
8
+ export * from './parser.js';
@@ -0,0 +1,219 @@
1
+ /**
2
+ * HTTP Protocol Parser
3
+ * Generic HTTP parsing utilities
4
+ */
5
+
6
+ import { HTTP_METHODS, type THttpMethod, type THttpVersion } from './constants.js';
7
+ import type { IHttpRequestLine, IHttpHeader } from './types.js';
8
+
9
+ /**
10
+ * HTTP parser utilities
11
+ */
12
+ export class HttpParser {
13
+ /**
14
+ * Check if string is a valid HTTP method
15
+ */
16
+ static isHttpMethod(str: string): str is THttpMethod {
17
+ return HTTP_METHODS.includes(str as THttpMethod);
18
+ }
19
+
20
+ /**
21
+ * Parse HTTP request line
22
+ */
23
+ static parseRequestLine(line: string): IHttpRequestLine | null {
24
+ const parts = line.trim().split(' ');
25
+
26
+ if (parts.length !== 3) {
27
+ return null;
28
+ }
29
+
30
+ const [method, path, version] = parts;
31
+
32
+ // Validate method
33
+ if (!this.isHttpMethod(method)) {
34
+ return null;
35
+ }
36
+
37
+ // Validate version
38
+ if (!version.startsWith('HTTP/')) {
39
+ return null;
40
+ }
41
+
42
+ return {
43
+ method: method as THttpMethod,
44
+ path,
45
+ version: version as THttpVersion
46
+ };
47
+ }
48
+
49
+ /**
50
+ * Parse HTTP header line
51
+ */
52
+ static parseHeaderLine(line: string): IHttpHeader | null {
53
+ const colonIndex = line.indexOf(':');
54
+
55
+ if (colonIndex === -1) {
56
+ return null;
57
+ }
58
+
59
+ const name = line.slice(0, colonIndex).trim();
60
+ const value = line.slice(colonIndex + 1).trim();
61
+
62
+ if (!name) {
63
+ return null;
64
+ }
65
+
66
+ return { name, value };
67
+ }
68
+
69
+ /**
70
+ * Parse HTTP headers from lines
71
+ */
72
+ static parseHeaders(lines: string[]): Record<string, string> {
73
+ const headers: Record<string, string> = {};
74
+
75
+ for (const line of lines) {
76
+ const header = this.parseHeaderLine(line);
77
+ if (header) {
78
+ // Convert header names to lowercase for consistency
79
+ headers[header.name.toLowerCase()] = header.value;
80
+ }
81
+ }
82
+
83
+ return headers;
84
+ }
85
+
86
+ /**
87
+ * Extract domain from Host header value
88
+ */
89
+ static extractDomainFromHost(hostHeader: string): string {
90
+ // Remove port if present
91
+ const colonIndex = hostHeader.lastIndexOf(':');
92
+ if (colonIndex !== -1) {
93
+ // Check if it's not part of IPv6 address
94
+ const beforeColon = hostHeader.slice(0, colonIndex);
95
+ if (!beforeColon.includes(']')) {
96
+ return beforeColon;
97
+ }
98
+ }
99
+ return hostHeader;
100
+ }
101
+
102
+ /**
103
+ * Validate domain name
104
+ */
105
+ static isValidDomain(domain: string): boolean {
106
+ // Basic domain validation
107
+ if (!domain || domain.length > 253) {
108
+ return false;
109
+ }
110
+
111
+ // Check for valid characters and structure
112
+ const domainRegex = /^(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\.[A-Za-z0-9-]{1,63})*$/;
113
+ return domainRegex.test(domain);
114
+ }
115
+
116
+ /**
117
+ * Extract line from buffer
118
+ */
119
+ static extractLine(buffer: Buffer, offset: number = 0): { line: string; nextOffset: number } | null {
120
+ // Look for CRLF
121
+ const crlfIndex = buffer.indexOf('\r\n', offset);
122
+ if (crlfIndex === -1) {
123
+ // Look for just LF
124
+ const lfIndex = buffer.indexOf('\n', offset);
125
+ if (lfIndex === -1) {
126
+ return null;
127
+ }
128
+
129
+ return {
130
+ line: buffer.slice(offset, lfIndex).toString('utf8'),
131
+ nextOffset: lfIndex + 1
132
+ };
133
+ }
134
+
135
+ return {
136
+ line: buffer.slice(offset, crlfIndex).toString('utf8'),
137
+ nextOffset: crlfIndex + 2
138
+ };
139
+ }
140
+
141
+ /**
142
+ * Check if buffer contains printable ASCII
143
+ */
144
+ static isPrintableAscii(buffer: Buffer, length?: number): boolean {
145
+ const checkLength = Math.min(length || buffer.length, buffer.length);
146
+
147
+ for (let i = 0; i < checkLength; i++) {
148
+ const byte = buffer[i];
149
+ // Allow printable ASCII (32-126) plus tab (9), LF (10), and CR (13)
150
+ if (byte < 32 || byte > 126) {
151
+ if (byte !== 9 && byte !== 10 && byte !== 13) {
152
+ return false;
153
+ }
154
+ }
155
+ }
156
+
157
+ return true;
158
+ }
159
+
160
+ /**
161
+ * Quick check if buffer starts with HTTP method
162
+ */
163
+ static quickCheck(buffer: Buffer): boolean {
164
+ if (buffer.length < 3) {
165
+ return false;
166
+ }
167
+
168
+ // Check common HTTP methods
169
+ const start = buffer.slice(0, 7).toString('ascii');
170
+ return start.startsWith('GET ') ||
171
+ start.startsWith('POST ') ||
172
+ start.startsWith('PUT ') ||
173
+ start.startsWith('DELETE ') ||
174
+ start.startsWith('HEAD ') ||
175
+ start.startsWith('OPTIONS') ||
176
+ start.startsWith('PATCH ') ||
177
+ start.startsWith('CONNECT') ||
178
+ start.startsWith('TRACE ');
179
+ }
180
+
181
+ /**
182
+ * Parse query string
183
+ */
184
+ static parseQueryString(queryString: string): Record<string, string> {
185
+ const params: Record<string, string> = {};
186
+
187
+ if (!queryString) {
188
+ return params;
189
+ }
190
+
191
+ // Remove leading '?' if present
192
+ if (queryString.startsWith('?')) {
193
+ queryString = queryString.slice(1);
194
+ }
195
+
196
+ const pairs = queryString.split('&');
197
+ for (const pair of pairs) {
198
+ const [key, value] = pair.split('=');
199
+ if (key) {
200
+ params[decodeURIComponent(key)] = value ? decodeURIComponent(value) : '';
201
+ }
202
+ }
203
+
204
+ return params;
205
+ }
206
+
207
+ /**
208
+ * Build query string from params
209
+ */
210
+ static buildQueryString(params: Record<string, string>): string {
211
+ const pairs: string[] = [];
212
+
213
+ for (const [key, value] of Object.entries(params)) {
214
+ pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
215
+ }
216
+
217
+ return pairs.length > 0 ? '?' + pairs.join('&') : '';
218
+ }
219
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * HTTP Protocol Type Definitions
3
+ */
4
+
5
+ import type { THttpMethod, THttpVersion, HttpStatus } from './constants.js';
6
+
7
+ /**
8
+ * HTTP request line structure
9
+ */
10
+ export interface IHttpRequestLine {
11
+ method: THttpMethod;
12
+ path: string;
13
+ version: THttpVersion;
14
+ }
15
+
16
+ /**
17
+ * HTTP response line structure
18
+ */
19
+ export interface IHttpResponseLine {
20
+ version: THttpVersion;
21
+ status: HttpStatus;
22
+ statusText: string;
23
+ }
24
+
25
+ /**
26
+ * HTTP header structure
27
+ */
28
+ export interface IHttpHeader {
29
+ name: string;
30
+ value: string;
31
+ }
32
+
33
+ /**
34
+ * HTTP message structure (base for request and response)
35
+ */
36
+ export interface IHttpMessage {
37
+ headers: Record<string, string>;
38
+ body?: Buffer;
39
+ }
40
+
41
+ /**
42
+ * HTTP request structure
43
+ */
44
+ export interface IHttpRequest extends IHttpMessage {
45
+ method: THttpMethod;
46
+ path: string;
47
+ version: THttpVersion;
48
+ query?: Record<string, string>;
49
+ }
50
+
51
+ /**
52
+ * HTTP response structure
53
+ */
54
+ export interface IHttpResponse extends IHttpMessage {
55
+ status: HttpStatus;
56
+ statusText: string;
57
+ version: THttpVersion;
58
+ }
59
+
60
+ /**
61
+ * Parsed URL structure
62
+ */
63
+ export interface IParsedUrl {
64
+ protocol?: string;
65
+ hostname?: string;
66
+ port?: number;
67
+ path?: string;
68
+ query?: string;
69
+ fragment?: string;
70
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Protocol-specific modules for smartproxy
3
+ *
4
+ * This directory contains generic protocol knowledge separated from
5
+ * smartproxy-specific implementation details.
6
+ */
7
+
8
+ export * as common from './common/index.js';
9
+ export * as tls from './tls/index.js';
10
+ export * as http from './http/index.js';
11
+ export * as proxy from './proxy/index.js';
12
+ export * as websocket from './websocket/index.js';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * PROXY Protocol Module
3
+ * HAProxy PROXY protocol implementation
4
+ */
5
+
6
+ export * from './types.js';
7
+ export * from './parser.js';