React native zoomclone app, how to connect different devices via reactapp and able to render other devices streams - react-native

how to connect other devices via socketio and webrtc in a react native app. I have tried using API_URL = my pc's ip address || 5000, can anyone tell me how to connect other android devices after installing the react native app. I am done with the coding part, but in node server I am not able to see any user connected, or mediadetails, or roomID or deviceID? I am using nodejs as backend.
I have tried creating peerServer =new Peer(undefined,{host:"/",port:443}) object inside async function.
I am not able to get massage connected client on the server side. i.e
socket.on('connection', () => console.log('connected client')); this line of code is not able to execute correctly.
server.js code
const express = require('express');
const http = require('http');
const socketio = require('socket.io');
const morgan = require('morgan');
const {ExpressPeerServer} = require('peer');
const { join } = require('path');
const app = express();
const server = http.createServer(app)
const io = socketio(server).sockets;
// Borderparser
app.use(express.json());
const customGenerationFunction = () =>
(Math.random().toString(36) + "00000000000000000").substr(2,16);
const peerServer = ExpressPeerServer(server, {
debug: true,
path:'/',
generateClientId: customGenerationFunction,
});
app.use("/mypeer", peerServer);
io.on('connection', function (socket){
socket.on('join-room', ({roomID, userId}) => {
socket.join(roomID);
socket.to(roomID).broadcast.emit("user-connected", userId);
});
});
const port = process.env.PORT || 5000;
server.listen(port, () => console.log(`Server is running on port
${port}`))
--------------------video-action.js codes-------------------------------
import IO from 'socket.io-client';
import Peer from 'react-native-peerjs';
import AsyncStorage from '#react-native-async-storage/async-storage';
import {mediaDevices} from 'react-native-webrtc';
import {ADD_STREAM, MY_STREAM, ADD_REMOTE_STREAM} from './types';
//* api uri*/
export const API_URI = `http://192.168.01.36:5000`;
//**socket config */
export const socket = IO(`${API_URI}`,{
forceNew: true
})
peerServer =new Peer(undefined,
{
host:'192.168.216.202',
secure: false,
port:5000,
path: '/mypeer',
})
peerServer.on('error', console.log);
socket.on('connection', () => console.log('connected client'));
export const joinRoom = (stream) => async (dispatch) => {
const roomID = 'ahdbflarlkhnlfkjvaerbjhfbjds';
//set my own stream
dispatch({type: MY_STREAM, payload: stream});
//open a connection to our server
peerServer.on('open', (userId) => {
socket.emit('join-room', {userId, roomID});
});
socket.on('user-connected', (userId) => {
connectToNewUser(userId, stream, dispatch)
});
// recieve a call
peerServer.on('call', (call) => {
call.answer(stream);
// stream back the call
call.on('stream', (stream) => {
dispatch({type: ADD_STREAM, payload: stream});
});
});
};
function connectToNewUser(userId, stream, dispatch) {
const call = peerServer.call(userId, stream);
}

Related

Shopify App hosted on fly.io oAuth/Auth callbacks failing

Currently I am trying to deploy my Shopify Custom App to Fly.io. Installing this app is succeeding on my development store but I get an error right after with the oAuth callback with status code 400. This is the URL it shows upon installing:
https://appname.fly.dev/api/auth/callback?code=71bfdaadd63b87eb72d9d3dc516ea1ea&hmac=1efd4ff63ebca8f28c733f464ded354ba2f0995aeb1910114e0139eaefd4cce3&host=YWRtaW4uc2hvcGlmeS5jb20vc3RvcmUvc2hvb3B5bG9vcHkx&shop=shoopyloopy1.myshopify.com&state=920113322594675&timestamp=1676563785
With text in body: Invalid OAuth callback.
The app works with all the callbacks working with a ngrok tunnel during development. Just not when deployed to fly.io. The apps frontend also works after deployment to fly.io, but all the api and auth callbacks fail to work. I get the following response on those API calls:
On performing API calls on the /api/ route I get the following error in the return of the api call:
Failed to parse session token 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczpcL1wvc2hvb3B5bG9vcHkxLm15c2hvcGlmeS5jb21cL2FkbWluIiwiZGVzdCI6Imh0dHBzOlwvXC9zaG9vcHlsb29weTEubXlzaG9waWZ5LmNvbSIsImF1ZCI6IjU4YTAzZjkwZTk4Yjc5NGRlZmE5NDZlMWZiNmVlMzRiIiwic3ViIjoiNzQ3NzAxNTM2NjEiLCJleHAiOjE2NzY1NjQyMjYsIm5iZiI6MTY3NjU2NDE2NiwiaWF0IjoxNjc2NTY0MTY2LCJqdGkiOiI0OTcyNDEwOC0zNWQ2LTRjODEtOWJkNS0wZWRkMWM4MWIxMDYiLCJzaWQiOiIxOGZmZjg5NTMyZGRiODdiOWQ3OTBhYmY1M2EwOTZiMDNkNmE4ZWU1ZTA0ZmRjZmFmOWUxOWM2OGQxZGFjN2Q2In0.XeuA5W95YjjVLZYOvmRJ9a90xpPNEukhNQ1_z4Kw_xA': signature verification failed
My fly.toml file:
app = "appname"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []
[env]
PORT = "8081"
HOST = "https://appname.fly.dev"
SHOPIFY_API_KEY = "58a03f90e98b794defa946e1fb6ee34b"
SCOPES = "write_products,read_script_tags,write_script_tags"
[experimental]
auto_rollback = true
[[services]]
http_checks = []
internal_port = 8081
processes = ["app"]
protocol = "tcp"
script_checks = []
[services.concurrency]
hard_limit = 25
soft_limit = 20
type = "connections"
[[services.ports]]
force_https = true
handlers = ["http"]
port = 80
[[services.ports]]
handlers = ["tls", "http"]
port = 443
[[services.tcp_checks]]
grace_period = "1s"
interval = "15s"
restart_limit = 0
timeout = "2s"
My index.js file starting up express:
// #ts-check
import { join } from "path";
import { readFileSync } from "fs";
import express from "express";
import serveStatic from "serve-static";
import shopify from "./shopify.js";
import productCreator from "./product-creator.js";
import GDPRWebhookHandlers from "./gdpr.js";
import {addScriptTag, deleteScriptTag, getProductInfo, getProductsFromIds, getScriptTags} from "./graph-functions.js";
const PORT = parseInt(process.env.BACKEND_PORT || process.env.PORT, 10);
const STATIC_PATH =
process.env.NODE_ENV === "production"
? `${process.cwd()}/frontend/dist`
: `${process.cwd()}/frontend/`;
const app = express();
// Set up Shopify authentication and webhook handling
app.get(shopify.config.auth.path, shopify.auth.begin());
app.get(
shopify.config.auth.callbackPath,
shopify.auth.callback(),
shopify.redirectToShopifyOrAppRoot()
);
app.post(
shopify.config.webhooks.path,
shopify.processWebhooks({ webhookHandlers: GDPRWebhookHandlers })
);
// All endpoints after this point will require an active session
app.use("/api/*", shopify.validateAuthenticatedSession());
app.use(express.json());
app.get("/api/products/count", async (_req, res) => {
const countData = await shopify.api.rest.Product.count({
session: res.locals.shopify.session,
});
res.status(200).send(countData);
});
app.get("/api/get-product", async (_req, res) => {
const products = await getProductInfo(res.locals.shopify.session, _req.query.id);
res.status(200).send(products);
});
app.get("/api/get-products", async (_req, res) => {
const products = await getProductsFromIds(res.locals.shopify.session,_req.query.ids);
res.status(200).send(products);
});
app.get("/api/add-script", async (_req, res) => {
const data = await addScriptTag(res.locals.shopify.session,_req.query.src);
console.log(_req.query.ids);
res.status(200).send(data);
});
app.get("/api/get-scripts", async (_req, res) => {
const data = await getScriptTags(res.locals.shopify.session);
res.status(200).send(data?.body?.data ? data?.body?.data : data);
});
app.get("/api/delete-script", async (_req, res) => {
const data = await deleteScriptTag(res.locals.shopify.session,_req.query.id);
res.status(200).send(data);
});
app.get("/api/products/create", async (_req, res) => {
let status = 200;
let error = null;
try {
await productCreator(res.locals.shopify.session);
} catch (e) {
console.log(`Failed to process products/create: ${e.message}`);
status = 500;
error = e.message;
}
res.status(status).send({ success: status === 200, error });
});
app.use(serveStatic(STATIC_PATH, { index: false }));
app.use("/*", shopify.ensureInstalledOnShop(), async (_req, res, _next) => {
return res
.status(200)
.set("Content-Type", "text/html")
.send(readFileSync(join(STATIC_PATH, "index.html")));
});
app.listen(PORT);
Any help would be highly appreciated.
I followed the official documentation: Shopify Official Docs
The Dockerfile has the same port 8081 as assigned to in the fly.toml file.
Edit (Added shopify app implementation with Database):
import { LATEST_API_VERSION } from "#shopify/shopify-api";
import { shopifyApp } from "#shopify/shopify-app-express";
import { SQLiteSessionStorage } from "#shopify/shopify-app-session-storage-sqlite";
import { restResources } from "#shopify/shopify-api/rest/admin/2023-01";
const DB_PATH = `${process.cwd()}/database.sqlite`;
const shopify = shopifyApp({
api: {
apiVersion: LATEST_API_VERSION,
restResources,
billing: undefined, // or replace with billingConfig above to enable example billing
},
auth: {
path: "/api/auth",
callbackPath: "/api/auth/callback",
},
webhooks: {
path: "/api/webhooks",
},
// This should be replaced with your preferred storage strategy
sessionStorage: new SQLiteSessionStorage(DB_PATH),
});
export default shopify;

Socket.io client is not connecting to the server

I am trying to connect to the socket.io client using the following server-side code...
const express = require("express");
const { createServer } = require("HTTP");
const { Server } = require("socket.io");
const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer);
io.on("connection", (socket) => {
console.log("New user connected");
socket.on("join_room", (room) => {
socket.join(room);
socket.on("message", (msg) => {
io.to(room).emit("update_msg", msg);
});
});
});
const PORT = process.env.PORT || 5000;
httpServer.listen(PORT, () => {
console.log(`Server has started on port number ${PORT}`);
});
My client-side code is as follows.
const socket = io("http://localhost:5000");
socket.emit("join_room", "Room1");
When I am running the above codes it does not print anything in the console. I am using socket.io and socket.io-client version 4.5.0 on the server-side and client-side respectively.
const express = require("express");
const { createServer } = require("http");
const { Server } = require("socket.io");
const cors = require('cors')
const app = express();
app.use(cors())
const httpServer = createServer(app);
const io = new Server(httpServer, { cors: {
origin: "http://localhost:4200",
methods: ["GET", "POST"]
}});
io.on("connection", (socket) => {
console.log("New user connected");
socket.on("join_room", (room) => {
socket.join(room);
socket.on("message", (msg) => {
io.to(room).emit("update_msg", msg);
});
});
});
const PORT = process.env.PORT || 5001;
httpServer.listen(PORT, () => {
console.log(`Server has started on port number ${PORT}`);
});
Hope above code will work.
Please confirm, Did you enable the CORS?, if you're trying to access from different origin.
For your'e reference, I have added the CORS while creating the HTTP Server
Ref: https://socket.io/docs/v3/handling-cors/

Nuxt/Express API is returning in console but not browser

I'm quite new to this whole backend business and I'm wondering if anyone can see where I'm going wrong. I've got an express server in my Nuxt app which is serving out an API. When I run the localhost:3000/api/salesforce/:id route - my vscode terminal generates a response - but it doesn't show up on the browser. Which in turn makes it inaccessible to Nuxt.
In my nuxt.config.js:
serverMiddleware: {
'/api': '~/api'
},
/api/index.js:
const express = require('express')
// Create express instance
const app = express()
// Require API routes
const users = require('./routes/users')
const test = require('./routes/test')
const salesforce = require('./routes/salesforce')
// Import API Routes
app.use(users)
app.use(test)
app.use(salesforce)
// Export express app
module.exports = app
// Start standalone server if directly running
if (require.main === module) {
const port = process.env.PORT || 3001
app.listen(port, () => {
// eslint-disable-next-line no-console
console.log(`API server listening on port ${port}`)
})
}
Then in /api/routes/salesforce.js:
const e = require('express')
const { Router } = require('express')
const router = Router()
const jsforce = require('jsforce');
// require the .env file for login
require('dotenv').config();
const { SF_USERNAME, SF_PASSWORD, SF_TOKEN, SF_LOGIN_URL } = process.env;
if (!(SF_USERNAME && SF_PASSWORD && SF_TOKEN && SF_LOGIN_URL)) {
console.error(
'Cannot start app: missing mandatory configuration. Check your .env file.'
);
process.exit(-1);
}
const conn = new jsforce.Connection({
loginUrl: SF_LOGIN_URL
});
conn.login(SF_USERNAME, SF_PASSWORD + SF_TOKEN, err => {
if (err) {
console.error(err);
process.exit(-1);
}
});
// get OPPORTUNITY specific
router.get('/salesforce/:id', function (req, res, next) {
const id = req.params.id
console.log(req.params.id)
const sfData = conn.query(`SELECT Id, Name, StageName FROM Opportunity WHERE Name = '` + id + `'`, (err, res)=>{
if(err){
console.log(err)
return "error";
} else {
console.log(res.records[0])
let sanitisedData = res.records[0]
return sanitisedData;
}
})
res.json(sfData.json)
})
If anyone can tell me where I'm going wrong that would be greatly appreciated, I'm kind of stuck here.

UnhandledPromiseRejectionWarning: Error: You must `await server.start()` before calling `server.applyMiddleware()` at ApolloServer

I am trying to start my nestJs server and It keeps giving me this error:
UnhandledPromiseRejectionWarning: Error: You must await server.start() before calling server.applyMiddleware()
at ApolloServer
I'm not even sure where to debug from as I am still very new at NestJs and GraphQL.
This is a known bug with an open issue and a merged PR to fix it. For now, you can downgrade to apollo-server-express#^2
A complete working code is:
const express = require("express");
const { ApolloServer } = require("apollo-server-express");
const http = require("http");
const app = express();
const typeDefs = `
type Query{
totalPosts: Int!
}
`;
const resolvers = {
Query: {
totalPosts: () => 100,
},
};
let apolloServer = null;
async function startServer() {
apolloServer = new ApolloServer({
typeDefs,
resolvers,
});
await apolloServer.start();
apolloServer.applyMiddleware({ app });
}
startServer();
const httpserver = http.createServer(app);
app.get("/rest", function (req, res) {
res.json({ data: "api working" });
});
app.listen(4000, function () {
console.log(`server running on port 4000`);
console.log(`gql path is ${apolloServer.graphqlPath}`);
});
I faced this issue when upgrading Ben Awad's Graphql-Next-Typeorm[...] stack, simply adding an await to server start fixed the warnings
const apolloServer = new ApolloServer({
introspection: true,
schema: await buildSchema({
resolvers: [__dirname + '/resolvers/**/*.js'],
validate: false
}),
context: ({ req, res }) => ({
req,
res,
redis: redisClient
}),
formatError
});
// added this line
await apolloServer.start();
apolloServer.applyMiddleware({
app,
cors: false
});
For Apollo Server Express 3.0 and above, you need to define an async function that takes in typeDefs and resolvers parameters, then assign the server to the same Apollo initialization as before as shown here
async function startApolloServer(typeDefs, resolvers){
const server = new ApolloServer({typeDefs, resolvers})
const app = express();
await server.start();
server.applyMiddleware({app, path: '/graphql'});
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}${server.graphqlPath}`);
})
}
startApolloServer(typeDefs, resolvers);
downgrading is not the option (at least anymore)
here is the solution =>
https://javascriptsu.wordpress.com/2021/08/02/apollo-error-must-await-server-start/
const server = new ApolloServer({ typeDefs, resolvers });
const app = express();
server.start().then(res => {
server.applyMiddleware({ app });
app.listen({ port: 3000 }, () =>
console.log("nice")
)
})
You can put everything in an async function and execute the function in your server(app,index...).js. You may also check the npm package.
https://www.npmjs.com/package/apollo-server-express
For example:
const express = require('express')
, http = require('http')
, path = require('path');
const { ApolloServer } = require('apollo-server-express');
async function startExpressApolloServer() {
const { typeDefs } = require('./graphql/schemas/schema');
const { resolvers } = require('./graphql/resolvers/resolver');
const server = new ApolloServer({ typeDefs, resolvers });
await server.start();
const app = express();
server.applyMiddleware({ app, path: '/api/graphql' });
await new Promise(resolve => app.listen({ port: 3001 }, resolve));
console.log(`Server ready at http://localhost:3001${server.graphqlPath}`);
return { server, app };
}
startExpressApolloServer();
I had the same type of problem. I was using TypeScript, Express, ApolloServer. What I did-
async function a(){
const server = new ApolloServer({ typeDefs, resolvers });
await server.start();
server.applyMiddleware({ app, path: '/graphql' });
}
a();
This is not a bug. As per the documentation, the Apollo server needs to be instantiated in an async function. This is the recommended setup for Apollo Express:
import { ApolloServer } from 'apollo-server-express';
import { ApolloServerPluginDrainHttpServer } from 'apollo-server-core';
import express from 'express';
import http from 'http';
async function startApolloServer(typeDefs, resolvers) {
const app = express();
const httpServer = http.createServer(app);
const server = new ApolloServer({
typeDefs,
resolvers,
plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
});
await server.start();
server.applyMiddleware({ app });
await new Promise(resolve => httpServer.listen({ port: 4000 }, resolve));
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
}
There are already some great answers here. But we should know why and where we should call server.start(). From apollo docs -
Always call await server.start() before calling
server.applyMiddleware and starting your HTTP server. This allows
you to react to Apollo Server startup failures by crashing your
process instead of starting to serve traffic.
One other option is to downgrade your apollo to any 2.x.x. It solved my problem
This is my working server:
import express from 'express';
import { ApolloServer } from 'apollo-server-express';
import typeDefs from './schema';
const app = express();
const server = new ApolloServer({
typeDefs,
mocks: true
});
server.start().then(() => {
server.applyMiddleware({
app,
cors: true,
});
});
const PORT = 4000;
app.listen(PORT, () => {
console.log(
`GraphQL endpoint and playground accessible at http://localhost:${PORT}${server.graphqlPath}`,
);
});
The key thing here is to wrap the "applyMiddleware" function call inside the "server.start" async function.
In v3, if you use apollo-server-express the start function is required https://www.apollographql.com/docs/apollo-server/api/apollo-server/#start.
You can do something like this.
const app = express()
app.use(express.urlencoded({ extended: true }))
app.use(express.json())
....
export const startup = async () => {
await server.start()
server.applyMiddleware({ app, path: `/api/${configs.region}/graphql` })
return app
}
// call startup in another file to get app
It is not ok to start the apollo server in advance. What happens with the case when I have to explicitly use http/https. Please see the following case:
const server = new ApolloServer({
typeDefs: [KeycloakTypeDefs, typeDefs], // 1. Add the Keycloak Type Defs
schemaDirectives: KeycloakSchemaDirectives, // 2. Add the
formatError: new ApolloErrorConverter(),
resolvers: resolvers,
context: ({ req }) => {
return makeContextWithDependencies(req);
}
});
server.applyMiddleware({ app });
http.createServer(app).listen(config.server.port, os.hostname());
const options = {
key: fs.readFileSync(config.server.ssl.keyFile, "utf8"),
cert: fs.readFileSync(config.server.ssl.certFile, "utf8"),
passphrase: config.server.ssl.passphrase
};
https
.createServer(options, app)
.listen(config.server.securePort, os.hostname());
console.log(
"Server waiting for requests on ports: " +
config.server.port +
"," +
config.server.securePort
);
We must wait for the server to get ready before adding middleware to it.
const app = express();
const apolloServer = new ApolloServer({
schema: await buildSchema({
resolvers: [HelloResolver],
validate: false,
}),
});
await apolloServer.start(); // First start the server then apply middleware on it
apolloServer.applyMiddleware({ app });
you can do like that, it works for me.
const server = new ApolloServer({ schema });
const startApollo = async () => {
try {
await server.start();
server.applyMiddleware({ app, path: "/api"})
} catch (error) {
console.log(error);
}
}

Run socket.io from an express route

I have researched on this but nothing seems to satisfy my need. I have an express route connected to a mongodb. Below is part of the code.
const express = require('express');
const socketIo = require("socket.io");
const dbconnect = require("./models");
const handle = require("./handlers");
const routes = require("./routes");
const app = express();
app.use('/messages', routes.messages);
const PORT = 3000;
const server = app.listen(3000, function() {
console.log(`Listening on 3000`);
dbconnect().then(() => {
console.log("MongoDb connected");
});
});
const io = socketIo(server);
io.on('connection', function(client) {
console.log('Connected...');
});
My route looks like this:
const router = require('express').Router();
const handle = require('../handlers/messages');
router.post('/unread_messages', handle.unread_messages);
module.exports = router;
My handler looks like this:
const db = require("../models");
exports.unread_messages = async (req, res, next) => {
try {
const unreadmessages = await db.messages.countDocuments({ $and: [{receiver: req.body.receiver},
{ messageread: false }]});
return res.json({ unreadmessages });
} catch (err) {
return next({ status: 400, message: `Cannot get unread messages ${err}` });
}
};
I would like to add socket to the "/unread_messages" route so that I get an update of the count of unread messages in realtime. How do I do that?