NestJS Websocket Gateway: using namespaces with the WS adapter - websocket

I am working on implementing a Websocket gateway in NestJS 7, as shown in the docs. I use the WS adapter.
const app = await NestFactory.create(ApplicationModule);
app.useWebSocketAdapter(new WsAdapter(app));
The problem I have is that the gateway accepts the connection regardless of the url. So for instance, If I define my gateway like so:
#WebSocketGateway(8080, {namespace: '/v3'}
export class MyGateway {}
Then this gateway's handleConnection is triggered regardless of the path the client requests:
ws://localhost:8080/some-other-path
This unfortunately means that all clients are connecting to every gateway. Is the namespace option only available for the socket.io adapter?

You need to specify the path option:
#WebSocketGateway(8080, {path: '/v3'}
Then you can connect with:
const socket = new WebSocket('ws://localhost:8080/v3');
Platform ws doesnt support namespaces. It's a feature of socket.io.
Reference: https://github.com/nestjs/nest/issues/4968#issuecomment-772494179

Related

how to add static(html,js) files for grpc

I have a grpc client and server. I have a protofile. I am using a grpc gateway and I want to use html for the client. There is a path localhost:8081/test, I would like it to be an html file when I go through this path. How can I tell the handler to give the html file in the response?
what should the handler look like?
syntax = "proto3";
option go_package = "/go_proto";
package api;
import "google/api/annotations.proto";
service authorization{
rpc Test(testRequest) returns (testResponse){
option(google.api.http) = {
get: "/test"
};
}
}
message testRequest{
}
message testResponse{
int32 arg1 = 1;
}
If I understand your question correctly, you cannot (directly).
gRPC Gateway is one way (Envoy's gRPC-JSON transcoder is another) to expose gRPC services as (JSON) REST APIs.
In your example, the above solutions will enable you to make HTTP GET calls against /test returning a JSON representation of testResponse ({"arg1":...}).
If you want to serve HTML, see Adding custom routes to the mux this would allow you to write a handler that serves HTML.
NOTE This HTML handler could include JavaScript that uses e.g. fetch to GET the /testendpoint.
Have a look at gRPC-Web too. This requires Node.JS but it provides a gRPC client for JavaScript as an alternative to the REST client described above.
If you want to expose gRPC services with REST APIs, then use gRPC Gateway or Envoy's gRPC-JSON transcoder. This gives you the ability to have clients that use gRPC and REST.
If you want to have only gRPC clients, gRPC-Web gives Node.JS developers access to your gRPC services too.

How to setup ApolloServer and SubscriptionServer to use http and ws in graphql

I have been following the docs for here and here to implement the subscriptions-transport-ws plugin. My big confusion is differentiating the graphql url for http:// and ws://. In the examples above it looks like ApolloServer is getting replaced by SubscriptionServer. But if I only want to use websockets in special circumstances, then don't I still need both? Or is SubscriptionServer handling both at once and doing some magic in the background which figures out which one to use based on whether or not a subscription is called?
apollo-server combines several tools such as: graphql-tools, graphql-subscriptions, graphql-upload, provide some custom errors, and use express.js web framework as its default web server implementation.
subscriptions-transport-ws is a GraphQL WebSocket server and client to facilitate GraphQL queries, mutations, and subscriptions over WebSocket.
subscriptions-transport-ws is an extension for GraphQL, and you can use it with any GraphQL client and server (not only Apollo).
So, ApolloServer is NOT replaced by SubscriptionServer.
Without using ApolloServer, you need to set up GraphQL HTTP server using express.js, graphqlExpress, graphiqlExpress, cors middlewares by yourself. Like this official sample does.
If you want to create a subscription server, you need to create HTTP server and pass it to SubscriptionServer constructor for initing and connecting WebSocket server to http

API Gateway WebSocket API postConnection timeout

I'm trying to set up a WebSocket API on API Gateway. I'm following the basic tutorial, and I have everything up and running -> Routes for $connect, $disconnect, "test", $default. I am able to connect to the API, store the connectionId in Redis, and retrieve it when accessing from the test route.
The problem is when I try to send back a message from my lambda (single lambda handling all routes). I'm using the following code
const apigwManagementApi = new AWS.ApiGatewayManagementApi({
apiVersion: '2018-11-29',
endpoint: `https://${event.requestContext.domainName}/${event.requestContext.stage}`
});
Then I call
await apigwManagementApi.postToConnection({
ConnectionId: connectionId,
Data: `Echo: ${data}`
}).promise()
This is only called on the "test" route.
All of this is as per their guide. I had to add a patch to be able to make postConnection work, again, as per their tutorial. The problem is when the above method is called I get a Internal Server Error message from the API Gateway and the lambda times out after 3 seconds.
There is very little info on this method. I'm not sure what is causing the internal server error. I have checked the endpoint and the connectionId, both are correct.
What am I doing wrong? Any suggestions?
So the problem wasn't the actual lambda but the fact that it wasn't set up in a VPC that had access to the Internet. So if you're lambda has VPC enabled, make sure you it has a NAT gateway and Internet gateway set up.

Connecting to AWS IoT Websocket without MQTT client

I have a client application which runs in the browser which I can't change the implementation of to implement an MQTT client such as mqtt on npm.
The code in the library is as follows and allows me to pass in a socketUrl
const ws = new WebSocket(socketUrl)
I have tried generating a presigned URL for IoT, which seems to work in terms of authenticating (i.e. no Unauthorized response) but I get a 426 Upgrade Required response.
I believe I'm correct in saying that if it were working it'd reply with a 101 Switching protocols but without knowing much about MQTT i'm unsure if this is not happening because I'm doing something wrong or because I'm not using MQTT.
I'm generating a signed URL using the below code (I'll switch to Cognito Identities if I get this working rather than using the fixed key/secret)
const v4 = require('aws-signature-v4')
const crypto = require('crypto')
const socketUrl = v4.createPresignedURL(
'GET',
'myioturl.iot.us-east-1.amazonaws.com',
'/mqtt', // tried just /mytopic, too
'iotdevicegateway',
crypto.createHash('sha256').update('', 'utf8').digest('hex'), {
'key': 'removed',
'secret': 'removed',
'protocol': 'wss',
'region': 'us-east-1'
}
)
The protocols page in the iot documentation seems to suggest that if I point at /mqtt I'm indicating I'll be using MQTT.
mqtt Specifies you will be sending MQTT messages over the WebSocket protocol.
What does this mean if I just specify /foobar? Should I be able to connect to the socket but not using MQTT?
There are quite a few unknowns for me so I'm struggling to work out if it should work at all, and if so, which bit am I doing wrong.

Can I use http request routs of sails.js in web-socket

Sails.js support both web-socket and http-request api call.
I have some route for my rest api like
get /api/v1/userController/fetch
but I can't call this route from socket, there is any way to bind this route in socket.io and call this route from both web-socket and http-request?
I found an android library here:
http://joshuamarquez.me/2016/06/12/how-to-use-sails.io.js-in-java/
This library is an wrapper around socket.io and connect to sails project in both socket and http way.
don't know why they don't mention this library in sails documentation :|

Resources