Getting SignalR unauthorized error in ReactJS - reactjs

I have created signalR connection in my ReactJS application, whenever i load page for the first time then i get an error "Error: Failed to complete negotiation with the server: Error: Unauthorized" but when i reload the page again then it works fine i.e. it get connected properly.
I just want to connect the signalR connection properly when page load for the first time without the need to reload it again
Here is my code for signalR connection:
export default class Dashboard extends Component {
constructor(props) {
super(props)
this.state = {
signalRURL: 'https://****/?hub=broadcast',
accessToken: '',
alertData: {}
}
}
getURL = () => {
return new Promise((resolve, reject) => {
return axios({
url: 'https://*****/api/SignalRConnection',
method: "get",
headers: {
"content-type": "application/json",
"Access-Control-Allow-Origin": "*"
},
})
//Get the SignalR connection information which contains Url and Access token,
//by calling the SignalRConnection API.
.then(response => {
localStorage.setItem("access_key", response.data.accessToken)
console.log("response", response)
resolve(response);
})
.catch(error => {
reject(error);
});
});
}
componentDidMount = () => {
this.getURL().then(data => {
console.log("dataaa", data)
})
.catch(err => {
console.log("error", err)
})
//Create the Hub connection using SignalR.HubConnectionBuilder.
const options = {
accessTokenFactory: () => localStorage.getItem("access_key")
};
const hubConnection = new SignalR.HubConnectionBuilder()
.withUrl(this.state.signalRURL, options)
.configureLogging(SignalR.LogLevel.Information)
.build();
hubConnection.on('notify', data => {
this.setState({alertData: data})
console.log("state data",this.state.alertData)
console.log(data);
});
hubConnection
.start()
.catch(
error => console.error(error)
);
hubConnection.serverTimeoutInMilliseconds = 6000000;
hubConnection.keepAliveIntervalInMilliseconds = 3000000;
hubConnection.onclose((error) => {hubConnection.start();
console.error(`Something went wrong: ${error}`); });
}
render() {
return (
<div>
</div>
)
}
}
This is the error message i get everytime when i load the page for the first time

Related

Axios does not catch error even not enter in catch block

I am trying to get the error status code that would be 413 in Axios catch block. I have tried different solutions nothing worked for me. Could you please review what is going wrong.
uploadNewDatDocuments(datId, files = [], additionalInfo = {}) {
return new Promise((resolve, reject) => {
let url = new URL(this.baseUrl + this.uploadDocument.replace('{id}', datId));
Object.keys(additionalInfo).forEach(queryParam => url.searchParams.set(queryParam, additionalInfo[queryParam]));
let formData = new FormData();
files.forEach(file => formData.append('files', file));
axios
.post(url.toString(), formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(response => {
resolve(response.data);
})
.catch(error => {
console.log("error occurred")
reject(error);
}).finally(error=>{
console.log(error);
})
});
}
Here is my Action code.
export function uploadNewDocuments(datId, additionalInfo = {}, attachments = [], comment = {}) {
return dispatch => {
datService
.uploadNewDatDocuments(datId, attachments, additionalInfo)
.then(response => {
const attachmentsIds = response.map(attachment => attachment.id);
dispatch(
DatCommentActions.addDatNewComment(datId, {
...comment,
message: { ...comment.message, attachments: attachmentsIds }
})
);
})
.catch(error => {
dispatch(MessageActions.showMessage({ message: error.response.data.message }));
console.error(error);
});
};
}
413 Request Entity Too Large is not actually error, its a not successful response and catch wont fire unless there is actual error on response.
What you could do is check response.status and based on that and write own error handling.

React - Send cookie to Express

I am getting a token to access an API endpoint and I want to send this token to my server-side app (expressJS) to retreive the data.
I have the following for my react app:
export default class Account extends React.Component {
constructor() {
super();
this.state = {
token: null,
response: {
}
};
this.getCurrentlyPlaying = this.getCurrentlyPlaying.bind(this);
}
componentDidMount() {
// Set token
let _token = hash.access_token;
if (_token) {
this.setState({
token: _token
});
const cookies = new Cookies();
cookies.set('token', _token, { path: '/' });
console.log(cookies.get('token'));
this.getCurrentlyPlaying(_token);
}
}
getCurrentlyPlaying() {
fetch(`http://localhost:3001/account`)
.then(res => res.json())
.then(data => {
this.setState ({
response: data
})
console.log(data);
});
}
render() {
if (this.state.response[0].is_playing === true) {
return (
<p> Something is playing</p>
);
}
else {
return (
<p> Nothing is playing</p>
);
}
}
}
In my express app, I have the cookie being gotten but I'm not sure if it actually is getting the cookie created by the react app:
router.get('/account', (req, res) => {
const config = {
headers: {
'Authorization': `Bearer ${req.session.token}`
}
};
fetch(`${CONFIG.spotifyUrl}/me/player/currently-playing `, config)
.then(html => html.json())
.then(json => {
res.json(json);
});
});
module.exports = router;
Can someone tell me where I'm going wrong please?
To parse cookies in backend with express, a good choice is to use the https://github.com/expressjs/cookie-parser middleware.
Provided you are using setup something similar to below
const cookieParser = require('cookie-parser');
app.use(cookieParser());
Every Request object on server will have cookies information in the req.cookies property. So in your case it should be req.cookies.token

Generic function to request api with Axios

I am trying to build a generic function for my endpoints, using Axios and React. Generic because I have always the same header and I do not want to repeat a lot of code for each of my components.
To do that, I built this function (sorry, a lot of comments that I will remove after of course) :
export const getRequest = ( endpoint ) => axios
.get( env._URL_SERVER_ + endpoint, { headers: getHeaders() } )
.then((res) => {
// Success
console.log(res);
return {error: false, response: res.data};
})
.catch((error) => {
// Error
if (error.response) {
/*
* The request was made and the server responded with a
* status code that falls out of the range of 2xx
*/
console.log(error.response.data);
console.log(error.response.status);
return {error: true, status: error.response.status, data: error.response.data};
} else if (error.request) {
/*
* The request was made but no response was received, `error.request`
* is an instance of XMLHttpRequest in the browser and an instance
* of http.ClientRequest in Node.js
*/
console.log(error.request);
return {error: true, data: error.request };
} else {
// Something happened in setting up the request and triggered an Error
console.log('Error', error.message);
return {error: true, data: error.message}
}
});
Ant then in my components I do that :
getSchools = () => {
this.setState({
loadingSchools: true
}, () => {
getRequest(`/schools?name=${this.state.filterByName}&city=${this.state.filterByCity}&school_type_id=${this.state.filterBySchoolTypeId}&page=${this.state.selectedPage}`)
.then((response) => {
// there is an error
if (!response.error) {
this.setState({
schools: response.response.data,
meta: response.response.meta,
links: response.response.links
})
} else {
this.setState({
error: true,
errorMessage: response.data,
})
}
})
.then(() => {
this.setState({loadingSchools : false});
})
})
}
It works fine. I tested it in several situation (all is OK - 200, not found - 404, no response). But is it a good practice ? I feel that there is a lot of codes in the parent component. Maybe I complicate my life?
Here is how I've done it:
var URL_BACKEND = "http://localhost:5000/";
// Create Function to handle requests from the backend
callToBackend = async (ENDPOINT, METHOD) => {
const options = {
url: `${URL_BACKEND}${ENDPOINT}`,
method: METHOD,
headers: {
Accept: "application/json",
"Content-Type": "application/json;charset=UTF-8",
},
};
const response = await axios(options);
return response.data;
}
// Then you make a call with the exact endpoint and method:
const response = await this.callToBackend('createSetupIntent', 'POST');
console.log(JSON.stringify(response));
create one common file for base URL let's say api.js
// api.js file code
export const apiUrl = axios.create({
baseURL: 'http://localhost:5000',
});
Register file
// register.js file code
import { apiUrl } from './api';
try {
const resp = await apiUrl.post('/api/register', {
username,
email,
password,
});
const { data, status } = resp;
if (Object.keys(data).length && status === 200) {
// received api data successfully
console.log('API response', data);
}
} catch (err) {
console.log(err);
}
// For auth request
try {
const token = localstorage.getItem('token');
const res = await apiUrl.post(
'/authroute',
{
name: fullName,
originCountry: country,
career: careerStatus,
},
{
headers: { Authorization: `Bearer ${token}` },
}
);
const { data, status } = strapiRes;
if (Object.keys(data).length && status === 200) {
return res.status(status).json(data);
}
} catch (error) {
throw new Error(error);
}
// same for all request
apiUrl.get(endpoint);
apiUrl.post(endpoint, body);
apiUrl.put(endpoint, body);
apiUrl.delete(endpoint, body);

Initial fetch get request slow using React, Express

In a simple react set up with express, the very first fetch get request is too slow. The get requests following it seem normal speed.See the first /api/passages/happiness in the log below with a time of 33+ milliseconds.
Basic order of operations:
button click triggers GET request from local Express server
sets state with the data
calls an external API through a proxy url
displays that data in a modal
I'm new at speed/performance issues. Where do I begin troubleshooting? Or which step is likely slowing it down?
// onClick of button, these steps occur:
handleOpen = () => {
// 1. call express api, returns a few lines of text
baseService.get(`/api/passages/${this.props.document}`)
.then(data => {
this.setState({
reference: data.reference,
abbr: data.abbr,
start: data.start,
end: data.end
})
})
.catch(err => {
alert("Verse failed to load")
console.log(err)
})
// 2. call external api, returns a few lines of text
.then(() => {
const url = `https://bibles.org/v2/chapters/eng-NASB:${this.state.abbr}/verses.js?start=${this.state.start}&end=${this.state.end}`
fetch(proxyurl + url, {
headers: new Headers({ 'Authorization': 'Basic ' + window.btoa(`${BIBLE_API_KEY}: x`) }),
redirect: "follow",
})
.then(res => res.json())
.then(contents => {
let versearray = contents.response.verses
versearray.forEach(verse => {
var regex = /(<([^>]+)>)|[0-9]/ig;
let versetext = verse.text.replace(regex, "");
let alltext = this.state.content.concat(' ', versetext)
this.setState({
content: alltext,
// 3. open modal displaying few lines of text
open: true
})
})
})
})
.catch(err => {
alert("Your Verse Failed to Load");
console.log(err)
})
};
config
let mongoose = require('mongoose');
const server = '127.0.0.1:27017'
const database = 'verseapp';
class Database {
constructor() {
this._connect()
}
_connect() {
mongoose.connect(`mongodb://${server}/${database}`, {
useNewUrlParser: true,
useCreateIndex: true,
})
.then(() => {
console.log('Database connection successful')
})
.catch(err => {
console.log('Database connection error', err)
})
}
}
module.exports = new Database()

React Native - Undefined is not an object when evaluating promise

i am beginner react-native programmer . I am trying to return the responseJSON in a fetch function . I know it is asynchronous and will return promise, thus I need to use .then() , but when it says undefined is not an object.
here is the code
auth.js
export const onVerify = (email,password,navigation) => {
console.log('Verifying');
fetch('xxx',
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'email=' + email + '&password=' + password
})
.then((response) => response.json())
.then((responseJson) => {
if(responseJson.status == '200') {
Alert.alert(
'Login Successful',
'Welcome Home'
);
let data = {
name: responseJson.name,
id : responseJson.id
};
onSignIn();
return responseJson
}
in my signin.js
export default class SignIn extends React.Component{
step(){
onVerify(this.state.email,this.state.password,this.props.navigation).then(
function(data) {
console.log(data);
}
);
}
As said by #teivaz on the comment, your onVerify function returns nothing. Because the fetch call is asynchronous. So what you can do is return a Promise from onVerify then you'll be able to resolve it from step function.
This is how you can implement this,
export const onVerify = (email,password,navigation) => {
return new Promise((resolve, reject) => {
fetch('endpoint',
{
method,
headers,
body,
})
.then((response) => response.json())
.then((responseJson) => {
if(responseJson.status == '200') {
Alert.alert(
'Login Successful',
'Welcome Home'
);
let data = {
name: responseJson.name,
id : responseJson.id
};
onSignIn();
resolve(responseJson)
}
})
.catch(err => reject(err));
}
}
Also, make sure to catch the errors if any in step function.
export default class SignIn extends React.Component{
step(){
onVerify(this.state.email,this.state.password,this.props.navigation).then(
function(data) {
console.log(data);
}
)
.catch(err => console.log('Error occured', err));
}
}

Resources