just-another-http-api 1.2.0 → 1.2.2

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/api.js CHANGED
@@ -30,24 +30,10 @@ async function createServer ( config ) {
30
30
  try {
31
31
 
32
32
  if ( config.cors ) {
33
- app.register ( require ( '@fastify/cors' ), ( instance ) => {
34
- return ( req, callback ) => {
35
- const corsOptions = {
36
- // This is NOT recommended for production as it enables reflection exploits
37
- origin: true
38
- };
39
-
40
- console.log ( 'hbawfjawhv' );
41
-
42
- // // do not include CORS headers for requests from localhost
43
- // if ( /^localhost$/m.test ( req.headers.origin ) ) {
44
- // corsOptions.origin = false;
45
- // }
46
-
47
- // callback expects two parameters: error and options
48
- callback ( null, corsOptions );
49
- };
50
- } );
33
+ app.register ( require ( '@fastify/cors' ), config.cors );
34
+ }
35
+ if ( config.websocket?.enabled ){
36
+ app.register ( require ( '@fastify/websocket' ), config.websocket?.options );
51
37
  }
52
38
  await uploads.initialiseUploads ( app, config );
53
39
  await caching.initialiseCaching ( app, config );
@@ -100,12 +86,13 @@ function registerEndpoint ( app, endpoint, globalConfig ) {
100
86
 
101
87
  const fastifyMethod = translateLegacyMethods ( method.toLowerCase () );
102
88
  const handler = endpoint.handlers[ method ];
103
- const wrappedHandler = fastifyHandlerWrapper ( handler, endpoint.handlers.config, globalConfig );
89
+ const wrappedHandler = fastifyHandlerWrapper ( handler, endpoint.handlers.config, globalConfig, method );
104
90
 
105
91
  app[ fastifyMethod ] (
106
92
  endpoint.path,
107
93
  {
108
- preHandler: preHandlers
94
+ preHandler: preHandlers,
95
+ websocket: handlerConfig?.websocket || false,
109
96
  },
110
97
  wrappedHandler
111
98
  );
@@ -121,22 +108,27 @@ function translateLegacyMethods ( method ) {
121
108
  }
122
109
  }
123
110
 
124
- function fastifyHandlerWrapper ( handler, config, globalConfig ) {
125
- return async ( req, reply ) => {
126
- try {
127
- let response = await caching.checkRequestCache ( app, req, reply, config, globalConfig );
111
+ function fastifyHandlerWrapper ( handler, config, globalConfig, method ) {
112
+ if ( config?.[ method ].websocket ){
113
+ return handler;
114
+ }
115
+ else {
116
+ return async ( req, reply ) => {
117
+ try {
118
+ let response = await caching.checkRequestCache ( app, req, reply, config, globalConfig );
128
119
 
129
- if ( !response ){
130
- response = await handler ( req );
131
- await caching.setRequestCache ( app, req, response, config, globalConfig );
132
- }
120
+ if ( !response ){
121
+ response = await handler ( req );
122
+ await caching.setRequestCache ( app, req, response, config, globalConfig );
123
+ }
133
124
 
134
- handleResponse ( reply, response, req.method, req.routeOptions.url );
135
- }
136
- catch ( error ) {
137
- handleError ( reply, error );
138
- }
139
- };
125
+ handleResponse ( reply, response, req.method, req.routeOptions.url );
126
+ }
127
+ catch ( error ) {
128
+ handleError ( reply, error );
129
+ }
130
+ };
131
+ }
140
132
  };
141
133
 
142
134
  function handleResponse ( reply, response, method, path ) {
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ redis: {
3
+ port: process.env.REDIS_PORT || 6379,
4
+ host: process.env.REDIS_HOST || 'localhost',
5
+ prefix: process.env.REDIS_PREFIX || 'api:'
6
+ }
7
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "just-another-http-api",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "A framework built on top of fastify aimed at removing the need for any network or server configuration. ",
5
5
  "homepage": "https://github.com/OllieEdge/just-another-http-api#readme",
6
6
  "repository": {
@@ -30,6 +30,7 @@
30
30
  "@fastify/cors": "^8.4.1",
31
31
  "@fastify/jwt": "^7.2.3",
32
32
  "@fastify/redis": "^6.1.1",
33
+ "@fastify/websocket": "^8.2.0",
33
34
  "abstract-cache": "^1.0.1",
34
35
  "abstract-cache-redis": "^2.0.0",
35
36
  "fastify": "^4.24.3",
@@ -0,0 +1,60 @@
1
+ const crypto = require ( 'crypto' );
2
+ const { redis } = require ( 'eip-cloud-services' );
3
+
4
+ class WebsocketGroup {
5
+
6
+ constructor ( groupName ) {
7
+ this.groupName = groupName;
8
+ this.connections = new Map ();
9
+ }
10
+
11
+ async initialize () {
12
+ try {
13
+ await redis.subscribe ( `${this.groupName}_broadcast`, this.handleMessage.bind ( this ) );
14
+ await redis.subscribe ( `${this.groupName}_messageReceived`, this.handleUserMessage.bind ( this ) );
15
+ }
16
+ catch ( error ){
17
+ console.log ( error );
18
+ }
19
+ }
20
+
21
+ handleMessage ( message ) {
22
+ this.broadcastMessageToClients ( message );
23
+ }
24
+
25
+ async handleUserMessage ( userMessage ) {
26
+ // don't really need to do anything with this message.
27
+ }
28
+
29
+ broadcastMessageToClients ( message ) {
30
+ this.connections.forEach ( conn => {
31
+ conn.socket.send ( JSON.stringify ( message ) );
32
+ } );
33
+ }
34
+
35
+ addNewConnection ( connection, connectionId = crypto.randomUUID () ) {
36
+ this.connections.set ( connectionId, connection );
37
+
38
+ connection.socket.on ( 'message', async message => {
39
+ const userMessage = {
40
+ groupName: this.groupName,
41
+ connectionId,
42
+ message: message.toString ()
43
+ };
44
+ await redis.publish ( `${this.groupName}_messageReceived`, JSON.stringify ( userMessage ) );
45
+ } );
46
+
47
+ connection.socket.on ( 'close', () => {
48
+ this.connections.delete ( connectionId );
49
+ } );
50
+
51
+ connection.socket.on ( 'error', error => {
52
+ console.error ( 'WebSocket error:', error );
53
+ this.connections.delete ( connectionId );
54
+ } );
55
+
56
+ return { connectionId, groupName: this.groupName, connection };
57
+ }
58
+ }
59
+
60
+ module.exports = WebsocketGroup;
@@ -0,0 +1,14 @@
1
+ const WebsocketGroup = require ( './WebsocketGroup' );
2
+
3
+ const websocketGroups = {};
4
+
5
+ const getGroupInstance = async ( groupName ) => {
6
+ if ( !websocketGroups[ groupName ] ) {
7
+ websocketGroups[ groupName ] = new WebsocketGroup ( groupName );
8
+ await websocketGroups[ groupName ].initialize ();
9
+ }
10
+
11
+ return websocketGroups[ groupName ];
12
+ };
13
+
14
+ module.exports = getGroupInstance;