Closed imranalisolanki closed 3 years ago
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';
export interface PackageInfo {
name: string;
version: string;
description: string;
}
export const PackageKey = BindingKey.create
const pkg: PackageInfo = require('../package.json');
export class BreezeApiApplication extends BootMixin(ServiceMixin(RepositoryMixin(RestApplication))) { constructor(options: ApplicationConfig = {}) { super(options);
this.api({
openapi: '3.0.0',
info: { title: pkg.name, version: pkg.version },
paths: {},
components: { securitySchemes: SECURITY_SCHEME_SPEC },
servers: [{ url: '/' }],
})
this.setUpBindings();
// Bind authentication component related elements
this.component(AuthenticationComponent);
registerAuthenticationStrategy(this, JWTAuthenticationStrategy);
// Set up the custom sequence
this.sequence(AuthenticationSequence);
// Set up default home page
this.static('/', path.join(__dirname, '../public'));
// Customize @loopback/rest-explorer configuration here
this.bind(RestExplorerBindings.CONFIG).to({ path: '/explorer', });
this.component(RestExplorerComponent);
this.projectRoot = __dirname;
// Customize @loopback/boot Booter Conventions here
this.bootOptions = {
controllers: {
// Customize ControllerBooter Conventions here
dirs: ['controllers'],
extensions: ['.controller.js'],
nested: true,
},
};
}
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);
this.bind(PasswordHasherBindings.ROUNDS).to(10);
this.bind(PasswordHasherBindings.PASSWORD_HASHER).toClass(BcryptHasher);
this.bind(UserServiceBindings.USER_SERVICE).toClass(MemberService);
this.bind(EmailServiceBindings.MAIL_SERVICE).toClass(EmailService)
this.bind(FCMServiceBindings.FCM_SERVICE).toClass(FCMService);
this.bind(ControllerServiceBindings.CONTROLLER_SERVICE).toClass(ControllerService);
} }
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) {
console.log('connected', socket.id)
socket.on('disconnect', function () {
console.log('user disconnected');
});
});
const url = app.restServer.url;
console.log(Server is running at ${url}
);
return app; }
@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.
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 .
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
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:
HttpServer
with this.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
WebSocketServer
constructor to receive the parent context: src/websocket.server.ts (lines 23 and 27).WebSocketServer
instancing: src/application.ts (line 40)thanks @arondn2 . I will try to integrate it into my program
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.
WebSocketServer
constructor to receive the parent context: src/websocket.server.ts (lines 23 and 27).WebSocketServer
instancing: src/application.ts (line 40)-------------------------- Updated ---------------------
The links were wrong. I have updated them.
@arondn2 httpserver and websocketserver must have different ports ? I get Cannot start the application. { Error: listen EADDRINUSE: address already in use :::5000
index.ts used from src/index.ts
@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
// ...
export async function main(options: ApplicationConfig = {}) {
const app = new PrjApplication(options);
await app.boot();
// commented out original http server
//await app.start();
await app.startWebSocket();
const url = app.restServer.url;
console.log(`Server is running at ${app.httpServer.url}/api`);
return app;
}
// ...
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
I try to inject websocket controller into notification.controller
via
constructor(
@inject('controllers.WebSocketController') private ws: WebSocketController,
) {}
Seems it is not the right way doing that:
500 ResolutionError: The key 'ws.socket' is not bound to any value in context
RequestContext-6bGhwRlvTmCH8MjrUYqIBQ-4 (context: RequestContext-6bGhwRlvTmCH8MjrUYqIBQ-4,
binding: ws.socket, resolutionPath: controllers.NotificationController -->
@NotificationController.constructor[4] --> controllers.WebSocketController -->
@WebSocketController.constructor[0])
@d-bo why are you trying to inject a controller into another controller? I assume notification.controller is a regular rest controller to handle HTTP requests, and WebSocketController is to handle connections socket.io. WebSocketController need the socket instance from socket.io connection which doesn't exist in a HTTP request.
@arondn2 i need to emit incoming data from rest notification.controller
to websocket
// for example
@post('/notifications')
async create(data: any) {
...
this.socket.emit('notification', data);
}
tried inject only socket
constructor(
@ws.socket() private socket: Socket,
) {}
no luck) same 500 ResolutionError ...
@d-bo I think you have to implement a room scheme like socket.io explains in their documentation here. I added some code in loopback4-example-websocket-app repo to show you a way to implement it, specifically how to emit an event from TodoController (Http request controller) to socket.io room. The specifics changes are:
@arondn2,
Thanks for sharing the updated repo.
I just downloaded your updated version and it looks like we still have an issue with "port in use".
`> loopback-example-websocket-app@0.1.2 prestart /home/zzz/latesttry/loopback/lb4/loopback4-example-websocket-app
npm run build
loopback-example-websocket-app@0.1.2 build /home/zzz/latesttry/loopback/lb4/loopback4-example-websocket-app lb-tsc
loopback-example-websocket-app@0.1.2 start /home/zzz/latesttry/loopback/lb4/loopback4-example-websocket-app node .
Cannot start the application. Error: listen EADDRINUSE: address already in use 127.0.0.1:3000
at Server.setupListenHandle [as _listen2] (net.js:1313:16)
at listenInCluster (net.js:1361:12)
at GetAddrInfoReqWrap.doListen [as callback] (net.js:1498:7)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:68:8) {
code: 'EADDRINUSE',
errno: 'EADDRINUSE',
syscall: 'listen',
address: '127.0.0.1',
port: 3000
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! loopback-example-websocket-app@0.1.2 start: node .
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the loopback-example-websocket-app@0.1.2 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in: `
netstat -tulpn (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN - tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - tcp 0 0 172.20.20.235:5432 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:6010 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:6011 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:6012 0.0.0.0:* LISTEN - tcp 0 0 172.20.20.235:6379 0.0.0.0:* LISTEN - tcp6 0 0 :::22 :::* LISTEN - tcp6 0 0 ::1:6010 :::* LISTEN - tcp6 0 0 ::1:6011 :::* LISTEN - tcp6 0 0 ::1:6012 :::* LISTEN - tcp6 0 0 :::80 :::* LISTEN - udp 0 0 127.0.0.53:53 0.0.0.0:* - udp 0 0 172.20.20.235:68 0.0.0.0:* -
Will appreciate if you can please look into it.
Thanks
@argupta23 Sorry, i can't get this issue but I am looking at what is happening.
Have you tried removing the node_modules folder, reinstalling dependencies?
Can you use npm run clean && npm run start
instead of npm run build
, lb-tsc
and node .
?
@d-bo
I am in the same situation as you and trying to achieve something similar.
@arondn2
Yes, I did what you suggested but have the same result.
I even tried the suggestion that was earlier made to comment out app.start(), but that made matters worse.
To get around the issue, within index.ts, I appended the port with 5000 and it seems to comeup.
websocket: { port: 5000 }
It also requires public/index.html to listen on 5000
But in this case we now have the app running on 2 ports (3000 and 5000).
Hope this helps. Please let me know if you want me try something else.
@argupta23 I will comment this when I find out the issue. @d-bo, do you have the same problem with the port? were you start the repo example that I left?
@argupta23 I have run the example in 3 differents computers and it always run ok. I have noticed you haven't run netstat
command as root, and logs are says Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all
, which means those are not all the proccesses. Please trying using another port in src/index.js
@arondn2 no, i didn't clone the repo loopback4-example-websocket-app
. I took files and pieces of code and port them to skeleton app generated from lb4 cli ...
@d-bo, does your version comeup on a single port?
@arondn2,
Just ran a quick test again for you and here is the output.
ubuntu: 20.04 running kernel 5.4.0-40-generic node -v : 12.18.2 npm -v : 6.14.7
and package.json
{ "name": "@loopback/example-file-transfer", "version": "1.4.2", "description": "Example application for file upload/download with LoopBack 4", "main": "dist/index.js", "types": "dist/index.d.ts", "engines": { "node": ">=10.16" }, "author": "IBM Corp.", "copyright.owner": "IBM Corp.", "license": "MIT", "publishConfig": { "access": "public" }, "scripts": { "acceptance": "lb-mocha \"dist/tests/acceptance//.js\"", "build": "lb-tsc", "build:watch": "lb-tsc --watch", "clean": "lb-clean example-file-transfer.tgz dist .tsbuildinfo package", "verify": "npm pack && tar xf example-file-transfer.tgz && tree package && npm run clean", "lint": "npm run prettier:check && npm run eslint", "lint:fix": "npm run eslint:fix && npm run prettier:fix", "prettier:cli": "lb-prettier \"/*.ts\" \"/*.js\"", "prettier:check": "npm run prettier:cli -- -l", "prettier:fix": "npm run prettier:cli -- --write", "eslint": "lb-eslint --report-unused-disable-directives .", "eslint:fix": "npm run eslint -- --fix", "pretest": "npm run clean && npm run build", "test": "lb-mocha \"dist/tests/*/.js\"", "test:dev": "lb-mocha dist/tests//*.js && npm run posttest", "prestart": "npm run build", "start": "node ." }, "repository": { "type": "git", "url": "https://github.com/strongloop/loopback-next.git", "directory": "examples/file-transfer" }, "dependencies": { "@loopback/boot": "^2.4.0", "@loopback/core": "^2.9.2", "@loopback/repository": "^2.10.0", "@loopback/rest": "^5.2.1", "@loopback/rest-explorer": "^2.2.7", "loopback-connector-mongodb": "^5.3.0", "multer": "^1.4.2", "tslib": "^2.0.0" }, "devDependencies": { "@loopback/build": "^6.1.1", "@loopback/eslint-config": "^8.0.4", "@loopback/testlab": "^3.2.1", "@types/express-serve-static-core": "^4.17.8", "@types/multer": "^1.4.3", "@types/node": "^10.17.27", "eslint": "^7.5.0", "typescript": "~3.9.7" }, "keywords": [ "loopback", "LoopBack", "example", "file", "upload" ], "gitHead": "5538896411bb56467ae52670a29d1aec1690be74" }
sudo netstat -tulpn Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.53:53 0.0.0.0: LISTEN 816/systemd-resolve tcp 0 0 0.0.0.0:22 0.0.0.0: LISTEN 902/sshd: /usr/sbin tcp 0 0 172.20.20.235:5432 0.0.0.0: LISTEN 56555/postgres tcp 0 0 127.0.0.1:6010 0.0.0.0: LISTEN 704372/sshd: argupt tcp 0 0 127.0.0.1:6011 0.0.0.0: LISTEN 712372/sshd: argupt tcp 0 0 172.20.20.235:6379 0.0.0.0: LISTEN 43528/redis-server tcp6 0 0 :::22 ::: LISTEN 902/sshd: /usr/sbin tcp6 0 0 ::1:6010 ::: LISTEN 704372/sshd: argupt tcp6 0 0 ::1:6011 ::: LISTEN 712372/sshd: argupt tcp6 0 0 :::80 ::: LISTEN 54445/apache2 udp 0 0 127.0.0.53:53 0.0.0.0: 816/systemd-resolve udp 0 0 172.20.20.235:68 0.0.0.0: 814/systemd-network
set websocket port to blank loopback4-example-websocket-app$ vi src/index.ts loopback4-example-websocket-app$ npm start
loopback-example-websocket-app@0.1.2 prestart /home/argupta/latesttry/loopback/lb4/loopback4-example-webs npm run build loopback-example-websocket-app@0.1.2 build /home/argupta/latesttry/loopback/lb4/loopback4-example-websock lb-tsc loopback-example-websocket-app@0.1.2 start /home/argupta/latesttry/loopback/lb4/loopback4-example-websock node .
Cannot start the application. Error: listen EADDRINUSE: address already in use 127.0.0.1:3000
at Server.setupListenHandle [as _listen2] (net.js:1313:16)
at listenInCluster (net.js:1361:12)
at GetAddrInfoReqWrap.doListen [as callback] (net.js:1498:7)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:68:8) {
code: 'EADDRINUSE',
errno: 'EADDRINUSE',
syscall: 'listen',
address: '127.0.0.1',
port: 3000
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! loopback-example-websocket-app@0.1.2 start: node .
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the loopback-example-websocket-app@0.1.2 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in: npm ERR! /home/argupta/.npm/_logs/2020-07-29T20_14_16_107Z-debug.log
sudo netstat -tulpn Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.53:53 0.0.0.0: LISTEN 816/systemd-resolve tcp 0 0 0.0.0.0:22 0.0.0.0: LISTEN 902/sshd: /usr/sbin tcp 0 0 172.20.20.235:5432 0.0.0.0: LISTEN 56555/postgres tcp 0 0 127.0.0.1:6010 0.0.0.0: LISTEN 704372/sshd: argupt tcp 0 0 127.0.0.1:6011 0.0.0.0: LISTEN 712372/sshd: argupt tcp 0 0 172.20.20.235:6379 0.0.0.0: LISTEN 43528/redis-server tcp6 0 0 :::22 ::: LISTEN 902/sshd: /usr/sbin tcp6 0 0 ::1:6010 ::: LISTEN 704372/sshd: argupt tcp6 0 0 ::1:6011 ::: LISTEN 712372/sshd: argupt tcp6 0 0 :::80 ::: LISTEN 54445/apache2 udp 0 0 127.0.0.53:53 0.0.0.0: 816/systemd-resolve udp 0 0 172.20.20.235:68 0.0.0.0: 814/systemd-network
updated websocket port to 5000
loopback4-example-websocket-app$ vi src/index.ts loopback4-example-websocket-app$ sudo netstat -tulpn Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.53:53 0.0.0.0: LISTEN 816/systemd-resolve tcp 0 0 0.0.0.0:22 0.0.0.0: LISTEN 902/sshd: /usr/sbin tcp 0 0 172.20.20.235:5432 0.0.0.0: LISTEN 56555/postgres tcp 0 0 127.0.0.1:6010 0.0.0.0: LISTEN 704372/sshd: argupt tcp 0 0 127.0.0.1:6011 0.0.0.0: LISTEN 712372/sshd: argupt tcp 0 0 172.20.20.235:6379 0.0.0.0: LISTEN 43528/redis-server tcp6 0 0 :::22 ::: LISTEN 902/sshd: /usr/sbin tcp6 0 0 ::1:6010 ::: LISTEN 704372/sshd: argupt tcp6 0 0 ::1:6011 ::: LISTEN 712372/sshd: argupt tcp6 0 0 :::80 ::: LISTEN 54445/apache2 udp 0 0 127.0.0.53:53 0.0.0.0: 816/systemd-resolve udp 0 0 172.20.20.235:68 0.0.0.0: 814/systemd-network
loopback4-example-websocket-app$ npm start
loopback-example-websocket-app@0.1.2 prestart /home/argupta/latesttry/loopback/lb4/loopback4-example-webs npm run build loopback-example-websocket-app@0.1.2 build /home/argupta/latesttry/loopback/lb4/loopback4-example-websock lb-tsc loopback-example-websocket-app@0.1.2 start /home/argupta/latesttry/loopback/lb4/loopback4-example-websock node .
Server is running at http://127.0.0.1:3000
ran netstat -tulpn from another terminal sudo netstat -tulpn [sudo] password for argupta: Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.53:53 0.0.0.0: LISTEN 816/systemd-resolve tcp 0 0 0.0.0.0:22 0.0.0.0: LISTEN 902/sshd: /usr/sbin tcp 0 0 127.0.0.1:3000 0.0.0.0: LISTEN 715259/node tcp 0 0 172.20.20.235:5432 0.0.0.0: LISTEN 56555/postgres tcp 0 0 127.0.0.1:6010 0.0.0.0: LISTEN 704372/sshd: argupt tcp 0 0 127.0.0.1:6011 0.0.0.0: LISTEN 712372/sshd: argupt tcp 0 0 172.20.20.235:6379 0.0.0.0: LISTEN 43528/redis-server tcp6 0 0 :::22 ::: LISTEN 902/sshd: /usr/sbin tcp6 0 0 ::1:6010 ::: LISTEN 704372/sshd: argupt tcp6 0 0 ::1:6011 ::: LISTEN 712372/sshd: argupt *tcp6 0 0 :::5000 ::: LISTEN 715259/node* tcp6 0 0 :::80 ::: LISTEN 54445/apache2 udp 0 0 127.0.0.53:53 0.0.0.0: 816/systemd-resolve udp 0 0 172.20.20.235:68 0.0.0.0: 814/systemd-network
one thing to note is that the websocket is attached to an IPv6 address / port
I can see you are using different ports for the configurations of rest and websocket. In my previous comment I say change the port for both, not just for websocket.
// src/index.ts
if (require.main === module) {
const port = process.env.PORT ?? 5000; ///<------- UPDATE HERE
// Run the application
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
}
};
main(config).catch(err => {
console.error('Cannot start the application.', err);
process.exit(1);
});
}
Also, it is very important to run npm run clean
before npm start
.
Anyway I don't know how I can help you more. I still thinking there is process using that port.
@argupta23 yeah, both http and websocket on a single port 3000. I disabled original http server started from generated lb4 cli app https://github.com/strongloop/loopback-next/issues/4044#issuecomment-663359434
@d-bo,
Maybe I am missing something on my end. Can I please request you to share a snippet the code of what changes need to be made?
@arondn2 I did try what you have suggested with the same results. If you want we could do an online session.
Thanks
@argupta23 in my profile is my email
@arondn2 confirmed, address in use:
bdo@bdo-PC:~/prj/loopback4-example-websocket-app$ npm start
> loopback-example-websocket-app@0.1.2 prestart /home/bdo/prj/loopback4-example-websocket-app
> npm run build
> loopback-example-websocket-app@0.1.2 build /home/bdo/prj/loopback4-example-websocket-app
> lb-tsc
> loopback-example-websocket-app@0.1.2 start /home/bdo/prj/loopback4-example-websocket-app
> node .
Cannot start the application. { Error: listen EADDRINUSE: address already in use 127.0.0.1:3000
at Server.setupListenHandle [as _listen2] (net.js:1280:14)
at listenInCluster (net.js:1328:12)
at GetAddrInfoReqWrap.doListen [as callback] (net.js:1461:7)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:61:10)
code: 'EADDRINUSE',
errno: 'EADDRINUSE',
syscall: 'listen',
address: '127.0.0.1',
port: 3000 }
@d-bo @argupta23 I will try to find out the problem
@arondn2, @argupta23 in websocket.application.ts
commented out await super.start();
and it works !
public async start(): Promise<void> {
await this.wsServer.start();
//await super.start();
}
@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.
@arondn2 thank you for example. there are the ws workspace and ws rest controller injector solved
@arondn2 some issues with socket rooms ...
I want to join client to the room with user id.
@ws({name: 'pzNsp', namespace: '/pz' })
export class WebSocketController {
...
@ws.connect()
connect() {
console.log('Client connected: ', this.socket.id);
}
@ws.subscribe('authentication')
async handleAuthentication(userId: string) {
// leave default room
this.socket.leaveAll();
// join room with userId
this.socket.join(`/pz#${userId}`, (err: any) => {
this.socket.in(`/pz#${userId}`).broadcast.emit('authenticated');
});
}
}
It is not emitting to client. Works only with this.socket.emit('authenticated');
Is this a bug or i misunderstood the concept ?
@d-bo this is what says the socket.io documentation:
// sending to all clients except sender
socket.broadcast.emit('broadcast', 'hello friends!');
I think If you want to indicate to the current connection is authenticated you should use this.socket.emit('authenticated');
. When you use this.socket.in(`/pz#${userId}`).broadcast.emit('authenticated');
the event will be sended to all connections of this user except the current connection.
@arondn2 the point is to push notifications to user logged in from many devices, browsers. to put user into own socket.io room after successfull authentication . so i tried all the matched variants from socket.io cheatsheet this.socket.in(`/pz#${userId}`).emit('authenticated')
, this.socket.to(`/pz#${userId}`).emit('authenticated')
... client is not responding at all
@d-bo do you want to send the event to all others connections of the same authenticated user or of all users connected?
@arondn2 to all other connections of the same authenticated user
@d-bo I think if you are using this.socket.in(`/pz#${userId}`).emit('authenticated')
or this.socket.in(`/pz#${userId}`).emit('authenticated')
, a simple client connection should received the event. Make sure you have socket.on('authenticated', function(){...})
in the client.
If you want send the event to all other connections of the same authenticated user, you will need to use broadcast
, and to test it you will need several connections for the same user at the same time.
You need to create a minimal repository loopback project with this problem, because there's not much I can say to find out the problem if I can't have the entire view.
Hi @arandn2 , I did what you said,but it keeps throwing me this error:
Cannot start the application. TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined at validateString (internal/validators.js:117:11) at Object.resolve (path.js:980:7) at new Bootstrapper (/Users/Sergio/Documents/kloustr/socketio/myIntSocketIO/my-int-socket-io/node_modules/@loopback/boot/src/bootstrapper.ts:46:24)
Do you know what might I be doing wrong?
@sergiogaitan I have say many things in this thread.. jajajajajajajaja... Please, tell me which of my comments you are talking about to try to help you.
Otherwise, did you run the example that I left?
@arondn2 Thanks for solving this issue, this example works great: https://github.com/arondn2/loopback4-example-websocket-app
@arondn2 how to get io
instance from rest / websocket controllers ? The broadcast don't comes from a socket.
async controllerMethod(
@ws.server() io: Server
): Promise<any> {
// ...
}
regards, @d-bo
Have anyone tried to implement the 'socket.io-client', loopback way? @arondn2, thanks your example is awesome! ;)
hi @w20k. Here is a example how to use socket.io-client for a acceptance test. https://github.com/strongloop/loopback-next/blob/socketio/extensions/socketio/src/tests/acceptance/socketio.server.acceptance.ts. I think you need to install socket.io-client and @types/socket.io-client dependencies
Hi, @arondn2 thanks for a quick answer. Probably my issue is a bit more complicated :)
I have a bidirectional connection via WebSocket where loopback is a middleman with (currently) Socket.io server (from the example). And now I need to figure out a proper way to initiate a connection to a server using the (as I've understood SocketIoServer doesn't support it?) 'socket.io-client', and somehow make those two websockets communicate, per user session_id. Communication part is not an issue, but to subscribe for client messages and push those on server.
Or that's the only option, and I'm overthinking 😄
@w20k I'm not sure I understand. The scheme that you are trying to explain is something like this:
And are you trying send messages from (1) to (2) and those message from (2) to (3)? For this you need server.io-client in (2)?
@arondn2 yeah, you got it right.
It's a WebSocket connection between (1) - (3), where (2) is a "Websocket manager", of some sort. And we need to send a message from (1) - (3) on login to establish a Websocket connection and back to client (3) - (1) if there were any updates.
And, yes, for this I was thinking I'd need to use 'server.io-client' in (2).
@w20k if (3) is public or visible for (1) you can connect directly to (3). But I think (3) is private or maybe you just is required connect through (2). If this is the case, my opinion is you must implement a kind of proxy, where client in (1) connects to server in (2) and a client in (2) using socket.io-client in loopback connects to server in (3).
Also (2) must catch events from client in (1) and emit them to server in (3) and catch events from server in (3) and emit them to (1).
You could do the latter linking event by event, or you could use socket.use
(documentation) for dynamically linking.
i want implement socket in my loopback4 server API. i have integrate socket in my API but it;s routing is not working.
it's my code but socket is not connected. i have seen this example.
https://github.com/raymondfeng/loopback4-example-websocket/ but it's work only socket server not working with API server. please suggest me how i can implement.