WebSocket does not connect to nest.js server - sockets

I have this code in the chat.gateway.ts file:
#Injectable()
#WebSocketGateway()
export class ChatGateway {
#WebSocketServer()
server: any;
#SubscribeMessage('message')
handleMessage(#MessageBody() message: string): void {
this.server.emit('message', message);
}
}
The app.module.ts file code:
#Module({
imports: [
ConfigModule.forRoot({
envFilePath: `${process.cwd()}/${process.env.NODE_ENV}.env`,
isGlobal: true,
}),
ChatModule
],
controllers: [AppController],
providers: [AppService, ChatGateway, UserMiddleware],
})
but when I connect from the client side on this URL: ws://192.168.29.88:9000/chat?EIO=4&transport=websocket. This does not work. Am I missing something? If I replace the endpoint chat with socket.io, it connects, but I am unable to send the message, and the server disconnects automatically.

Related

How to Integrate Rest Api with GraphQL Gateway and send Context

I use GraphQL Gateway to integrate with GraphQL Federation Microservices .
but I use some Rest API code for some reason. like(refresh token , Upload Images with rest)
The Question is : how to communicate with Rest API for the other services from graphql gateway and how to send context to the controller(rest api) server.
import { IntrospectAndCompose, RemoteGraphQLDataSource } from '#apollo/gateway';
import { ApolloGatewayDriver, ApolloGatewayDriverConfig } from '#nestjs/apollo';
import { Module } from '#nestjs/common';
import { GraphQLModule } from '#nestjs/graphql';
import { AppController } from './app.controller';
#Module({
imports: [
GraphQLModule.forRoot<ApolloGatewayDriverConfig>({
driver: ApolloGatewayDriver,
server: {
// ... Apollo server options
context: ({ req, res }) => ({
authorization:req.headers.authorization,
req,
res,
url: req.protocol + '://' + req.headers.host,
}),
cors: true,
},
gateway: {
buildService({ name, url }) {
return new RemoteGraphQLDataSource({
url,
willSendRequest({ request, context }) {
request.http.headers.set('authorization',context['authorization'] );
}
});
},
supergraphSdl: new IntrospectAndCompose({
subgraphs: [
{ name: 'Service1', url: 'http://localhost:3001/graphql' },
{ name: 'Service2', url: 'http://localhost:3002/graphql' },
{ name: 'Service3' , url: 'http://localhost:3003/graphql' }
],
}),
},
}),
],controllers:[AppController]
})
export class AppModule { }
Note: if I removed '/graphql' from Url to access origin url , it gives me error[Couldn't load service definitions for service1] .
This code works fine with GraphQL but didn't work with Rest.
Server : NestJS.
Thanks..
Your question is not super clear but let me take a stab at it.
You can use a service like WunderGraph on top of your existing gateway or you can create a new gateway and ingest the GraphQL Federated Microservices. You can then introspect the REST API and ingest it into your gateway. .

Mongoose Error: Cannot read property 'length' of undefined in NestJs

I am using nests framework and versions of mongodb and mongoose are as specified below.
Please refer to the screenshot for error in detail.
versions
"mongodb": "4.0.0",
"mongoose": "5.5.12",
Error Screenshot
User Document Module
import { Module } from '#nestjs/common';
import { UserDocumentsService } from './user-documents.service';
import { UserDocumentsController } from './user-documents.controller';
import { MongooseModule } from '#nestjs/mongoose';
import { UserDocumentsSchema } from './schema/user-documents.schema';
#Module({
imports: [
// showing error on this line
MongooseModule.forFeature([
{ name: 'UserDocument', schema: UserDocumentsSchema },
]),
],
controllers: [UserDocumentsController],
providers: [UserDocumentsService],
})
export class UserDocumentsModule {}
App.module.ts
#Module({
imports: [
MongooseModule.forRootAsync({
imports: [SharedModule],
useFactory: async (configService: ConfigService) => ({
uri: configService.mongoDBName(),
useNewUrlParser: true,
useFindAndModify: false,
}),
inject: [ConfigService],
}),
UserDocumentsModule,
],
providers: [AppGateway],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer): MiddlewareConsumer | void {
consumer.apply(contextMiddleware).forRoutes('*');
}
}
UPDATE
I think there is something wrong with the mongoose imports in the schema file. It says "could not find declaration for module 'mongoose'".
I tried removing and reinstalling mongoose and it's types. But now it shows new error.
I tried solutions mentioned in this post:
Node.js heap out of memory
But this also didn't work for me.
I'm using Mac-M1 with 8GB config.
UPDATE
The issue has been resolved now. The project is running on node v10.24.1 and I was using node v16.6.2.
After downgrading node version using NVM, this issue is gone.
You'll have to pull SharedModule import off MongooseModule.
Try this:
#Module({
imports: [
MongooseModule.forRootAsync({
useFactory: async (configService: ConfigService) => ({
uri: configService.mongoDBName(),
useNewUrlParser: true,
useFindAndModify: false,
}),
inject: [ConfigService],
}),
UserDocumentsModule,
SharedModule
],
providers: [AppGateway],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer): MiddlewareConsumer | void {
consumer.apply(contextMiddleware).forRoutes('*');
}
}
It was because I was using a wrong version of node. The project was built on node v10.24.1 and I was using node v16.6.2.
After downgrading node version using NVM, I was able to fix this issue.

Open device settings with Ionic Capacitor

I’m trying to find a way to open the settings/preferences app with capacitor but I’m unsuccessful.
App.canOpenUrl({ url: 'com.apple.Preferences' }) is failing with error message -canOpenURL: failed for URL: "com.apple.Preferences" - error: "Invalid input URL"
I’m not sure if I’m doing it wrong or if it’s even possible with capacitor to open native app…?
this article shows how to open the facebook app, but nothing about native app
There's now a capacitor plugin for this, capacitor native settings.
It's similar to the cordova plugin but you have to call the correct function for each platform (iOS or Android) instead of using a single function for both.
for someone with the same problem
Install:
cordova-open-native-settings
$ npm install cordova-open-native-settings
$ npm install #ionic-native/open-native-settings
$ ionic cap sync
app.module.ts
// ...
import { OpenNativeSettings } from '#ionic-native/open-native-settings/ngx';
#NgModule({
declarations: [
// ...
],
entryComponents: [
// ...
],
imports: [
// ...
],
providers: [
// ...
OpenNativeSettings,
],
bootstrap: [AppComponent]
})
export class AppModule {}
whatever.page.ts
// ...
import { OpenNativeSettings } from '#ionic-native/open-native-settings/ngx';
#Component({
selector: 'app-whatever',
templateUrl: './whatever.page.html',
styleUrls: ['./whatever.page.scss'],
})
export class PopoverComponent implements OnInit {
constructor(
// ...
private nativeSettings: OpenNativeSettings
) { }
phoneSettings() {
this.nativeSettings
.open('settings')
.then( res => {
console.log(res);
})
.catch( err => {
console.log(err);
})
}
}

Angular2 HTTP Request Providers

I want to make connection between my angular app and my REST API.
Here it returns JSON http://is.njn.mvm.bg/check. So my question is which providers do I need because I include in app.module, but it still doesn't work.
import { HttpModule} from '#angular/http';
I am using Angular2 HTTP tutorial
private heroesUrl = 'http://is.njn.mvm.bg/check'; // URL to web API
constructor (private http: Http) {}
getHeroes (): Observable<Hero[]> {
return this.http.get(this.heroesUrl)
.map(this.extractData)
.catch(this.handleError);
}
I am getting XMLHttpRequest cannot load http://localhost:8000/da. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
you are using the http request wrong. plz use following code.
app.component.ts
//our root app component
import { Component } from '#angular/core'
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
#Component({
selector: 'root',
template: `
<div>
{{people}}
{{ err}}
</div>
`
})
export class App {
people;
err;
constructor(http:Http) {
http.get('http://is.njn.mvm.bg/check').map(res => res.text()).subscribe(people => this.people = people,err=>this.err = err);
// Subscribe to the observable to get the parsed people object and attach it to the
// component
}
}
Also remember
Follow error occur in your console:
Access-control-allow-origin
For remove this error see:
chrome extension for access control
You need to put header parameter "Access-Control-Allow-Origin" in the server's HTTP response. You can't make this work from the client side only. I also had the same issue when trying to grab data from my Java JSON REST server. I am not sure what you use server side, but in Java it looks something like this:
return Response.ok() //200
.header("Access-Control-Allow-Origin", "*");
For information on this error (CORS), see this:
How does Access-Control-Allow-Origin header work?
You also need to add it to imports of #NgModule
#NgModule({
imports: [BrowserModule, HttpModule]
...
})
You module code will be like below:
#NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
],
declarations: [
AppComponent
],
providers: [
{provide: APP_BASE_HREF, useValue: '/'},
],
bootstrap: [AppComponent]
})
export class AppModule {
}
you service code need to similar to this
constructor(private http: Http) {
}
getCountriesByRegion(region: string) {
return this.http.get(this.countries_endpoint_url + region).map(res => res.json());
}
//you can also do like this
getHeroes(): Observable<any[]> {
return this.http.get(this.heroesUrl)
.map(this.extractData)
.catch(this.handleError);
}
You have the Angular app that's served by the server running on port 3000, but this app tries to make HTTP calls to the server running on another port 8000.
You have two options:
1. Deploy your Angular app under the server that runs on port 8000, in which case your Angular app will hit the same port it was served from.
2. Configure a proxy on the server that runs on port 3000 to allow access to port 8000.
For the second scenario, if you use Angular CLI with your project, create a file proxy-conf.json, for example:
{
 "/api": {
 "target": "http://localhost:8000",
 "secure": false
 }
}
Then sevre your Anglar app like this:
ng serve --proxy-config proxy-conf.json

Angular2 HTTP - How to understand that the backend server is down

I am developing a front end which consumes JSON services provided by a server.
I happily use HTTP of Angular2 and I can catch errors via .catch() operator.
If I find a problem related to a specific service (e.g. the service is not defined by the server) the catch() operator receives a Response with status 404 and I can easily manage the situation.
On the other hand, if it is the server that is completely down, the catch() operator receives a Response with status code 200and no specific sign or text related to the cause of the problem (which is that the whole server is down).
On the console I see that angular (http.dev.js) writes a message net::ERR_CONNECTION_REFUSED but I do not know how to do something similar (i.e. understand what is happening and react appropriately) from within my code.
Any help would be appreciated.
If you would like to handle this event globally in your application I recommend using slightly modified Nicolas Henneaux's answer https://stackoverflow.com/a/37028266/1549135
Basically you can check for error.status === 0 which happens when the net::ERR_CONNECTION_REFUSED error occurs.
The complete module file:
import { Request, XHRBackend, BrowserXhr, ResponseOptions, XSRFStrategy, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
export class AuthenticationConnectionBackend extends XHRBackend {
constructor(_browserXhr: BrowserXhr, _baseResponseOptions: ResponseOptions, _xsrfStrategy: XSRFStrategy) {
super(_browserXhr, _baseResponseOptions, _xsrfStrategy);
}
createConnection(request: Request) {
let xhrConnection = super.createConnection(request);
xhrConnection.response = xhrConnection.response.catch((error: Response) => {
if (error.status === 0){
console.log("Server is down...")
}
...
return Observable.throw(error);
});
return xhrConnection;
}
}
Module file:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { HttpModule, XHRBackend } from '#angular/http';
import { AppComponent } from './app.component';
import { AuthenticationConnectionBackend } from './authenticated-connection.backend';
#NgModule({
bootstrap: [AppComponent],
declarations: [
AppComponent,
],
entryComponents: [AppComponent],
imports: [
BrowserModule,
CommonModule,
HttpModule,
],
providers: [
{ provide: XHRBackend, useClass: AuthenticationConnectionBackend },
],
})
export class AppModule {
}
I have the same problem while using angular2.0.0-beta.15
It seems like this is a bug. You get http status 200 and this is not correct:
https://github.com/angular/http/issues/54
Well i have faced something similar before. I was trying to make a logging Service and a Error handling which tells the user if error happened with some requests to the server or if the whole server is down.
I used HTTP Interceptor to catch the responses here is the code:
export class HttpErrorHandlingInterceptor implements HttpInterceptor {
constructor(private logService: LogService,
private layoutStateService: LayoutStateService){}
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (req.url) {
return next.handle(req).pipe(
map((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
return event;
}
}),catchError(err => {
if(!err.status){
this.layoutStateService.dispatchServerDown();
}else{
this.layoutStateService.dispatchAddServerError(err);
this.logService.logError(err);
}
throw err;
})
);
}
}
}
Now you can specify what should happen when Server is down according to your application.
Hope that helps.