socket.io keep repeating fail request - javascript

I have strange issue. Basically the client will send a request i.e:delete chat, but Server will reject, since client is not authorized.
however, the client keep repeating the same request, even if I open new browser and load the same address. Both browser will keep requesting the previous action. my code looks something like this:
Client
socket.on(username, (res) => {
show(res.err)
})
socket.send({
type: "delete_chat",
username: username,
id: chat_id
})
Server:
io.sockets.on("connection", (socket) => {
socket.on("message", (data) => {
if(data.type === "delete_chat"){
Chat.delete(chatid, (err, res) => {
io.emit(username, {err:res}) //send error to username
});
}
})
})

Related

How socket.io can be used like axios?

I've an application, which is built in axios, just PUT, POST, DELETE, GET in mind. which looks like this
getAPI = axios.create(.....)
....
getAPI.post('signup/', {email, password})
.then(res => {
/// return some res
})
.catch(err => {
/// some error is show if not succeed
})
}
and also goes or "post/", "logout/", "signup/" with different methods.
Later i found that, In order to make post actions realtime in client side , we need to use websocket. So i used socket.io .
I've already setup server and client.
In server socket connection like this
io.on('connection', socket => {
console.log('User is connected on socket');
socket.on('disconnect', () => console.log('disconnected'));
})
and in client connection i've searc tutorials and used contextAPI, and passed to allcomponents.
in my specific component, where i've user post and user post is shown i've put code like this
const {socket} = useContext(AuthContext);
useEffect(() => {
socket.on("connect", () => {
console.log("client connected")
})
return ()=> socket.disconnect()
})
Now how can i use those of axios request with catch errors but with socket.io. It seems very hard to me using socket.io integrating with axios . Although i need not to use socket on authentication. But i need to use it on "/post" request.
Posting from client to server was easy by that axios.POST.then().catch(), axios.GET .....
but i'm confused to integrate that axios things in socket in client .
Also in backend side , i've routes like these
router.get('/logout', logout)
router.post('/post/create', post)
with each handler like these
exports.postCreate = (req, res) => {
let post = new Post(req.body)
post.save((err, post) => {
if(err){
return res.status(400).json({error: "Error"})
}
return res.json(post)
})
}
but if i want to use socket.io, what should i do? I'm very confused by socket.io docs, not showing for handeling things.
If you have idea about these things,
please answer me Thank you for your answer
Socket.io keeps its connections alive. In order to handle errors. You will need to listen to events. For example:
Handling connection errors:
socket.on("connect_error", (error) => {
// ...
});
Handling disconnect errors:
socket.on("disconnect", (reason) => {
if (reason === "io server disconnect") {
// the disconnection was initiated by the server, you need to reconnect manually
socket.connect();
}
// else the socket will automatically try to reconnect
});
If you'd like to ensure that your server side handled your request and need confirmation you can use the optional 'ack' feature like this:
// client side
socket.emit("ferret", "tobi", (data) => {
console.log(data); // data will be "woot"
});
// server side:
io.on("connection", (socket) => {
socket.on("ferret", (name, fn) => {
fn("woot");
});
});

Can you send a status code and a html web page?

I am using the express framework in node and I don't know what is best practice or if this is the wrong thing to do but I wanted to send a status code e.g. res.status(200).send("Success"); if the form input matches with the server and if it does not match then send something like res.status(403).send("Forbidden");
Then in the webpage I can update the paragraph element with the sent response. So the user knows if it has been successful or not.
Is this possible? If it is how do I do it? And is there a better way?
For sure it is possible!
Taken from the express api reference:
res.status(code)
Sets the HTTP status for the response. It is a chainable alias of Node’s response.statusCode.
res.status(403).end()
res.status(400).send('Bad Request')
res.status(404).sendFile('/absolute/path/to/404.png')
Generally sending status codes is the way to go. If you are sending data without a status code, express will add the 200 status code automatically, so you don't have to add it manually.
On the client side, you have to check for a non 2xx status code in your response object of your request. Here is an example using the fetch api.
fetch('/your/api')
.then((response) => {
if (!response.ok) { // Check for a non 2xx status code
throw new Error('Network response was not ok');
}
// Do something with the response data
})
.catch((error) => {
// This is only reached when a network error is encountered or CORS is misconfigured on the server-side
console.error('There has been a problem with your fetch operation:', error);
});
Example: Credentials Use Case
If you want to write a web page which has a form to enter user credentials to gain access to further content, I would suggest doing it the following way:
Client side:
// Function is listening to the submit event of your login form
function submitLoginForm() {
let username = document.getElementById("username").value;
let password = document.getElementById("password").value;
const options = {
method: 'POST',
body: JSON.stringify({ username, password }),
headers: {
'Content-Type': 'application/json'
}
};
return fetch('/api/login', options)
.then((response) => {
// Check for a non 2xx status code
if (!response.ok) {
// Show a failed login hint
showMessageBox('Login was not granted by the server. Please check you user name or password and try again.', 'error');
}
// Your login was successfull, manually redirect to user's dashboard, or whatever content...
})
.catch((error) => {
// This is only reached when a network error is encountered or CORS is misconfigured on the server-side
console.error('There has been a problem with your fetch operation:', error);
});
}
Server side:
app.post('/api/login', (req, res, next) => {
let username = req.body.username;
let password = req.body.password;
checkCredentials(username, password, (err) => {
if (err) {
return res.status(400).send('Wrong user name or password.');
}
// Consider adding a token or a cookie to the response object, so that the user keeps logged in.
return res.send('Access granted.');
});
});

Implement unread messages

I am implementing a live chat.
Here is my server file.
io.on('connection', socket => {
socket.on('userConnect', async (room, user_id) => {
socket.join(room);
});
socket.on('send-chat-message', (room, sender_id, userMessage) => {
const message = new Message(room, sender_id, userMessage);
db.query(message.saveMessage());
socket.to(room).emit('chat-message', { message: userMessage, user: sender_id });
});
});
This is how I implemented the connection to the room and the connection for sending messages from the client.
How can I make a function that the user has not yet read the message?

React Native Fetch Requests are not getting sent to my Node Js backend for some users

I've built a react native app that has a Node js backend. Users can sign In, sign up and view a profile page.
All my users can sign In but some of them can't view the profile page.
When I look at the request made to my backend, I get:
POST /UserRouter/SignIn 200 212.537 ms - 130342
Signing in works, it finds the user, returns the JWT token. When it's in the app no other requests are made. I get JSON Parse error: Unexpected EOF
Once you sign in, its supposed to immediately make a request to get your profile. With some accounts, this doesn't happen
My initial hypothesis of this problem is that the token for some users has expired, so they are not able to access protected routes. I use p***assport-jwt*** for my tokens. Hence, the backend not registering any requests.
Please find my code below:
_fetchData = () => {
AsyncStorage.getItem('jwt', (err, token) => {
fetch(`${backendUri }/UserRouter/Profile`, {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: token
}
})
.then((response) => response.json())
.then((json) => {
this.setState({name:json.name})
})
.catch((error) => {
console.log(error)
alert('There was an error ')
})
.done()
})
}
Here is my node JS code
app.get('/UserRouter/profile', passport.authenticate('jwt1', { session: false }), function (req, res) {
const token = req.headers.authorization
const decoded = jwt.decode(token.substring(4), config.secret)
User.findOne({
_id: decoded._id
},
function (err, user) {
if (err) throw err
res.json({ email: user.email, name: user.fName})
})
})
Thank you
This was the answer: https://stackoverflow.com/a/33617414/6542299
Turns out I was encoding my token with the users' document. the users' document was too large. so I just needed to reduce it

Why is post request not being received on rest api?

I wrote a rest api to handle all requests for my chat app, such as logging in, signing up, or sending a message. This works fine for my serverside code;however, I want logging in or signing up to send a request to the rest api instead. On the api, the request is never received from the client. I tried testing it basically in a similar way on a separate directly
I'm working on a chat app I started around a month ago
Code for server that handles logins:
app.route('/login').post(async (req, res) => {
console.log('login request')
var users = await serverController.listDocuments({
database:'chatbase',
collectionName:'users',
query:`{'username':'${req.body.usrnm}'}`
})
if(!users[0]) return res.send('Incorrect Credentials')
var user = new User(users[0])
var isCorrect = await bcrypt.compare(req.body.psw, user.password)
if(!isCorrect) return res.send('Incorrect Credentials')
res.send({token: user.token, username:user.username, id:user.id})
})
Code for client side:
let xhr = new XMLHttpRequest()
xhr.open("POST", 'https://api.domain.com')
xhr.setRequestHeader('Content-Type', "application/json");
xhr.onreadystatechange = () => {
if (xhr.status == 200) {
alert('Reqest succeeded');
}
alert(xhr.status)
}
xhr.send(JSON.stringify({
usrnm:'Example Username',
psw:'Example Password'
}))
Code for server(Works):
socket.on('login', credentials => {
var opt = {
uri:'https://message-api.glitch.me/login',
method:'POST',
body:credentials,
headers: {
'User-Agent': 'Request-Promise'
},
json:true
}
rp(opt)
.then(res => {
if(res == 'Incorrect Credentials') return socket.emit('loginFailed')
socket.emit('loginSuccess', res)
})
})
The serverside code receives creds from user and then forwards them to api. The server then receives either a token that the user can send messages using or it sends an incorrect login(Works). The api code simply routes various request types, such as creating servers or logging in(Works from serverside requests). The client side creates a reqyest and then sends it(Is never recieved)

Categories