Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

2 lat temu
2 lat temu
2 lat temu
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. const fs = require('fs-extra');
  2. const { basename, extname } = require('path');
  3. const debug = require('debug')('server-connect:sockets');
  4. const { isEmpty } = require('./util');
  5. const config = require('./config');
  6. const cookieParser = require('cookie-parser');
  7. const { promisify } = require('util');
  8. module.exports = function (server, appSession) {
  9. //if (isEmpty('app/sockets')) return null;
  10. const io = require('socket.io')();
  11. if (global.redisClient) {
  12. const { createAdapter } = require('@socket.io/redis-adapter');
  13. const pubClient = global.redisClient.duplicate();
  14. const subClient = global.redisClient.duplicate();
  15. Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
  16. io.adapter(createAdapter(pubClient, subClient));
  17. });
  18. }
  19. // user hooks
  20. if (fs.existsSync('extensions/server_connect/sockets')) {
  21. const entries = fs.readdirSync('extensions/server_connect/sockets', { withFileTypes: true });
  22. for (let entry of entries) {
  23. if (entry.isFile() && extname(entry.name) == '.js') {
  24. const hook = require(`../../extensions/server_connect/sockets/${entry.name}`);
  25. if (hook.handler) hook.handler(io);
  26. debug(`Custom sockets hook ${entry.name} loaded`);
  27. }
  28. }
  29. }
  30. // create socket connections for api endpoints
  31. if (fs.existsSync('app/api')) {
  32. io.of('/api').on('connection', async (socket) => {
  33. socket.onAny(async (event, params, cb) => {
  34. try {
  35. if (typeof cb == 'function' && global.redisClient && global.redisClient.isReady) {
  36. const cached = await global.redisClient.get('ws:' + event + ':' + JSON.stringify(params));
  37. if (cached) return cb(JSON.parse(cached));
  38. }
  39. const req = Object.assign({}, socket.handshake);
  40. const res = {
  41. statusCode: 200,
  42. getHeader: () => { },
  43. setHeader: () => { },
  44. sendStatus: (statusCode) => { res.statusCode = statusCode; },
  45. write: () => { },
  46. end: () => { }
  47. };
  48. cookieParser(config.secret)(req, res, () => {
  49. appSession(req, res, async () => {
  50. const App = require('../core/app');
  51. const app = new App(req, res);
  52. const action = await fs.readJSON(`app/api/${event}.json`);
  53. app.set('$_PARAM', params);
  54. app.set('$_GET', params); // fake query params
  55. app.socket = socket;
  56. await app.define(action, true);
  57. if (typeof cb == 'function') {
  58. cb({
  59. status: res.statusCode,
  60. data: res.statusCode == 200 ? app.data : null
  61. });
  62. if (global.redisClient && global.redisClient.isReady) {
  63. let ttl = (action.settings && action.settings.options && action.settings.options.ttl) ? action.settings.options.ttl : null;
  64. if (ttl && res.statusCode < 400) { // only cache valid response, not error response
  65. global.redisClient.setEx('ws:' + event + ':' + JSON.stringify(params), ttl, JSON.stringify({
  66. status: res.statusCode,
  67. data: res.statusCode == 200 ? app.data : null
  68. }));
  69. }
  70. }
  71. }
  72. });
  73. });
  74. } catch (e) {
  75. debug(`ERROR: ${e.message}`);
  76. console.error(e);
  77. }
  78. });
  79. });
  80. }
  81. if (fs.existsSync('app/sockets')) {
  82. parseSockets();
  83. }
  84. function parseSockets(namespace = '') {
  85. const entries = fs.readdirSync('app/sockets' + namespace, { withFileTypes: true });
  86. io.of(namespace || '/').on('connection', async (socket) => {
  87. if (fs.existsSync(`app/sockets${namespace}/connect.json`)) {
  88. try {
  89. const req = Object.assign({}, socket.handshake);
  90. const res = {
  91. statusCode: 200,
  92. getHeader: () => { },
  93. setHeader: () => { },
  94. sendStatus: (statusCode) => { res.statusCode = statusCode; },
  95. write: () => { },
  96. end: () => { }
  97. };
  98. cookieParser(config.secret)(req, res, () => {
  99. appSession(req, res, async () => {
  100. const App = require('../core/app');
  101. const app = new App(req, res);
  102. const action = await fs.readJSON(`app/sockets${namespace}/connect.json`);
  103. app.socket = socket;
  104. await app.define(action, true);
  105. });
  106. });
  107. } catch (e) {
  108. debug(`ERROR: ${e.message}`);
  109. console.error(e);
  110. }
  111. }
  112. if (fs.existsSync(`app/sockets${namespace}/disconnect.json`)) {
  113. socket.on('disconnect', async (event) => {
  114. try {
  115. const req = Object.assign({}, socket.handshake);
  116. const res = {
  117. statusCode: 200,
  118. getHeader: () => { },
  119. setHeader: () => { },
  120. sendStatus: (statusCode) => { res.statusCode = statusCode; },
  121. write: () => { },
  122. end: () => { }
  123. };
  124. cookieParser(config.secret)(req, res, () => {
  125. appSession(req, res, async () => {
  126. const App = require('../core/app');
  127. const app = new App(req, res);
  128. const action = await fs.readJSON(`app/sockets${namespace}/disconnect.json`);
  129. app.socket = socket;
  130. await app.define(action, true);
  131. });
  132. });
  133. } catch (e) {
  134. debug(`ERROR: ${e.message}`);
  135. console.error(e);
  136. }
  137. });
  138. }
  139. socket.onAny(async (event, params, cb) => {
  140. try {
  141. const req = Object.assign({}, socket.handshake);
  142. const res = {
  143. statusCode: 200,
  144. getHeader: () => { },
  145. setHeader: () => { },
  146. sendStatus: (statusCode) => { res.statusCode = statusCode; },
  147. write: () => { },
  148. end: () => { }
  149. };
  150. cookieParser(config.secret)(req, res, () => {
  151. appSession(req, res, async () => {
  152. const App = require('../core/app');
  153. const app = new App(req, res);
  154. const action = await fs.readJSON(`app/sockets${namespace}/${event}.json`);
  155. app.set('$_PARAM', params);
  156. app.socket = socket;
  157. await app.define(action, true);
  158. if (typeof cb == 'function') cb(app.data);
  159. });
  160. });
  161. } catch (e) {
  162. debug(`ERROR: ${e.message}`);
  163. console.error(e);
  164. }
  165. });
  166. });
  167. for (let entry of entries) {
  168. if (entry.isDirectory()) {
  169. parseSockets(namespace + '/' + entry.name);
  170. }
  171. }
  172. }
  173. io.attach(server, {
  174. cors: config.cors
  175. });
  176. return io;
  177. };