topnic-https 1.2.2 → 1.2.4

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "topnic-https",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "main": "./src/main/index.js",
5
5
  "type": "commonjs",
6
6
  "scripts": {
@@ -96,6 +96,7 @@
96
96
  "https": "^1.0.0",
97
97
  "localtunnel": "^2.0.2",
98
98
  "nanoid": "^5.0.8",
99
+ "net": "^1.0.2",
99
100
  "ngrok": "^5.0.0-beta.2",
100
101
  "os": "^0.1.2",
101
102
  "path": "^0.12.7",
package/readme CHANGED
@@ -25,7 +25,7 @@ $ npm install -g topnic-https
25
25
 
26
26
  ## أمثلة
27
27
  ```bash
28
- $ httpst share -p 3000 -d 60 # مشاركة لمدة 60 دقيقة
28
+ $ httpst share -p 3000 # مشاركة لمدة 60 دقيقة
29
29
  $ httpst run #تشغيل الخادم
30
30
  $ httpst stop #إيقاف الخادم
31
31
  $ httpst restart #إعادة تشغيل الخادم
@@ -2,6 +2,7 @@ const http = require('http');
2
2
  const WebSocket = require('ws');
3
3
  const { nanoid } = require('nanoid/non-secure');
4
4
  const os = require('os');
5
+ const net = require('net');
5
6
 
6
7
  class DirectServer {
7
8
  constructor() {
@@ -20,16 +21,60 @@ class DirectServer {
20
21
  return 'localhost';
21
22
  }
22
23
 
24
+ async isPortAvailable(port) {
25
+ return new Promise((resolve) => {
26
+ const tester = net.createServer()
27
+ .once('error', () => resolve(false))
28
+ .once('listening', () => {
29
+ tester.once('close', () => resolve(true)).close();
30
+ })
31
+ .listen(port);
32
+ });
33
+ }
34
+
23
35
  async start(port = 3500) {
36
+ if (!(await this.isPortAvailable(port))) {
37
+ console.log(`المنفذ ${port} مشغول، جاري المحاولة على منفذ آخر...`);
38
+ port = await this.findAvailablePort(3501);
39
+ }
40
+
24
41
  return new Promise((resolve) => {
25
42
  this.server.listen(port, '0.0.0.0', () => {
26
43
  console.log(`🚀 خادم المشاركة يعمل على المنفذ ${port}`);
27
44
  console.log(`📡 عنوان IP: ${this.publicIp}:${port}`);
28
- resolve();
45
+ resolve(port);
29
46
  });
30
47
  });
31
48
  }
32
49
 
50
+ async findAvailablePort(startPort) {
51
+ let port = startPort;
52
+ while (!(await this.isPortAvailable(port))) {
53
+ port++;
54
+ }
55
+ return port;
56
+ }
57
+
58
+ async verifyTargetPort(port) {
59
+ try {
60
+ const response = await new Promise((resolve, reject) => {
61
+ const req = http.request({
62
+ hostname: 'localhost',
63
+ port: port,
64
+ path: '/',
65
+ method: 'GET',
66
+ timeout: 2000
67
+ }, resolve);
68
+
69
+ req.on('error', reject);
70
+ req.end();
71
+ });
72
+ return true;
73
+ } catch (error) {
74
+ return false;
75
+ }
76
+ }
77
+
33
78
  createConnection(targetPort) {
34
79
  const id = nanoid(6);
35
80
  this.connections.set(id, {
@@ -41,41 +86,61 @@ class DirectServer {
41
86
  }
42
87
 
43
88
  async handleRequest(req, res) {
44
- const connectionId = req.url.split('/')[1];
45
- const connection = this.connections.get(connectionId);
89
+ try {
90
+ const urlParts = req.url.split('/');
91
+ const connectionId = urlParts[1];
92
+ const connection = this.connections.get(connectionId);
46
93
 
47
- if (!connection) {
48
- res.writeHead(404);
49
- res.end('رابط المشاركة غير صالح');
50
- return;
51
- }
94
+ if (!connection) {
95
+ res.writeHead(404);
96
+ res.end('رابط المشاركة غير صالح');
97
+ return;
98
+ }
52
99
 
53
- // إعادة توجيه الطلب إلى المنفذ المحلي
54
- const options = {
55
- hostname: 'localhost',
56
- port: connection.port,
57
- path: req.url.replace(`/${connectionId}`, '') || '/',
58
- method: req.method,
59
- headers: {
60
- ...req.headers,
61
- host: `localhost:${connection.port}`
100
+ // التحقق من أن الخدمة المحلية تعمل
101
+ if (!(await this.verifyTargetPort(connection.port))) {
102
+ res.writeHead(502);
103
+ res.end('الخدمة المحلية غير متاحة');
104
+ return;
62
105
  }
63
- };
64
106
 
65
- connection.visitors++;
107
+ // إعادة بناء المسار الأصلي
108
+ const originalPath = '/' + urlParts.slice(2).join('/');
66
109
 
67
- const proxyReq = http.request(options, (proxyRes) => {
68
- res.writeHead(proxyRes.statusCode, proxyRes.headers);
69
- proxyRes.pipe(res);
70
- });
110
+ const options = {
111
+ hostname: 'localhost',
112
+ port: connection.port,
113
+ path: originalPath,
114
+ method: req.method,
115
+ headers: {
116
+ ...req.headers,
117
+ host: `localhost:${connection.port}`
118
+ }
119
+ };
71
120
 
72
- proxyReq.on('error', (error) => {
73
- console.error('خطأ في التوجيه:', error);
74
- res.writeHead(502);
75
- res.end('خطأ في الاتصال بالتطبيق المحلي');
76
- });
121
+ const proxyReq = http.request(options, (proxyRes) => {
122
+ res.writeHead(proxyRes.statusCode, proxyRes.headers);
123
+ proxyRes.pipe(res);
124
+ });
125
+
126
+ proxyReq.on('error', (error) => {
127
+ console.error('خطأ في التوجيه:', error);
128
+ res.writeHead(502);
129
+ res.end('خطأ في الاتصال بالتطبيق المحلي');
130
+ });
77
131
 
78
- req.pipe(proxyReq);
132
+ if (!req.readableEnded) {
133
+ req.pipe(proxyReq);
134
+ } else {
135
+ proxyReq.end();
136
+ }
137
+
138
+ connection.visitors++;
139
+ } catch (error) {
140
+ console.error('خطأ في معالجة الطلب:', error);
141
+ res.writeHead(500);
142
+ res.end('خطأ داخلي في الخادم');
143
+ }
79
144
  }
80
145
 
81
146
  removeConnection(id) {
@@ -12,21 +12,23 @@ class ShareManager {
12
12
 
13
13
  async createShare(port) {
14
14
  try {
15
- const shareId = this.server.createConnection(port);
16
- const shareUrl = `http://${this.server.publicIp}:3500/${shareId}`;
15
+ const { id, accessCode } = this.server.createConnection(port);
16
+ const shareUrl = `http://${this.server.publicIp}:3500/${id}/login`;
17
17
 
18
18
  const share = {
19
- id: shareId,
19
+ id,
20
20
  url: shareUrl,
21
+ accessCode,
21
22
  port: port,
22
23
  startTime: Date.now()
23
24
  };
24
25
 
25
- this.activeShares.set(shareId, share);
26
+ this.activeShares.set(id, share);
26
27
 
27
28
  return {
28
- id: shareId,
29
+ id,
29
30
  url: shareUrl,
31
+ accessCode,
30
32
  localUrl: `http://localhost:${port}`
31
33
  };
32
34
  } catch (error) {