You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
How to integrate socket in loopback 4 server API #4044
Hi @imranalisolanki can you share a minimal version of your app reproducing the issue, so I can troubleshoot? Sharing a code snippet is not enough, since other factors responsible for the failure may be left out of the context.
@hacksparrow i have create a simple loopback4 server with some routing and i have gone through https://github.com/raymondfeng/loopback4-example-websocket/ this example and when i have configure it in my server then existing routing is not working. Application.ts
import { BootMixin } from '@loopback/boot';
import { ApplicationConfig, BindingKey } from '@loopback/core';
import { RestExplorerBindings, RestExplorerComponent, } from '@loopback/rest-explorer';
import { RepositoryMixin } from '@loopback/repository';
import { RestApplication } from '@loopback/rest';
import { ServiceMixin } from '@loopback/service-proxy';
import * as path from 'path';
import { AuthenticationSequence } from './sequence';
import { AuthenticationComponent, registerAuthenticationStrategy } from '@loopback/authentication';
import { TokenServiceBindings, UserServiceBindings, TokenServiceConstants, PasswordHasherBindings, EmailServiceBindings, FCMServiceBindings, ControllerServiceBindings } from './keys';
import { JWTService } from './services/jwt-service';
import { MemberService } from './services/user-service';
import { BcryptHasher } from './services/hash.password.bcryptjs';
import { JWTAuthenticationStrategy } from './authentication-strategies/jwt-strategy';
import { EmailService, FCMService, ControllerService } from './services';
import { ReviewController } from './controllers';
import { SECURITY_SCHEME_SPEC } from './utils/security-spec';
Reacted by AmpleworkTechies, imranalisolanki, ashkank83, Eldar Sieitablaiev, oussama1995, Ivan Rangel, Bùi Xuân Diễn, Fr4nZ82 and Huascar Miranda Martínez
Instancing HttpServer with this.restServer.requestHandler: src/application.ts
Calling app.startWebSocket() in main function and add websocket options: src/index.ts
I am starting with LB4, and I don't know what are the future repercussions of this implementation or if it is a bad practice, but, at the moment, it works for me and maybe for you too.
Hi @arondn2 . when i integrate in my program i am getting error.
Error: The key 'authentication.actions.authenticate' is not bound to any value in context application
hi @imranalisolanki. I had a similar problem after my first comment in this feed. It is because websocket has not the same context of app. If you have a regular loopbak 4 app like loopback4-example-todo-list you must inherit the websocket context of the main context. I did with this changes.
Updating WebSocketServer constructor to receive the parent context: src/websocket.server.ts (lines 23 and 27).
Passing main context to WebSocketServer instancing: src/application.ts (line 40)
@arondn2 httpserver and websocketserver must have different ports ? I get Cannot start the application. { Error: listen EADDRINUSE: address already in use :::5000
@d-bo I successfully handled the web when I changed port 5000 to a different port than the http server. index.js
if (require.main === module) {
// Run the application
const config = {
rest: {
port: +(process.env.PORT || 3000),
host: process.env.HOST,
protocol: process.env.HTTPS === "1" ? "https" : "http",
key: fs.readFileSync(path.join(__dirname, './ssl/private/server-key.pem')).toString(),
cert: fs.readFileSync(path.join(__dirname, './ssl/private/server-cert.pem')).toString(),
// The `gracePeriodForClose` provides a graceful close for http/https
// servers with keep-alive clients. The default value is `Infinity`
// (don't force-close). If you want to immediately destroy all sockets
// upon stop, set its value to `0`.
// See https://www.npmjs.com/package/stoppable
gracePeriodForClose: 5000, // 5 seconds
openApiSpec: {
// useful when used with OpenAPI-to-GraphQL to locate your application
setServersFromRequest: true,
},
},
websocket: { port: 5000 }
};
application.main(config).catch(err => {
console.error('Cannot start the application.', err);
process.exit(1);
});
}
@xdien just commented out original http server from skeleton app. finally both websocket and http server are on the same port:
// src/index.ts// ...exportasyncfunctionmain(options: ApplicationConfig={}){constapp=newPrjApplication(options);awaitapp.boot();// commented out original http server//await app.start();awaitapp.startWebSocket();consturl=app.restServer.url;console.log(`Server is running at ${app.httpServer.url}/api`);returnapp;}// ...
Minor note, who ever stumble on the same issue, after a day of debugging, for some reason (something related to: circular/connection issue) you cannot use 'server.io-client' from the NodeJS server (loopback4, in my case) to connect to internal/external server. It just doesn't let you (tried switching to transports: ['websocket'],upgrade: false - didn't help). By switching to 'ws' library issue was resolved!
@d-bo fine. I don't know why it works for me. I gonna try if that works in my proyect to make a refactoring of the example.
@alexkander Did you find out the problem of "port in use" issue? I found that the key is the value of "host" in config. const config = { rest: { port, host: process.env.HOST ?? 'localhost', openApiSpec: { // useful when used with OpenAPI-to-GraphQL to locate your application setServersFromRequest: true, }, }, websocket: { port } };
The value of "host" for "rest" is 'localhost' and for websocket is undefined. If you assign "locahost" to the host of websocket, you have able to repo the issue. I still have no idea for the solution.
Thanks,
Justin
@justin65 I couldn't even replicate the problem. If you could create a repo test with the minimum configuration that generates the error, I could review it.
@justin65 your fork is of a old repository. You should to use the example of socketio that currently loopback 4 has. @loopback/example-socketio. I gonna to archive my example repository because it is no longer stable.
Anywhere, do you need set host configuration for websocket? I have commented it and it works!.
websocket: {port,// host: 'localhost',}
I gonna try to work in the documentation of the example and extension of socketio as soon as I can. Sorry for not being able to help more.
@alexkander I know that loopback 4 release a socketio example. But is't an Application, I can not extend it from rest application like the repository you are going to archive. That's why I keep working on old repository. Is there any guideline to merge two loopback 4 application?
Regarding the host field, I just show you how to repo the 'port in use' problem. I can comment it, but I don't know what happened exactly.
@aleksspeaker I'am trying to use host in websocket config but it leads to a problem Cannot start the application. Error: listen EADDRINUSE: address already in use 127.0.0.1:[port]
Activity
hacksparrow commentedon Nov 4, 2019
Hi @imranalisolanki can you share a minimal version of your app reproducing the issue, so I can troubleshoot? Sharing a code snippet is not enough, since other factors responsible for the failure may be left out of the context.
imranalisolanki commentedon Nov 4, 2019
@hacksparrow i have create a simple loopback4 server with some routing and i have gone through https://github.com/raymondfeng/loopback4-example-websocket/ this example and when i have configure it in my server then existing routing is not working.
Application.ts
import { BootMixin } from '@loopback/boot';
import { ApplicationConfig, BindingKey } from '@loopback/core';
import { RestExplorerBindings, RestExplorerComponent, } from '@loopback/rest-explorer';
import { RepositoryMixin } from '@loopback/repository';
import { RestApplication } from '@loopback/rest';
import { ServiceMixin } from '@loopback/service-proxy';
import * as path from 'path';
import { AuthenticationSequence } from './sequence';
import { AuthenticationComponent, registerAuthenticationStrategy } from '@loopback/authentication';
import { TokenServiceBindings, UserServiceBindings, TokenServiceConstants, PasswordHasherBindings, EmailServiceBindings, FCMServiceBindings, ControllerServiceBindings } from './keys';
import { JWTService } from './services/jwt-service';
import { MemberService } from './services/user-service';
import { BcryptHasher } from './services/hash.password.bcryptjs';
import { JWTAuthenticationStrategy } from './authentication-strategies/jwt-strategy';
import { EmailService, FCMService, ControllerService } from './services';
import { ReviewController } from './controllers';
import { SECURITY_SCHEME_SPEC } from './utils/security-spec';
export interface PackageInfo {
name: string;
version: string;
description: string;
}
export const PackageKey = BindingKey.create('application.package');
const pkg: PackageInfo = require('../package.json');
export class BreezeApiApplication extends BootMixin(ServiceMixin(RepositoryMixin(RestApplication))) {
constructor(options: ApplicationConfig = {}) {
super(options);
}
setUpBindings(): void {
this.bind(TokenServiceBindings.TOKEN_SECRET).to(TokenServiceConstants.TOKEN_SECRET_VALUE);
this.bind(TokenServiceBindings.TOKEN_EXPIRES_IN).to(TokenServiceConstants.TOKEN_EXPIRES_IN_VALUE);
this.bind(TokenServiceBindings.TOKEN_SERVICE).toClass(JWTService);
}
}
index.ts
import { BreezeApiApplication } from './application';
import { ApplicationConfig } from '@loopback/core';
export { BreezeApiApplication };
export async function main(options: ApplicationConfig = {}) {
const app = new BreezeApiApplication(options);
await app.boot();
//await app.start();
app.io = require('socket.io')(await app.start());
app.io.on('connection', async function (socket: any) {
});
const url = app.restServer.url;
console.log(
Server is running at ${url});return app;
}
hacksparrow commentedon Nov 4, 2019
@imranalisolanki the code you pasted refers to many files not found in the original https://github.com/raymondfeng/loopback4-example-websocket/. Also it has basic run-time errors like
console.log(Server is running at ${url});.I will be able to help you if you can provide a minimal app reproducing the error. Code snippets are not enough.
kchraniuk commentedon Nov 5, 2019
I have the same problem as @imranalisolanki. I would also like to know how to use/implement the websocket from this example https://github.com/raymondfeng/loopback4-example-websocket/ in this example https://github.com/strongloop/loopback4-example-shopping .
xdien commentedon Jun 23, 2020
I have been following this topic for a long time. Everyone who has done it successfully with https://github.com/strongloop/loopback4-example-shopping.
Particularly https://github.com/raymondfeng/loopback4-example-websocket/ using httpserver with "Express" I do not know how to implement with RestExplorerComponent
alexkander commentedon Jul 16, 2020
Hi guys, I had the same problem: Looback 4 RestApplication + socket.io. I solved it based on loopback4-example-todo-list and loopback4-example-websocket. Here is the partial codes:
HttpServerwiththis.restServer.requestHandler: src/application.tsapp.startWebSocket()in main function and add websocket options: src/index.tsI am starting with LB4, and I don't know what are the future repercussions of this implementation or if it is a bad practice, but, at the moment, it works for me and maybe for you too.
-------------------------- Updated ---------------------
To inject dependencies of the main app into websocket controllers you must inherit the websocket context of the main context
WebSocketServerconstructor to receive the parent context: src/websocket.server.ts (lines 23 and 27).WebSocketServerinstancing: src/application.ts (line 40)xdien commentedon Jul 19, 2020
thanks @arondn2 . I will try to integrate it into my program
imranalisolanki commentedon Jul 20, 2020
Hi @arondn2 . when i integrate in my program i am getting error.
Error: The key 'authentication.actions.authenticate' is not bound to any value in context application
alexkander commentedon Jul 20, 2020
hi @imranalisolanki. I had a similar problem after my first comment in this feed. It is because websocket has not the same context of app. If you have a regular loopbak 4 app like loopback4-example-todo-list you must inherit the websocket context of the main context. I did with this changes.
WebSocketServerconstructor to receive the parent context: src/websocket.server.ts (lines 23 and 27).WebSocketServerinstancing: src/application.ts (line 40)-------------------------- Updated ---------------------
The links were wrong. I have updated them.
d-bo commentedon Jul 22, 2020
@arondn2 httpserver and websocketserver must have different ports ? I get
Cannot start the application. { Error: listen EADDRINUSE: address already in use :::5000index.ts used from src/index.ts
xdien commentedon Jul 24, 2020
@d-bo I successfully handled the web when I changed port 5000 to a different port than the http server.
index.jsd-bo commentedon Jul 24, 2020
@xdien just commented out original http server from skeleton app. finally both websocket and http server are on the same port:
alexkander commentedon Jul 24, 2020
I didn't need to comment on that line. I made a complete example with the integration: loopback4-example-websocket-app. I hope it helps
37 remaining items
w20k commentedon Sep 24, 2020
Thanks for a tip @arondn2.
Minor note, who ever stumble on the same issue, after a day of debugging, for some reason (something related to: circular/connection issue) you cannot use 'server.io-client' from the NodeJS server (loopback4, in my case) to connect to internal/external server. It just doesn't let you (tried switching to transports:
['websocket'],upgrade: false- didn't help). By switching to 'ws' library issue was resolved!alexkander commentedon Nov 6, 2020
Guys, There is a new loopback 4 module for socketio @loopback/socketio and example @loopback/example-socketio.
justin65 commentedon Jan 8, 2021
@alexkander Did you find out the problem of "port in use" issue? I found that the key is the value of "host" in config.
const config = { rest: { port, host: process.env.HOST ?? 'localhost', openApiSpec: { // useful when used with OpenAPI-to-GraphQL to locate your application setServersFromRequest: true, }, }, websocket: { port } };The value of "host" for "rest" is 'localhost' and for websocket is undefined. If you assign "locahost" to the host of websocket, you have able to repo the issue. I still have no idea for the solution.
Thanks,
Justin
alexkander commentedon Jan 8, 2021
@justin65 I couldn't even replicate the problem. If you could create a repo test with the minimum configuration that generates the error, I could review it.
justin65 commentedon Jan 8, 2021
@alexkander I just fork the project and add a commit to replicate the problem.
Could you please take a look for https://github.com/justin65/loopback4-example-websocket-app.git?
I think the issue is caused by different http server instances in both rest and socketio. Am I right?
alexkander commentedon Jan 8, 2021
@justin65 with your repository I can replicate the problem. I'll take a look as soon as I can
mAlaliSy commentedon Jan 9, 2021
How can I create a REST and socket.io application?
justin65 commentedon Jan 13, 2021
@alexkander Did you have any update? Should both rest and socket.io share the same http server instance? Thanks.
alexkander commentedon Jan 13, 2021
@justin65 your fork is of a old repository. You should to use the example of socketio that currently loopback 4 has. @loopback/example-socketio. I gonna to archive my example repository because it is no longer stable.
Anywhere, do you need set
hostconfiguration for websocket? I have commented it and it works!.I gonna try to work in the documentation of the example and extension of socketio as soon as I can. Sorry for not being able to help more.
Regards
justin65 commentedon Jan 14, 2021
@alexkander I know that loopback 4 release a socketio example. But is't an Application, I can not extend it from rest application like the repository you are going to archive. That's why I keep working on old repository. Is there any guideline to merge two loopback 4 application?
Regarding the host field, I just show you how to repo the 'port in use' problem. I can comment it, but I don't know what happened exactly.
Regards
ArtemShapovalov commentedon Feb 2, 2021
@aleksspeaker I'am trying to use host in websocket config but it leads to a problem
Cannot start the application. Error: listen EADDRINUSE: address already in use 127.0.0.1:[port]d-bo commentedon Feb 2, 2021
@justin65 , @ArtemShapovalov guys there is a working websocket repo built from original lb4 skeleton app https://github.com/d-bo/lb4-client-err where
EADDRINUSE: address already in useproblem solved.And the line causing this error https://github.com/d-bo/lb4-client-err/blob/173b996da0974f2a39f20ac0c53f67d95be0c29b/src/index.ts#L14
ArtemShapovalov commentedon Feb 2, 2021
@d-bo thanks a lot it solve problem with
EADDRINUSEbut now I see undefined when server is started