I am trying to establish a peer-to-peer video connection between a web frontend and a react-native android smart tv app. I want to display the user's webcam video on the smart tv. I am using an express server for signaling:
const app = require("express")();
const server = require("http").createServer(app);
const cors = require("cors");
const io = require("socket.io")(server, {
cors: {
origin: "*",
methods: [ "GET", "POST" ]
}
});
app.use(cors());
const PORT = process.env.PORT || 8082;
//here we define the behaviour of the API Endpoints
app.get('/', (req, res) => {
res.send('Runnin');
});
app.post('/',(req,res) => {
const body = req.body;
res.send(body);
});
io.on("connection", (socket) => {
socket.emit("me", socket.id);
console.log(socket.id);
socket.on("disconnect", () => {
socket.broadcast.emit("callEnded")
});
socket.on("callUser", ({ userToCall, signalData, from, name }) => {
io.to(userToCall).emit("callUser", { signal: signalData, from, name });
});
socket.on("answerCall", (data) => {
io.to(data.to).emit("callAccepted", data.signal)
});
});
server.listen(PORT, () => console.log(`Server is running on port ${PORT}`));
The signaling is working but as I am trying to display the video the following error is displayed:
[Link to screenshot of the error][1]
Code of the react-native Callscreen component:
import React, { useEffect, useState, useCallback, useContext } from 'react';
import { View, StyleSheet, Alert, Button, Text } from 'react-native';
import { RTCView } from 'react-native-webrtc';
import { SocketContext } from './Context';
import Callnotification from './Callnotifcation';
function CallScreen(props) {
const { callAccepted, userVideo, callEnded, me } = useContext(SocketContext);
return (
<>
{callAccepted && !callEnded && (
<View style={styles.root}>
<View style={[styles.videos, styles.remoteVideos]}>
<Text>Video of the caller</Text>
<RTCView streamURL={JSON.stringify(userVideo)} style={styles.remoteVideo} />
</View>
</View>
)
}
<View style={styles.root}>
<Callnotification />
<Text>{JSON.stringify(me)}</Text>
</View>
</>
);
}
Code of the Context.js connecting the react-native app to the signaling server:
import React, { createContext, useState, useRef, useEffect } from 'react';
import { io } from 'socket.io-client';
import Peer from 'simple-peer';
const SocketContext = createContext();
const socket = io('http://10.0.2.2:8082'); // use this to access via android emulator
//const socket = io('http://192.168.178.106:8082'); //use this to access via SmartTv Fire Tv Stick
const ContextProvider = ({ children }) => {
const [callAccepted, setCallAccepted] = useState(false);
const [callEnded, setCallEnded] = useState(false);
const [stream, setStream] = useState();
const [name, setName] = useState('');
const [call, setCall] = useState({});
const [me, setMe] = useState('');
const userVideo = useRef();
const connectionRef = useRef();
useEffect(() => {
socket.on('me', (id) => setMe(id));
socket.on('callUser', ({ from, name: callerName, signal }) => {
setCall({ isReceivingCall: true, from, name: callerName, signal });
});
}, []);
const answerCall = () => {
setCallAccepted(true);
const peer = new Peer({ initiator: false, trickle: false, stream });
peer.on('signal', (data) => {
socket.emit('answerCall', { signal: data, to: call.from });
});
peer.on('stream', (currentStream) => {
userVideo.current.srcObject = currentStream;
});
peer.signal(call.signal);
connectionRef.current = peer;
};
/* const callUser = (id) => {
const peer = new Peer({ initiator: true, trickle: false, stream });
peer.on('signal', (data) => {
socket.emit('callUser', { userToCall: id, signalData: data, from: me, name });
});
peer.on('stream', (currentStream) => {
userVideo.current.srcObject = currentStream;
});
socket.on('callAccepted', (signal) => {
setCallAccepted(true);
peer.signal(signal);
});
connectionRef.current = peer;
};*/
const leaveCall = () => {
setCallEnded(true);
connectionRef.current.destroy();
};
return (
<SocketContext.Provider value={{
call,
callAccepted,
setCallAccepted,
userVideo,
stream,
name,
setName,
callEnded,
me,
leaveCall,
answerCall,
}}
>
{children}
</SocketContext.Provider>
);
};
export { ContextProvider, SocketContext };
Code of the Context.js connecting the web react frontend to the signaling server:
import React, { createContext, useState, useRef, useEffect } from 'react';
import { io } from 'socket.io-client';
import Peer from 'simple-peer';
const SocketContext = createContext();
// const socket = io('http://localhost:5000');
const socket = io('http://localhost:8082');
const ContextProvider = ({ children }) => {
const [callAccepted, setCallAccepted] = useState(false);
const [callEnded, setCallEnded] = useState(false);
const [stream, setStream] = useState();
const [name, setName] = useState('');
const [call, setCall] = useState({});
const [me, setMe] = useState('');
const myVideo = useRef();
const userVideo = useRef();
const connectionRef = useRef();
useEffect(() => {
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then((currentStream) => {
setStream(currentStream);
myVideo.current.srcObject = currentStream;
});
socket.on('me', (id) => setMe(id));
socket.on('callUser', ({ from, name: callerName, signal }) => {
setCall({ isReceivingCall: true, from, name: callerName, signal });
});
}, []);
const answerCall = () => {
setCallAccepted(true);
const peer = new Peer({ initiator: false, trickle: false, stream });
peer.on('signal', (data) => {
socket.emit('answerCall', { signal: data, to: call.from });
});
peer.on('stream', (currentStream) => {
userVideo.current.srcObject = currentStream;
});
peer.signal(call.signal);
connectionRef.current = peer;
};
const callUser = (id) => {
const peer = new Peer({ initiator: true, trickle: false, stream });
peer.on('signal', (data) => {
socket.emit('callUser', { userToCall: id, signalData: data, from: me, name });
});
peer.on('stream', (currentStream) => {
userVideo.current.srcObject = currentStream;
});
socket.on('callAccepted', (signal) => {
setCallAccepted(true);
peer.signal(signal);
});
connectionRef.current = peer;
};
const leaveCall = () => {
setCallEnded(true);
connectionRef.current.destroy();
window.location.reload();
};
return (
<SocketContext.Provider value={{
call,
callAccepted,
myVideo,
userVideo,
stream,
name,
setName,
callEnded,
me,
callUser,
leaveCall,
answerCall,
}}
>
{children}
</SocketContext.Provider>
);
};
export { ContextProvider, SocketContext };
In my opinion the error lies in the RTCView of the Callscreen but i have no idea how to fix it. Your help is very much appreciated!
Thank you very much!
[1]: https://i.stack.imgur.com/YBh9P.jpg
The library that you are using is probably using the SubtleCrypto.generateKey function to generate shared secrets. This API is "only available in a secure context", which means that it can only be used if the page is served over HTTPS.
Serve your page over HTTPS, and the error should go away.
I have a problem with axios Post. I work on adding Stripe payment to my page, but i send me axios error 404.
Maybe somebody can help me, I stuck on it for week already and cant just solve it.
Here is the code:
import React from 'react'
import StripeCheckout from 'react-stripe-checkout';
import { useState, useEffect } from "react";
import { useNavigate } from 'react-router-dom';
import axios from "axios";
const Pay = () => {
const [stripeToken, setStripeToken] = useState(null)
const navigate = useNavigate()
const onToken = (token) => {
setStripeToken(token);
}
useEffect(() => {
const makeRequest = async () => {
try {
const res = await axios.post(
"http//:localhost:5001/api/checkout/payment",
{
tokenId: stripeToken.id,
amount: 6000,
});
console.log(res.data)
} catch (err) {
console.log(err)
}
};
stripeToken && makeRequest()
}, [stripeToken]);
return (
<div className='pay__div'>
{stripeToken ? (<span>Processing</span>) : (
<StripeCheckout
name="Kate store"
image=""
billingAddress
shippingAddress
description="Yout total is $60"
amount={2000}
token={onToken}
stripeKey={KEY}
>
<button>Pay</button>
</StripeCheckout>
)}
</div>
)
}
export default Pay
Thank you for your time.
Also here are stripe.js index.js pages from backend
stripe.js
const router = require("express").Router();
const stripe = require("stripe")(process.env.STRIPE_KEY);
router.post("/payment", (req, res) => {
stripe.charges.create({
sourse: req.body.tokenId,
amount: req.body.amount,
currency: "usd"
},
(stripeErr, stripeRes) => {
if (stripeErr) {
res.status(500).json(stripeErr);
} else {
res.status(200).json(stripeRes);
}
});
});
module.exports = router;
And index.js
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const userRoute = require("./routes/user");
const authRoute = require("./routes/auth");
const productRoute = require("./routes/product");
const cartRoute = require("./routes/cart");
const orderRoute = require("./routes/order");
const stripeRoute = require("./routes/stripe");
const cors = require("cors");
dotenv.config();
mongoose.connect(process.env.MONGO_URL)
.then(() => console.log("DB Connected Successfull!"))
.catch((err) => {
console.log(err);
})
app.use(cors());
app.use(express.json());
app.use("/api/user", userRoute);
app.use("/api/auth", authRoute);
app.use("/api/product", productRoute);
app.use("/api/cart", cartRoute);
app.use("/api/order", orderRoute);
app.use("/api/checkout", stripeRoute);
app.listen(process.env.PORT || 5001, () => {
console.log("Backend is running")
})
Had the same problem. Moved dotenv.config(); before const stripeRoute = require("./routes/stripe"); in index.js and worked.
I have a module whith the connection:
import { createContext } from 'react';
import SInfo from 'react-native-sensitive-info';
import io from 'socket.io-client';
export const socket = io('http://192...', {
forceNew: true,
auth: {
token: 'eyJhbGciO...'
},
});
export const SocketContext = createContext(undefined);
But my token is saved by lib react-native-sensitive-info and i need to get it by
await SInfo.getItem('token', {});
My question is: How can I use await to get the token I need to export the socket?
Something like this:
export const socket = io('http://192...', {
forceNew: true,
auth: {
token: await SInfo.getItem('token', {});
},
});
Thanks in advance :D
Try this:
export const socket = async () => {
const token = await SInfo.getItem('token', {});
return io('http://192...', {
forceNew: true,
auth: {
token,
},
});
}
or
export const createSocket = (token) => {
return io('http://192...', {
forceNew: true,
auth: {
token,
},
});
}
and then use it in this way:
const token = await SInfo.getItem('token', {});
const socket = createSocket(token)
I know that similar questions have already been here, but I didn't find anything for my problem.
I am creating project using [Webpack-Express-Pug-VanillaJS] stack of technologies.
I'm trying to make POST-request to send formData to '/api/users' using fetch a push data to array in my express file, but its only pending...
What kind of problems it can be?
client-side code
document.addEventListener('DOMContentLoaded', () => {
async function postData(url, data) {
try {
console.log('addEventListener works!')
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
console.log('fetch works!')
return await response.json()
} catch(e) {
console.warn('Error',e.message)
}
}
const forms = document.getElementsByTagName('FORM');
for (let i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(e) {
console.log(forms[i])
e.preventDefault();
let formData = new FormData(this);
formData = Object.fromEntries(formData);
console.log(formData) return object like {name:'Zhanna', age:25, email:'123zhanna#gmail.com'}
postData('/api/users', formData).then(data => console.log('Successful!'))
})
}
})
server-side
const path = require('path')
const express =require('express')
const webpack = require('webpack')
const bodyParser = require('body-parser')
const users = require('../routes/userInfo')
import webpackDevMiddleware from 'webpack-dev-middleware'
import webpackHotMiddleware from 'webpack-hot-middleware'
import config from '../../webpack.dev.config.js'
import { v4 } from 'uuid';
const PORT = process.env.PORT || 8080
const app = express(),
compiler = webpack(config)
app.use(users.router);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.json());
app.set('views', path.join(__dirname, "views"));
app.set('view engine', 'pug');
app.locals.basedir = __dirname;
app.use('/assets',express.static(path.join(__dirname,'assets')))
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath
})
)
app.use(webpackHotMiddleware(compiler))
app.get('/registration', (req,res)=> {
res.status(200).render('registration')
})
app.get('/login', (req,res)=> {
res.status(200).render('signIn')
})
app.get('/', (req, res) => {
res.status(200).render('index')
}
)
app.get('/api/users', (req,res)=> {
res.status(200).json(users.list)
})
app.post('/api/users', (req,res)=> {
const user = {...req.body, id:v4()}
users.list.push(user)
console.log('Data was sent')
res.status(201).json(user)
})
app.listen(PORT, () => {
console.log(`App listening to ${PORT}....`)
console.log('Press Ctrl+C to quit.')
})
And in my console there is only 3 logs:
addEvent listener works!
<form class="registration--form" id="send-form">...<form>
3.{name: "Zhanna", surname: "Kaymedenova", gender: "female", brth: "07.01.1994", email: "zh.kaymed#gmail.com"}
I am trying to mock an axios call within a vuejs method. Is this possible?
Here is my vue component (SomeObj):
methods:{
callAxiosMethod() {
const callApi= axios.create();
callApi.defaults.timeout = 10000;
callApi.get(mockedUrl)
.then(response => {
console.log('response is ' + response);
})
.catch(e => {});
}
}
Here is my spec.js
let mockData = {};
beforeEach(() => {
jest.spyOn(axios, 'get').mockReturnValue(Promise.resolve(mockData));
});
let wrapper = shallowMount(SomeObj, {
stubs: [], localVue, mocks: {
mockUrl: mockUrl,
$route: {
params: { testId: "123" }
}
}
});
it('is a Vue instance', () => {
expect(wrapper.isVueInstance()).toBeTruthy();
axios.get.mockResolvedValue(mockData);
wrapper.vm.callAxiosMethod();
})
When I looked at the coverage, the system says the callApi is not covered. Any idea on how I can mock the axios call within the function?
Your code calls axios.create so you need to mock that function to return a mock callApi object.
Here is a simplified working example:
code.js
import * as axios from 'axios';
const mockedUrl = 'http://mock-url';
export const callAxiosMethod = () => {
const callApi = axios.create();
callApi.defaults.timeout = 10000;
return callApi.get(mockedUrl); // <= return the Promise so it can be awaited
}
code.test.js
import { callAxiosMethod } from './code';
jest.mock('axios', () => ({
create: jest.fn().mockReturnValue({
defaults: {},
get: jest.fn().mockResolvedValue('mocked data')
})
}));
test('callAxiosMethod', async () => { // <= async test function
const response = await callAxiosMethod(); // <= await the Promise
expect(response).toBe('mocked data'); // Success!
});